qtmobility/src/contacts/qcontactdetail.cpp
changeset 4 90517678cc4f
parent 1 2b40d63a9c3d
child 5 453da2cfceef
--- a/qtmobility/src/contacts/qcontactdetail.cpp	Fri Apr 16 15:51:22 2010 +0300
+++ b/qtmobility/src/contacts/qcontactdetail.cpp	Mon May 03 13:18:40 2010 +0300
@@ -42,6 +42,7 @@
 #include "qcontactdetail.h"
 #include "qcontactdetail_p.h"
 #include "qcontactmanager.h"
+#include <QDebug>
 
 QTM_BEGIN_NAMESPACE
 
@@ -49,17 +50,52 @@
 QAtomicInt QContactDetailPrivate::lastDetailKey(1);
 
 /* Definitions of predefined string constants */
-Q_DEFINE_LATIN1_LITERAL(QContactDetail::FieldDetailUri, "DetailUri");
-Q_DEFINE_LATIN1_LITERAL(QContactDetail::FieldLinkedDetailUris, "LinkedDetailUris");
-Q_DEFINE_LATIN1_LITERAL(QContactDetail::FieldContext, "Context");
-Q_DEFINE_LATIN1_LITERAL(QContactDetail::ContextOther, "Other");
-Q_DEFINE_LATIN1_LITERAL(QContactDetail::ContextHome, "Home");
-Q_DEFINE_LATIN1_LITERAL(QContactDetail::ContextWork, "Work");
+Q_DEFINE_LATIN1_CONSTANT(QContactDetail::FieldDetailUri, "DetailUri");
+Q_DEFINE_LATIN1_CONSTANT(QContactDetail::FieldLinkedDetailUris, "LinkedDetailUris");
+Q_DEFINE_LATIN1_CONSTANT(QContactDetail::FieldContext, "Context");
+Q_DEFINE_LATIN1_CONSTANT(QContactDetail::ContextOther, "Other");
+Q_DEFINE_LATIN1_CONSTANT(QContactDetail::ContextHome, "Home");
+Q_DEFINE_LATIN1_CONSTANT(QContactDetail::ContextWork, "Work");
+
+static uint qHash(const QContactStringHolder& holder)
+{
+    if (!holder.m_str)
+        return 0;
+    uint h = 0;
+    uint g;
+    const register uchar*p = (const uchar*)holder.m_str;
+
+    while (*p) {
+        h = (h << 4) + *p++;
+        if ((g = (h & 0xf0000000)) != 0)
+            h ^= g >> 23;
+        h &= ~g;
+    }
+    return h;
+}
+
+/* Storage */
+QHash<QString, char*> QContactStringHolder::s_allocated;
+QHash<const char *, QString> QContactStringHolder::s_qstrings;
+
+/* Dtor function */
+static int qClearAllocatedStringHash()
+{
+    QHash<QString, char*>::const_iterator it = QContactStringHolder::s_allocated.constBegin();
+    while (it != QContactStringHolder::s_allocated.constEnd()) {
+        delete[] it.value();
+        it++;
+    }
+    QContactStringHolder::s_allocated.clear();
+    QContactStringHolder::s_qstrings.clear();
+    return 1;
+}
+Q_DESTRUCTOR_FUNCTION(qClearAllocatedStringHash);
 
 /*!
   \class QContactDetail
  
-  \brief The QContactDetail class provides access to a single, complete detail about a contact.
+  \brief The QContactDetail class represents a single, complete detail about a contact.
   \ingroup contacts-main
  
   All of the information for a contact is stored in one or more QContactDetail objects.
@@ -158,8 +194,18 @@
 {
 }
 
+/*!
+    Constructs a new, empty detail of the definition identified by \a thisDefinitionId.
+    The definitionId must be restricted to the Latin 1 character set.
+ */
+QContactDetail::QContactDetail(const QString& thisDefinitionId)
+    : d(new QContactDetailPrivate)
+{
+    d->m_definitionName = thisDefinitionId;
+}
+
 /*! Constructs a new, empty detail of the definition identified by \a thisDefinitionId */
-QContactDetail::QContactDetail(const QString& thisDefinitionId)
+QContactDetail::QContactDetail(const char* thisDefinitionId)
     : d(new QContactDetailPrivate)
 {
     d->m_definitionName = thisDefinitionId;
@@ -171,10 +217,29 @@
 {
 }
 
-/*! Constructs a detail that is a copy of \a other if \a other is of the expected definition identified by \a expectedDefinitionId, else constructs a new, empty detail of the definition identified by the \a expectedDefinitionId */
+/*!
+    Constructs a detail that is a copy of \a other if \a other is of the expected definition
+    identified by \a expectedDefinitionId, else constructs a new, empty detail of the
+    definition identified by the \a expectedDefinitionId
+*/
+QContactDetail::QContactDetail(const QContactDetail& other, const char* expectedDefinitionId)
+{
+    if (other.d->m_definitionName == expectedDefinitionId) {
+        d = other.d;
+    } else {
+        d = new QContactDetailPrivate;
+        d->m_definitionName = expectedDefinitionId;
+    }
+}
+
+/*!
+    Constructs a detail that is a copy of \a other if \a other is of the expected definition
+    identified by \a expectedDefinitionId, else constructs a new, empty detail of the
+    definition identified by the \a expectedDefinitionId
+*/
 QContactDetail::QContactDetail(const QContactDetail& other, const QString& expectedDefinitionId)
 {
-    if (other.definitionName() == expectedDefinitionId) {
+    if (other.d->m_definitionName == expectedDefinitionId) {
         d = other.d;
     } else {
         d = new QContactDetailPrivate;
@@ -190,11 +255,33 @@
     return *this;
 }
 
-/*! Assigns this detail to \a other if the definition of \a other is that identified by the given \a expectedDefinitionId, else assigns this detail to be a new, empty detail of the definition identified by the given \a expectedDefinitionId */
+/*!
+    Assigns this detail to \a other if the definition of \a other is that identified
+    by the given \a expectedDefinitionId, else assigns this detail to be a new, empty
+    detail of the definition identified by the given \a expectedDefinitionId
+*/
+QContactDetail& QContactDetail::assign(const QContactDetail& other, const char* expectedDefinitionId)
+{
+    if (this != &other) {
+        if (other.d->m_definitionName == expectedDefinitionId) {
+            d = other.d;
+        } else {
+            d = new QContactDetailPrivate;
+            d->m_definitionName = expectedDefinitionId;
+        }
+    }
+    return *this;
+}
+
+/*!
+    Assigns this detail to \a other if the definition of \a other is that identified
+    by the given \a expectedDefinitionId, else assigns this detail to be a new, empty
+    detail of the definition identified by the given \a expectedDefinitionId
+*/
 QContactDetail& QContactDetail::assign(const QContactDetail& other, const QString& expectedDefinitionId)
 {
     if (this != &other) {
-        if (other.definitionName() == expectedDefinitionId) {
+        if (other.d->m_definitionName == expectedDefinitionId) {
             d = other.d;
         } else {
             d = new QContactDetailPrivate;
@@ -220,7 +307,7 @@
     be compared according to their values. */
 bool QContactDetail::operator==(const QContactDetail& other) const
 {
-    if (d.constData()->m_definitionName != other.d.constData()->m_definitionName)
+    if (! (d.constData()->m_definitionName == other.d.constData()->m_definitionName))
         return false;
 
     if (d.constData()->m_access != other.d.constData()->m_access)
@@ -232,17 +319,34 @@
     return true;
 }
 
-/*! Sets the preferred actions for this detail to be the given list of \a preferredActions */
-void QContactDetail::setPreferredActions(const QList<QContactActionDescriptor>& preferredActions)
+/*! Returns the hash value for \a key. */
+uint qHash(const QContactDetail &key)
 {
-    d->m_preferredActions = preferredActions;
+    const QContactDetailPrivate* dptr= QContactDetailPrivate::detailPrivate(key);
+    uint hash = QT_PREPEND_NAMESPACE(qHash)(dptr->m_definitionName)
+                + QT_PREPEND_NAMESPACE(qHash)(dptr->m_access);
+    QHash<QContactStringHolder, QVariant>::const_iterator it = dptr->m_values.constBegin();
+    while(it != dptr->m_values.constEnd()) {
+        hash += QT_PREPEND_NAMESPACE(qHash)(it.key())
+                + QT_PREPEND_NAMESPACE(qHash)(it.value().toString());
+        ++it;
+    }
+    return hash;
 }
 
-/*! Returns the list of preferred actions for this detail */
-QList<QContactActionDescriptor> QContactDetail::preferredActions() const
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const QContactDetail& detail)
 {
-    return d->m_preferredActions;
+    dbg.nospace() << "QContactDetail(name=" << detail.definitionName() << ", key=" << detail.key();
+    QVariantMap fields = detail.variantValues();
+    QVariantMap::const_iterator it;
+    for (it = fields.constBegin(); it != fields.constEnd(); ++it) {
+        dbg.nospace() << ", " << it.key() << '=' << it.value();
+    }
+    dbg.nospace() << ')';
+    return dbg.maybeSpace();
 }
+#endif
 
 /*! Returns true if no values are contained in this detail.  Note that context is stored as a value; hence, if a context is set, this function will return false. */
 bool QContactDetail::isEmpty() const
@@ -271,9 +375,16 @@
   no value for the given \a key exists */
 QString QContactDetail::value(const QString& key) const
 {
-    if (d.constData()->m_values.contains(key))
-        return d.constData()->m_values.value(key).toString();
-    return QString();
+    return d.constData()->m_values.value(key.toLatin1().constData()).toString();
+}
+
+
+/*! \overload
+  Returns the value stored in this detail for the given \a key as a QString, or an empty QString if
+  no value for the given \a key exists */
+QString QContactDetail::value(const char* key) const
+{
+    return d.constData()->m_values.value(key).toString();
 }
 
 // A bug in qdoc means this comment needs to appear below the comment for the other value().
@@ -285,9 +396,13 @@
 /*! Returns the value stored in this detail for the given \a key as a QVariant, or an invalid QVariant if no value for the given \a key exists */
 QVariant QContactDetail::variantValue(const QString& key) const
 {
-    if (d.constData()->m_values.contains(key))
-        return d.constData()->m_values.value(key);
-    return QVariant(); // returns an invalid qvariant
+    return d.constData()->m_values.value(key.toLatin1().constData());
+}
+
+/*! Returns the value stored in this detail for the given \a key as a QVariant, or an invalid QVariant if no value for the given \a key exists */
+QVariant QContactDetail::variantValue(const char* key) const
+{
+    return d.constData()->m_values.value(key);
 }
 
 /*!
@@ -295,9 +410,15 @@
  */
 bool QContactDetail::hasValue(const QString& key) const
 {
-    if (d.constData()->m_values.contains(key))
-        return true;
-    return false;
+    return d.constData()->m_values.contains(key.toLatin1().constData());
+}
+
+/*!
+  Returns true if this detail has a field with the given \a key, or false otherwise.
+ */
+bool QContactDetail::hasValue(const char * key) const
+{
+    return d.constData()->m_values.contains(key);
 }
 
 /*! Inserts \a value into the detail for the given \a key if \a value is valid.  If \a value is invalid,
@@ -309,6 +430,19 @@
     if (!value.isValid())
         return removeValue(key);
 
+    d->m_values.insert(QContactStringHolder(key), value);
+    return true;
+}
+
+/*! Inserts \a value into the detail for the given \a key if \a value is valid.  If \a value is invalid,
+    removes the field with the given \a key from the detail.  Returns true if the given \a value was set
+    for the \a key (if the \a value was valid), or if the given \a key was removed from detail (if the
+    \a value was invalid), and returns false if the key was unable to be removed (and the \a value was invalid) */
+bool QContactDetail::setValue(const char* key, const QVariant& value)
+{
+    if (!value.isValid())
+        return removeValue(key);
+
     d->m_values.insert(key, value);
     return true;
 }
@@ -316,6 +450,13 @@
 /*! Removes the value stored in this detail for the given \a key.  Returns true if a value was stored for the given \a key and the operation succeeded, and false otherwise */
 bool QContactDetail::removeValue(const QString& key)
 {
+    if(d->m_values.remove(key.toLatin1().constData()))
+        return true;
+    return false;
+}
+/*! Removes the value stored in this detail for the given \a key.  Returns true if a value was stored for the given \a key and the operation succeeded, and false otherwise */
+bool QContactDetail::removeValue(const char * key)
+{
     if(d->m_values.remove(key))
         return true;
     return false;
@@ -326,7 +467,14 @@
  */
 QVariantMap QContactDetail::variantValues() const
 {
-    return d.constData()->m_values;
+    QVariantMap ret;
+    QHash<QContactStringHolder, QVariant>::const_iterator it = d.constData()->m_values.constBegin();
+    while(it != d.constData()->m_values.constEnd()) {
+        ret.insert(it.key(), it.value());
+        ++it;
+    }
+
+    return ret;
 }
 
 /*!