src/contacts/qcontact.cpp
changeset 0 876b1a06bc25
child 5 603d3f8b6302
equal deleted inserted replaced
-1:000000000000 0:876b1a06bc25
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the Qt Mobility Components.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include <QSet>
       
    43 #include <QDebug>
       
    44 
       
    45 #include "qcontact.h"
       
    46 #include "qcontact_p.h"
       
    47 #include "qcontactdetail_p.h"
       
    48 #include "qcontactmanager_p.h"
       
    49 #include "qcontactaction.h"
       
    50 
       
    51 QTM_BEGIN_NAMESPACE
       
    52 
       
    53 /*!
       
    54   \class QContact
       
    55  
       
    56   \brief The QContact class represents an addressbook contact.
       
    57 
       
    58   \ingroup contacts-main
       
    59 
       
    60   Individual contacts, groups, and other types of contacts are represented with
       
    61   a QContact object.  In addition to the type, a QContact consists of information
       
    62   that belongs to the contact, some information about the relationships that the
       
    63   contact has, and the preferred ways to interact with the contact.
       
    64 
       
    65   A QContact object has a collection of details (like a name, phone numbers and
       
    66   email addresses).  Each detail (which can have multiple fields) is stored
       
    67   in an appropriate subclass of QContactDetail, and the QContact allows
       
    68   retrieving these details in various ways.
       
    69 
       
    70   Depending on the details of the QContact, certain actions are available for a
       
    71   contact.  An instance of a QContact can return a list of actions that can be
       
    72   performed on it, and a list of details supported by a specific action can be
       
    73   retrieved (for example - a list of phone numbers supported by a specific "Call" action).
       
    74   It is also possible to store one detail for each type of action that is the "preferred"
       
    75   detail to use.
       
    76 
       
    77   A QContact may have zero or more relationships with other contacts.  For example,
       
    78   a group contact would have a \c "HasMember" relationship with the QContacts that
       
    79   are its members.  Spouses, managers and assistants can also be represented this
       
    80   way.
       
    81  
       
    82   A QContact instance represents the in-memory version of an addressbook contact,
       
    83   and has no tie to a specific QContactManager.  It is possible for the contents
       
    84   of a QContact to change independently of the contents that are stored persistently
       
    85   in a QContactManager.  A QContact has an ID associated with it when it is first
       
    86   retrieved from a QContactManager, or after it has been first saved, and this allows
       
    87   clients to track changes using the signals in QContactManager.
       
    88 
       
    89   A QContact has a number of mandatory details:
       
    90   \list
       
    91    \o A QContactType, with the type of the contact (individual contact, group etc)
       
    92    \o A QContactDisplayLabel, representing the text to display
       
    93   \endlist
       
    94 
       
    95   If you have edited the contents of a QContact (via saving or removing details),
       
    96   you will need to ask a specific QContactManager for the new display label for the
       
    97   contact, since system settings (like the order of first or last names) can vary
       
    98   between managers.
       
    99  
       
   100   \sa QContactManager, QContactDetail
       
   101  */
       
   102 
       
   103 /*!
       
   104  * \fn QList<T> QContact::details() const
       
   105  * Returns a list of details of the template parameter type.  The type must be
       
   106  * a subclass of QContactDetail.
       
   107  *
       
   108  * For example:
       
   109  *  \snippet doc/src/snippets/qtcontactsdocsample/qtcontactsdocsample.cpp 3
       
   110  */
       
   111 
       
   112 /*!
       
   113  * \fn QList<T> QContact::details(const QString& fieldName, const QString& value) const
       
   114  * Returns a list of details of the template parameter type which have field called \a fieldName, with matching \a value.
       
   115  * The type must be a subclass of QContactDetail.
       
   116  *
       
   117  * For example:
       
   118  *  \snippet doc/src/snippets/qtcontactsdocsample/qtcontactsdocsample.cpp 4
       
   119  */
       
   120 
       
   121 /*!
       
   122  * \fn T QContact::detail() const
       
   123  * Returns the first detail of the template parameter type, as returned by the template details() function.
       
   124  * The type must be a subclass of QContactDetail.
       
   125  */
       
   126 
       
   127 /*!
       
   128  * \fn QContact::operator!=(const QContact &other) const
       
   129  * Returns true if this contacts id or details are different to those of the \a other contact.
       
   130  */
       
   131 
       
   132 /*!
       
   133     Construct an empty contact.
       
   134 
       
   135     The contact will have an empty display label, an empty id, and have type \l QContactType::TypeContact.
       
   136     The isEmpty() function will return true.
       
   137 */
       
   138 QContact::QContact()
       
   139     : d(new QContactData)
       
   140 {
       
   141     clearDetails();
       
   142 }
       
   143 
       
   144 /*! Initializes this QContact from \a other */
       
   145 QContact::QContact(const QContact& other)
       
   146     : d(other.d)
       
   147 {
       
   148 }
       
   149 
       
   150 /*!
       
   151  * Returns true if this QContact is empty, false if not.
       
   152  *
       
   153  * An empty QContact has an empty label and no extra details.
       
   154  * The type of the contact is irrelevant.
       
   155  */
       
   156 bool QContact::isEmpty() const
       
   157 {
       
   158     /* Every contact has a display label field.. */
       
   159     if (d->m_details.count() > 2)
       
   160         return false;
       
   161 
       
   162     /* We know we have two details (a display label and a type) */
       
   163     const QContactDisplayLabel& label = d->m_details.at(0);
       
   164     return label.label().isEmpty();
       
   165 }
       
   166 
       
   167 /*!
       
   168  * Removes all details of the contact.
       
   169  * This function does not modify the id or type of the contact.
       
   170  * Calling isEmpty() after calling this function will return true.
       
   171  */
       
   172 void QContact::clearDetails()
       
   173 {
       
   174     d->m_details.clear();
       
   175 
       
   176     // insert the contact's display label detail.
       
   177     QContactDisplayLabel contactLabel;
       
   178     contactLabel.setValue(QContactDisplayLabel::FieldLabel, QString());
       
   179     contactLabel.d->m_access = QContactDetail::Irremovable | QContactDetail::ReadOnly;
       
   180     d->m_details.insert(0, contactLabel);
       
   181 
       
   182     // and the contact type detail.
       
   183     QContactType contactType;
       
   184     contactType.setType(QContactType::TypeContact);
       
   185     contactType.d->m_access = QContactDetail::Irremovable;
       
   186     d->m_details.insert(1, contactType);
       
   187 }
       
   188 
       
   189 /*! Replace the contents of this QContact with \a other */
       
   190 QContact& QContact::operator=(const QContact& other)
       
   191 {
       
   192     d = other.d;
       
   193     return *this;
       
   194 }
       
   195 
       
   196 /*! Frees the memory used by this QContact */
       
   197 QContact::~QContact()
       
   198 {
       
   199 }
       
   200 
       
   201 /*!
       
   202     Returns the QContactId that identifies this contact.
       
   203 
       
   204     This may have been set when the contact was retrieved from
       
   205     a particular manager, or when the contact was first saved
       
   206     in a manager.  The QContactId is only valid with a specific
       
   207     manager.  See \l QContactManager::saveContact() for more
       
   208     information.
       
   209 
       
   210     \sa localId()
       
   211  */
       
   212 QContactId QContact::id() const
       
   213 {
       
   214     return d->m_id;
       
   215 }
       
   216 
       
   217 /*!
       
   218     Returns the QContactLocalId that identifies this contact within its manager
       
   219 
       
   220     This may have been set when the contact was retrieved from
       
   221     a particular manager, or when the contact was first saved
       
   222     in a manager.  The QContactLocalId is associated with a specific
       
   223     manager, but other contacts with the same local id might exist in
       
   224     different managers.
       
   225 
       
   226     See \l QContactManager::saveContact() for more
       
   227     information.
       
   228 
       
   229    \sa id()
       
   230 */
       
   231 QContactLocalId QContact::localId() const
       
   232 {
       
   233     return d->m_id.localId();
       
   234 }
       
   235 
       
   236 /*!
       
   237  * Returns the type of the contact.  Every contact has exactly one type which
       
   238  * is either set manually (by saving a modified copy of the QContactType
       
   239  * in the contact, or by calling \l setType()) or synthesized automatically.
       
   240  *
       
   241  * \sa setType()
       
   242  */
       
   243 QString QContact::type() const
       
   244 {
       
   245     // type is detail 1
       
   246     QString type = d->m_details.at(1).value(QContactType::FieldType);
       
   247     if (type.isEmpty())
       
   248         return QString(QLatin1String(QContactType::TypeContact));
       
   249     return type;
       
   250 }
       
   251 
       
   252 /*!
       
   253  * Sets the type of the contact to the given \a type.
       
   254  */
       
   255 void QContact::setType(const QString& type)
       
   256 {
       
   257     // type is detail 1
       
   258     QContactType newType;
       
   259     newType.setType(type);
       
   260     newType.d->m_access = QContactDetail::Irremovable;
       
   261 
       
   262     d->m_details[1] = newType;
       
   263 }
       
   264 
       
   265 /*!
       
   266  * Sets the type of the contact to the given \a type detail.
       
   267  */
       
   268 void QContact::setType(const QContactType& type)
       
   269 {
       
   270     // type is detail 1
       
   271     d->m_details[1] = type;
       
   272     d->m_details[1].d->m_access = QContactDetail::Irremovable;
       
   273 }
       
   274 
       
   275 /*!
       
   276  * Returns the display label of this contact.
       
   277  *
       
   278  * A contact which has been retrieved from a manager will have a display label set when
       
   279  * the contact is retrieved.
       
   280  *
       
   281  * The display label is usually read-only, since some managers do not support arbitrary
       
   282  * labels (see also \l QContactName::setCustomLabel()).  If you modify the contact in a way
       
   283  * that would affect the display label, you can call QContactManager::synthesizeContactDisplayLabel() to get an
       
   284  * up-to-date display label.
       
   285  *
       
   286  * See the following example for more information:
       
   287  * \snippet doc/src/snippets/qtcontactsdocsample/qtcontactsdocsample.cpp Updating the display label of a contact
       
   288  *
       
   289  * \sa QContactManager::synthesizeContactDisplayLabel()
       
   290  */
       
   291 QString QContact::displayLabel() const
       
   292 {
       
   293     return d->m_details.at(0).value(QContactDisplayLabel::FieldLabel);
       
   294 }
       
   295 
       
   296 /*!
       
   297  * Sets the id of this contact to \a id.
       
   298  *
       
   299  * Note that this only affects this object, not any corresponding structures stored
       
   300  * by a QContactManager.
       
   301  *
       
   302  * If you change the id of a contact and save the contact
       
   303  * in a manager, the previously existing contact will still
       
   304  * exist.  You can do this to create copies (possibly modified)
       
   305  * of an existing contact, or to save a contact in a different manager.
       
   306  *
       
   307  * \sa QContactManager::saveContact()
       
   308  */
       
   309 void QContact::setId(const QContactId& id)
       
   310 {
       
   311     d->m_id = id;
       
   312 }
       
   313 
       
   314 /*!
       
   315     \fn QContactDetail QContact::detail(const QLatin1Constant& definitionName) const
       
   316     Returns the first detail stored in the contact which with the given \a definitionName.
       
   317     The \a definitionName argument is typically the detail name constant provided by a
       
   318     specific subclass of QContactDetail.  For example:
       
   319 
       
   320     \snippet doc/src/snippets/qtcontactsdocsample/qtcontactsdocsample.cpp 0
       
   321 
       
   322     It would usually be more convenient to use the template version of this function, in
       
   323     the following manner:
       
   324 
       
   325     \snippet doc/src/snippets/qtcontactsdocsample/qtcontactsdocsample.cpp 1
       
   326 */
       
   327 
       
   328 /*!
       
   329     \fn QList<QContactDetail> QContact::details(const QLatin1Constant& definitionName) const
       
   330     Returns a list of details of the given \a definitionName.
       
   331 
       
   332     The \a definitionName argument is typically the detail name constant provided by a
       
   333     specific subclass of QContactDetail.  For example:
       
   334 
       
   335     \snippet doc/src/snippets/qtcontactsdocsample/qtcontactsdocsample.cpp 2
       
   336 
       
   337     It would usually be more convenient to use the template version of this function, in
       
   338     the following manner:
       
   339 
       
   340     \snippet doc/src/snippets/qtcontactsdocsample/qtcontactsdocsample.cpp 3
       
   341 */
       
   342 
       
   343 /*!
       
   344     \fn QList<QContactDetail> QContact::details(const QLatin1Constant& definitionName, const QLatin1Constant& fieldName, const QString& value)
       
   345     Returns a list of details of the given \a definitionName, with fields named \a fieldName and with value \a value.
       
   346 */
       
   347 
       
   348 /*!
       
   349     \fn QList<T> QContact::details(const char* fieldName, const QString& value) const
       
   350     \internal
       
   351 
       
   352     Returns a list of details of the template type which match the \a fieldName and \a value criteria
       
   353 */
       
   354 
       
   355 /*!
       
   356     Returns the first detail stored in the contact with the given \a definitionName
       
   357 */
       
   358 QContactDetail QContact::detail(const QString& definitionName) const
       
   359 {
       
   360     if (definitionName.isEmpty())
       
   361         return d->m_details.first();
       
   362 
       
   363     // build the sub-list of matching details.
       
   364     for (int i = 0; i < d->m_details.size(); i++) {
       
   365         const QContactDetail& existing = d->m_details.at(i);
       
   366         if (QContactDetailPrivate::detailPrivate(existing)->m_definitionName == definitionName) {
       
   367             return existing;
       
   368         }
       
   369     }
       
   370 
       
   371     return QContactDetail();
       
   372 }
       
   373 
       
   374 /*! Returns a list of details with the given \a definitionName
       
   375     The definitionName string can be determined by the DefinitionName attribute
       
   376     of defined objects (e.g. QContactPhoneNumber::DefinitionName) or by
       
   377     requesting a list of all the definitions synchronously with
       
   378     \l {QContactManager::detailDefinitions()}{detailDefinitions()} or
       
   379     asynchronously with a
       
   380     \l {QContactDetailDefinitionFetchRequest}{detail definition fetch request},
       
   381     and then inspecting the
       
   382     \l{QContactDetailDefinition::name()}{name()} of each
       
   383     definition.  If \a definitionName is empty, all details of any definition
       
   384     will be returned.
       
   385  */
       
   386 QList<QContactDetail> QContact::details(const QString& definitionName) const
       
   387 {
       
   388     // build the sub-list of matching details.
       
   389     QList<QContactDetail> sublist;
       
   390 
       
   391     // special case
       
   392     if (definitionName.isEmpty()) {
       
   393         sublist = d->m_details;
       
   394     } else {
       
   395         for (int i = 0; i < d->m_details.size(); i++) {
       
   396             const QContactDetail& existing = d->m_details.at(i);
       
   397             if (QContactDetailPrivate::detailPrivate(existing)->m_definitionName == definitionName) {
       
   398                 sublist.append(existing);
       
   399             }
       
   400         }
       
   401     }
       
   402 
       
   403     return sublist;
       
   404 }
       
   405 
       
   406 /*!
       
   407     Returns a list of details of the given \a definitionName, with fields named \a fieldName and with value \a value.
       
   408     The definitionName string can be determined by the DefinitionName attribute
       
   409     of defined objects (e.g. QContactPhoneNumber::DefinitionName) or by
       
   410     requesting a list of all the definitions synchronously with
       
   411     \l {QContactManager::detailDefinitions()}{detailDefinitions()} or
       
   412     asynchronously with a
       
   413     \l {QContactDetailDefinitionFetchRequest}{detail definition fetch request},
       
   414     and then inspecting the
       
   415     \l{QContactDetailDefinition::name()}{name()} of each
       
   416     definition.  If \a definitionName is empty, all details of any definition
       
   417     will be returned.
       
   418  */
       
   419 QList<QContactDetail> QContact::details(const QString& definitionName, const QString& fieldName, const QString& value) const
       
   420 {
       
   421     // build the sub-list of matching details.
       
   422     QList<QContactDetail> sublist;
       
   423 
       
   424     // special case
       
   425     if (fieldName.isEmpty()) {
       
   426         sublist = details(definitionName);
       
   427     } else {
       
   428         for (int i = 0; i < d->m_details.size(); i++) {
       
   429             const QContactDetail& existing = d->m_details.at(i);
       
   430             if (QContactDetailPrivate::detailPrivate(existing)->m_definitionName == definitionName
       
   431                 && existing.hasValue(fieldName) && value == existing.value(fieldName)) {
       
   432                 sublist.append(existing);
       
   433             }
       
   434         }
       
   435     }
       
   436 
       
   437     return sublist;
       
   438 }
       
   439 
       
   440 /*!
       
   441     \internal
       
   442     Returns the first detail stored in the contact which with the given \a definitionName
       
   443 */
       
   444 QContactDetail QContact::detail(const char* definitionName) const
       
   445 {
       
   446     if (definitionName == 0)
       
   447         return d->m_details.first();
       
   448 
       
   449     // build the sub-list of matching details.
       
   450     for (int i = 0; i < d->m_details.size(); i++) {
       
   451         const QContactDetail& existing = d->m_details.at(i);
       
   452         if (QContactDetailPrivate::detailPrivate(existing)->m_definitionName == definitionName) {
       
   453             return existing;
       
   454         }
       
   455     }
       
   456 
       
   457     return QContactDetail();
       
   458 }
       
   459 
       
   460 /*!
       
   461     \internal
       
   462     Returns a list of details with the given \a definitionName
       
   463 */
       
   464 QList<QContactDetail> QContact::details(const char* definitionName) const
       
   465 {
       
   466     // build the sub-list of matching details.
       
   467     QList<QContactDetail> sublist;
       
   468 
       
   469     // special case
       
   470     if (definitionName == 0) {
       
   471         sublist = d->m_details;
       
   472     } else {
       
   473         for (int i = 0; i < d->m_details.size(); i++) {
       
   474             const QContactDetail& existing = d->m_details.at(i);
       
   475             if (QContactDetailPrivate::detailPrivate(existing)->m_definitionName == definitionName) {
       
   476                 sublist.append(existing);
       
   477             }
       
   478         }
       
   479     }
       
   480 
       
   481     return sublist;
       
   482 }
       
   483 
       
   484 /*!
       
   485     \internal
       
   486     Returns a list of details with the given \a definitionName, \a fieldName and field \a value
       
   487 */
       
   488 QList<QContactDetail> QContact::details(const char* definitionName, const char* fieldName, const QString& value) const
       
   489 {
       
   490     // build the sub-list of matching details.
       
   491     QList<QContactDetail> sublist;
       
   492 
       
   493     // special case
       
   494     if (fieldName == 0) {
       
   495         sublist = details(definitionName);
       
   496     } else {
       
   497         for (int i = 0; i < d->m_details.size(); i++) {
       
   498             const QContactDetail& existing = d->m_details.at(i);
       
   499             if (QContactDetailPrivate::detailPrivate(existing)->m_definitionName == definitionName
       
   500                 && existing.hasValue(fieldName) && value == existing.value(fieldName)) {
       
   501                 sublist.append(existing);
       
   502             }
       
   503         }
       
   504     }
       
   505 
       
   506     return sublist;
       
   507 }
       
   508 
       
   509 /*!
       
   510  * Saves the given \a detail in the list of stored details, and sets the detail's id.
       
   511  * If another detail of the same type and id has been previously saved in
       
   512  * this contact, that detail is overwritten.  Otherwise, a new id is generated
       
   513  * and set in the detail, and the detail is added to the contact.
       
   514  *
       
   515  * If the detail's access constraint includes \c QContactDetail::ReadOnly,
       
   516  * this function will return true and save the detail in the contact,
       
   517  * however attempting to save the contact in a manager may fail (if that manager
       
   518  * decides that the read only detail should not be updated).
       
   519  * Details with the \c QContactDetail::ReadOnly constraint set are typically provided
       
   520  * in a contact by the manager, and are usually information that is either
       
   521  * synthesized, or not intended to be changed by the user (e.g. presence information
       
   522  * for other contacts).
       
   523  *
       
   524  * If \a detail is a QContactType, the existing contact type will
       
   525  * be overwritten with \a detail.  There is never more than one contact type
       
   526  * in a contact.
       
   527  *
       
   528  * If \a detail is a QContactDisplayLabel, the contact will not be updated,
       
   529  * and the function will return false.  Since the display label formatting is specific
       
   530  * to each manager, use the QContactManager::synthesizeContactDisplayLabel() function
       
   531  * instead.
       
   532  *
       
   533  * Be aware that if a contact is retrieved (or reloaded) from the backend, the
       
   534  * keys of any details it contains may have been changed by the backend, or other
       
   535  * threads may have modified the contact details in the backend.  Therefore,
       
   536  * clients should reload the detail that they wish to save in a contact after retrieving
       
   537  * the contact, in order to avoid creating unwanted duplicated details.
       
   538  *
       
   539  * Returns true if the detail was saved successfully, otherwise returns false.
       
   540  *
       
   541  * Note that the caller retains ownership of the detail.
       
   542  * \sa QContactManager::synthesizeContactDisplayLabel()
       
   543  */
       
   544 bool QContact::saveDetail(QContactDetail* detail)
       
   545 {
       
   546     if (!detail)
       
   547         return false;
       
   548 
       
   549     /* Also handle contact type specially - only one of them. */
       
   550     if (QContactDetailPrivate::detailPrivate(*detail)->m_definitionName == QContactType::DefinitionName.latin1()) {
       
   551         detail->d->m_access |= QContactDetail::Irremovable;
       
   552         d->m_details[1] = *detail;
       
   553         return true;
       
   554     }
       
   555 
       
   556     /* And display label.. */
       
   557     if (QContactDetailPrivate::detailPrivate(*detail)->m_definitionName == QContactDisplayLabel::DefinitionName.latin1()) {
       
   558         return false;
       
   559     }
       
   560 
       
   561     // try to find the "old version" of this field
       
   562     // ie, the one with the same type and id, but different value or attributes.
       
   563     for (int i = 0; i < d->m_details.size(); i++) {
       
   564         const QContactDetail& curr = d->m_details.at(i);
       
   565         if (detail->d->m_definitionName == curr.d->m_definitionName && detail->d->m_id == curr.d->m_id) {
       
   566             // update the detail constraints of the supplied detail
       
   567             detail->d->m_access = d->m_details[i].accessConstraints();
       
   568             // Found the old version.  Replace it with this one.
       
   569             d->m_details[i] = *detail;
       
   570             return true;
       
   571         }
       
   572     }
       
   573 
       
   574     // this is a new detail!  add it to the contact.
       
   575     d->m_details.append(*detail);
       
   576     return true;
       
   577 }
       
   578 
       
   579 /*!
       
   580  * Removes the \a detail from the contact.
       
   581  *
       
   582  * The detail in the contact which has the same key as that of the given \a detail
       
   583  * will be removed if it exists.  Only the key is used for comparison - that is, the
       
   584  * information in the detail may be different.
       
   585  *
       
   586  * Any action preferences for the matching detail is also removed.
       
   587  *
       
   588  * Be aware that if a contact is retrieved (or reloaded) from the backend, the
       
   589  * keys of any details it contains may have been changed by the backend, or other
       
   590  * threads may have modified the contact details in the backend.  Therefore,
       
   591  * clients should reload the detail that they wish to remove from a contact after retrieving
       
   592  * the contact, in order to ensure that the remove operation is successful.
       
   593  *
       
   594  * If the detail's access constraint includes \c QContactDetail::Irremovable,
       
   595  * this function will return false.
       
   596  *
       
   597  * Returns true if the detail was removed successfully, false if an error occurred.
       
   598  *
       
   599  * Note that the caller retains ownership of the detail.
       
   600  */
       
   601 bool QContact::removeDetail(QContactDetail* detail)
       
   602 {
       
   603     if (!detail)
       
   604         return false;
       
   605 
       
   606     // find the detail stored in the contact which has the same key as the detail argument
       
   607     int removeIndex = -1;
       
   608     for (int i = 0; i < d->m_details.size(); i++) {
       
   609         if (d->m_details.at(i).key() == detail->key()) {
       
   610             removeIndex = i;
       
   611             break;
       
   612         }
       
   613     }
       
   614 
       
   615     // make sure the detail exists (in some form) in the contact.
       
   616     if (removeIndex < 0)
       
   617         return false;
       
   618 
       
   619     if (detail->accessConstraints() & QContactDetail::Irremovable)
       
   620         return false;
       
   621 
       
   622     if (!d->m_details.contains(*detail))
       
   623         return false;
       
   624 
       
   625     // remove any preferences we may have stored for the detail.
       
   626     QStringList keys = d->m_preferences.keys();
       
   627     for (int i = 0; i < keys.size(); i++) {
       
   628         QString prefKey = keys.at(i);
       
   629         if (d->m_preferences.value(prefKey) == detail->d->m_id) {
       
   630             d->m_preferences.remove(prefKey);
       
   631         }
       
   632     }
       
   633 
       
   634     // then remove the detail.
       
   635     d->m_details.removeAt(removeIndex);
       
   636     return true;
       
   637 }
       
   638 
       
   639 /*! Returns true if this contact is equal to the \a other contact, false if either the id or stored details are not the same */
       
   640 bool QContact::operator==(const QContact& other) const
       
   641 {
       
   642     return other.d->m_id == d->m_id &&
       
   643         other.d->m_details == d->m_details;
       
   644 }
       
   645 
       
   646 /*!
       
   647     \relates QContact
       
   648     Returns the hash value for \a key.
       
   649 */
       
   650 uint qHash(const QContact &key)
       
   651 {
       
   652     uint hash = qHash(key.id());
       
   653     foreach (const QContactDetail& detail, key.details()) {
       
   654         hash += qHash(detail);
       
   655     }
       
   656     return hash;
       
   657 }
       
   658 
       
   659 QDebug operator<<(QDebug dbg, const QContact& contact)
       
   660 {
       
   661     dbg.nospace() << "QContact(" << contact.id() << ")";
       
   662     foreach (const QContactDetail& detail, contact.details()) {
       
   663         dbg.space() << '\n' << detail;
       
   664     }
       
   665     return dbg.maybeSpace();
       
   666 }
       
   667 
       
   668 
       
   669 /*!
       
   670   \deprecated
       
   671 */
       
   672 QContactDetail QContact::detailWithAction(const QString& actionName) const
       
   673 {
       
   674     qWarning("QContact::detailWithAction(const QString&) This function is deprecated and will be removed after the transition period has elapsed.  Use the function which takes a pointer to an action implementation instance instead!");
       
   675     return QContactDetail();
       
   676 }
       
   677 
       
   678 /*!
       
   679   \deprecated
       
   680 */
       
   681 QList<QContactDetail> QContact::detailsWithAction(const QString& actionName) const
       
   682 {
       
   683     qWarning("QContact::detailsWithAction(const QString&) This function is deprecated and will be removed after the transition period has elapsed.  Use the function which takes a pointer to an action implementation instance instead!");
       
   684     return QList<QContactDetail>();
       
   685 }
       
   686 
       
   687 /*!
       
   688     Retrieve the first detail in this contact supported by the given \a action.
       
   689 
       
   690     If there is a preferred detail set for this action name, and that detail is
       
   691     supported by the given \a action, that preferred detail will be returned.
       
   692 
       
   693     Otherwise, the first detail in the list returned by detailsWithAction() will
       
   694     be returned.
       
   695 
       
   696     \sa detailsWithAction()
       
   697 */
       
   698 QContactDetail QContact::detailWithAction(QContactAction* action) const
       
   699 {
       
   700     if (action) {
       
   701         QContactDetail pref = preferredDetail(action->actionDescriptor().actionName());
       
   702         if (!pref.isEmpty() && action->isDetailSupported(pref, *this))
       
   703             return pref;
       
   704         foreach (const QContactDetail& detail, d->m_details) {
       
   705             if (action->isDetailSupported(detail, *this)) {
       
   706                 return detail;
       
   707             }
       
   708         }
       
   709     }
       
   710     return QContactDetail();
       
   711 }
       
   712 
       
   713 /*!
       
   714     Retrieve any details supported by the given \a action.
       
   715 
       
   716     If the action does not exist, an empty list will be returned.  Otherwise,
       
   717     the details in this contact will be tested by the action and a list of the
       
   718     details supported will be returned.
       
   719 
       
   720     If a preferred detail for this action name has been set, and it is supported
       
   721     by the given \a action, that detail will be the first detail returned in the list.
       
   722 
       
   723     See this example for usage:
       
   724     \snippet doc/src/snippets/qtcontactsdocsample/qtcontactsdocsample.cpp Details with action
       
   725 */
       
   726 QList<QContactDetail> QContact::detailsWithAction(QContactAction* action) const
       
   727 {
       
   728     QList<QContactDetail> retn;
       
   729 
       
   730     if (action) {
       
   731         QContactDetail preferred = preferredDetail(action->actionDescriptor().actionName());
       
   732         foreach (const QContactDetail& detail, d->m_details) {
       
   733             if (action->isDetailSupported(detail, *this)) {
       
   734                 if (detail == preferred)
       
   735                     retn.prepend(detail);
       
   736                 else
       
   737                     retn.append(detail);
       
   738             }
       
   739         }
       
   740     }
       
   741     return retn;
       
   742 }
       
   743 
       
   744 /*!
       
   745     Returns a list of relationships of the given \a relationshipType in which this contact is a participant.
       
   746 
       
   747     If \a relationshipType is empty, all relationships will be returned.
       
   748 
       
   749     \note This function only examines the relationships that were present when this contact
       
   750     was retrieved from a manager.  You can also query the manager directly, if you require
       
   751     the most up to date information.
       
   752 
       
   753     \snippet doc/src/snippets/qtcontactsdocsample/qtcontactsdocsample.cpp 5
       
   754 
       
   755     \sa QContactRelationshipFetchRequest, QContactManager::relationships()
       
   756  */
       
   757 QList<QContactRelationship> QContact::relationships(const QString& relationshipType) const
       
   758 {
       
   759     // if empty, then they want all relationships
       
   760     if (relationshipType.isEmpty())
       
   761         return d->m_relationshipsCache;
       
   762 
       
   763     // otherwise, filter on type.
       
   764     QList<QContactRelationship> retn;
       
   765     for (int i = 0; i < d->m_relationshipsCache.size(); i++) {
       
   766         QContactRelationship curr = d->m_relationshipsCache.at(i);
       
   767         if (curr.relationshipType() == relationshipType) {
       
   768             retn.append(curr);
       
   769         }
       
   770     }
       
   771 
       
   772     return retn;
       
   773 }
       
   774 
       
   775 /*!
       
   776     Returns a list of the ids of contacts which have a relationship of the given \a relationshipType with this contact.
       
   777     The \a role parameter describes the role that the related contacts have in the relationship.
       
   778 
       
   779     If \a relationshipType is empty, relationships of all types will be considered.
       
   780 
       
   781     \note This function only examines the relationships that were present when this contact
       
   782     was retrieved from a manager.  You can also query the manager directly, if you require
       
   783     the most up to date information.
       
   784 
       
   785     \snippet doc/src/snippets/qtcontactsdocsample/qtcontactsdocsample.cpp 6
       
   786 
       
   787     \sa QContactRelationshipFetchRequest, QContactManager::relationships()
       
   788  */
       
   789 QList<QContactId> QContact::relatedContacts(const QString& relationshipType, QContactRelationship::Role role) const
       
   790 {
       
   791     QList<QContactId> retn;
       
   792     for (int i = 0; i < d->m_relationshipsCache.size(); i++) {
       
   793         QContactRelationship curr = d->m_relationshipsCache.at(i);
       
   794         if (relationshipType.isEmpty() || curr.relationshipType() == relationshipType) {
       
   795             // check that the other contacts fill the given role
       
   796             if (role == QContactRelationship::First) {
       
   797                 if (curr.first() != d->m_id) {
       
   798                     if (!retn.contains(curr.first())) {
       
   799                         retn.append(curr.first());
       
   800                     }
       
   801                 }
       
   802             } else if (role == QContactRelationship::Second) {
       
   803                 if (curr.first() == d->m_id) {
       
   804                     if (!retn.contains(curr.second())) {
       
   805                         retn.append(curr.second());
       
   806                     }
       
   807                 }
       
   808             } else { // role == Either.
       
   809                 if (curr.first() == d->m_id) {
       
   810                     if (!retn.contains(curr.second())) {
       
   811                         retn.append(curr.second());
       
   812                     }
       
   813                 } else {
       
   814                     if (!retn.contains(curr.first())) {
       
   815                         retn.append(curr.first());
       
   816                     }
       
   817                 }
       
   818             }
       
   819         }
       
   820     }
       
   821 
       
   822     return retn;
       
   823 }
       
   824 
       
   825 /*!
       
   826  * Return a list of descriptors for the actions available to be performed on this contact.
       
   827  *
       
   828  * The actions considered can be restricted by the optional parameters
       
   829  * \list
       
   830  *  \o The actions can be restricted to those provided by a specific vendor with the \a vendorName parameter.
       
   831  * If \a vendorName is empty, actions from all vendors will be considered.
       
   832  *  \o A specific version of an action can also be requested with \a implementationVersion.  If \c -1 is
       
   833  * passed (the default), all versions will be considered.  This is usually useful in conjunction with a specific vendor.
       
   834  * \endlist
       
   835  *
       
   836  * Each action that matches the above criteria will be tested to see if this contact is supported
       
   837  * by the action, and a list of the action descriptors that are supported will be returned.
       
   838  */
       
   839 QList<QContactActionDescriptor> QContact::availableActions(const QString& vendorName, int implementationVersion) const
       
   840 {
       
   841     // check every action implementation to see if it supports me.
       
   842     QSet<QContactActionDescriptor> retn;
       
   843     QList<QContactActionDescriptor> descriptors = QContactManagerData::actionDescriptors();
       
   844     for (int i = 0; i < descriptors.size(); i++) {
       
   845         QContactActionDescriptor currDescriptor = descriptors.at(i);
       
   846         if ((vendorName.isEmpty() || currDescriptor.vendorName() == vendorName) &&
       
   847             (implementationVersion == -1 || currDescriptor.implementationVersion() == implementationVersion)) {
       
   848             QScopedPointer<QContactAction> currImpl(QContactManagerData::action(currDescriptor));
       
   849             if (QContactManagerEngine::testFilter(currImpl->contactFilter(), *this)) {
       
   850                 retn.insert(currDescriptor);
       
   851             }
       
   852         }
       
   853     }
       
   854 
       
   855     return retn.toList();
       
   856 }
       
   857 
       
   858 /*!
       
   859  * Set a particular detail (\a preferredDetail) as the preferred detail for any actions with the given \a actionName.
       
   860  *
       
   861  * The \a preferredDetail object must exist in this object, and the \a actionName cannot be empty.
       
   862  *
       
   863  * Returns true if the preference could be recorded, and false otherwise.
       
   864  *
       
   865  * \sa preferredDetail()
       
   866  */
       
   867 bool QContact::setPreferredDetail(const QString& actionName, const QContactDetail& preferredDetail)
       
   868 {
       
   869     // if the given action name is empty, bad argument.
       
   870     if (actionName.isEmpty())
       
   871         return false;
       
   872 
       
   873     // check to see whether the the given preferredDetail is saved in this contact
       
   874     if (!d->m_details.contains(preferredDetail))
       
   875         return false;
       
   876 
       
   877     // otherwise, save the preference.
       
   878     d->m_preferences.insert(actionName, preferredDetail.d->m_id);
       
   879     return true;
       
   880 }
       
   881 
       
   882 /*!
       
   883  * Returns true if the given \a detail is a preferred detail for the given \a actionName,
       
   884  * or for any action if the \a actionName is empty.
       
   885  *
       
   886  * \sa preferredDetail()
       
   887  */
       
   888 bool QContact::isPreferredDetail(const QString& actionName, const QContactDetail& detail) const
       
   889 {
       
   890     if (!d->m_details.contains(detail))
       
   891         return false;
       
   892 
       
   893     if (actionName.isEmpty())
       
   894          return d->m_preferences.values().contains(detail.d->m_id);
       
   895 
       
   896     QMap<QString, int>::const_iterator it = d->m_preferences.find(actionName);
       
   897     if (it != d->m_preferences.end() && it.value() == detail.d->m_id)
       
   898         return true;
       
   899 
       
   900     return false;
       
   901 }
       
   902 
       
   903 /*!
       
   904  * Returns the preferred detail for a given \a actionName.
       
   905  *
       
   906  * If the \a actionName is empty, or there is no preference recorded for
       
   907  * the supplied \a actionName, returns an empty QContactDetail.
       
   908  *
       
   909  * \sa preferredDetails()
       
   910  */
       
   911 QContactDetail QContact::preferredDetail(const QString& actionName) const
       
   912 {
       
   913     // if the given action name is empty, bad argument.
       
   914     if (actionName.isEmpty())
       
   915         return QContactDetail();
       
   916 
       
   917     if (!d->m_preferences.contains(actionName))
       
   918         return QContactDetail();
       
   919 
       
   920     QContactDetail retn;
       
   921     int detId = d->m_preferences.value(actionName);
       
   922     for (int i = 0; i < d->m_details.size(); i++) {
       
   923         QContactDetail det = d->m_details.at(i);
       
   924         if (det.d->m_id == detId) {
       
   925             // found it.
       
   926             retn = det;
       
   927             break;
       
   928         }
       
   929     }
       
   930 
       
   931     return retn;
       
   932 }
       
   933 
       
   934 /*!
       
   935  * Returns the recorded detail preferences for action names.
       
   936  *
       
   937  * Each entry in the map has the action name as the key, and the corresponding
       
   938  * preferred detail as the value.
       
   939  */
       
   940 QMap<QString, QContactDetail> QContact::preferredDetails() const
       
   941 {
       
   942     QMap<QString, QContactDetail> ret;
       
   943     QMap<QString, int>::const_iterator it = d->m_preferences.constBegin();
       
   944     while (it != d->m_preferences.constEnd()) {
       
   945         ret.insert(it.key(), d->m_details.at(it.value()));
       
   946         ++it;
       
   947     }
       
   948 
       
   949     return ret;
       
   950 }
       
   951 
       
   952 QTM_END_NAMESPACE