src/contacts/qcontactmanagerengine.cpp
changeset 0 876b1a06bc25
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 "qcontactmanagerengine.h"
       
    43 
       
    44 #include "qcontactdetaildefinition.h"
       
    45 #include "qcontactdetailfielddefinition.h"
       
    46 #include "qcontactdetails.h"
       
    47 #include "qcontactsortorder.h"
       
    48 #include "qcontactfilters.h"
       
    49 #include "qcontactaction.h"
       
    50 #include "qcontactactiondescriptor.h"
       
    51 #include "qcontactabstractrequest.h"
       
    52 #include "qcontactabstractrequest_p.h"
       
    53 #include "qcontactrequests.h"
       
    54 #include "qcontactrequests_p.h"
       
    55 #include "qcontact.h"
       
    56 #include "qcontactfetchhint.h"
       
    57 
       
    58 #include "qcontact_p.h"
       
    59 #include "qcontactdetail_p.h"
       
    60 
       
    61 #include <QMutex>
       
    62 #include <QMutexLocker>
       
    63 #include <QWeakPointer>
       
    64 
       
    65 QTM_BEGIN_NAMESPACE
       
    66 
       
    67 /*!
       
    68   \class QContactManagerEngine
       
    69   \brief The QContactManagerEngine class provides the interface for all
       
    70   implementations of the contact manager backend functionality.
       
    71   \ingroup contacts-backends
       
    72 
       
    73   Instances of this class are usually provided by a
       
    74   \l QContactManagerEngineFactory, which is loaded from a plugin.
       
    75 
       
    76   The default implementation of this interface provides a basic
       
    77   level of functionality for some functions so that specific engines
       
    78   can simply implement the functionality that is supported by
       
    79   the specific contacts engine that is being adapted.
       
    80 
       
    81   More information on writing a contacts engine plugin is available in
       
    82   the \l{Qt Contacts Manager Engines} documentation.
       
    83 
       
    84   \sa QContactManager, QContactManagerEngineFactory
       
    85  */
       
    86 
       
    87 /*!
       
    88   \fn QContactManagerEngine::QContactManagerEngine()
       
    89 
       
    90   A default, empty constructor.
       
    91  */
       
    92 
       
    93 /*!
       
    94   \fn QContactManagerEngine::dataChanged()
       
    95 
       
    96   This signal is emitted some time after changes occur to the data managed by this
       
    97   engine, and the engine is unable to determine which changes occurred, or if the
       
    98   engine considers the changes to be radical enough to require clients to reload all data.
       
    99 
       
   100   If this signal is emitted, no other signals may be emitted for the associated changes.
       
   101 
       
   102   As it is possible that other processes (or other devices) may have caused the
       
   103   changes, the timing can not be determined.
       
   104 
       
   105   \sa contactsAdded(), contactsChanged(), contactsRemoved()
       
   106  */
       
   107 
       
   108 /*!
       
   109   \fn QContactManagerEngine::contactsAdded(const QList<QContactLocalId>& contactIds);
       
   110 
       
   111   This signal is emitted some time after a set of contacts has been added to
       
   112   this engine where the \l dataChanged() signal was not emitted for those changes.
       
   113   As it is possible that other processes (or other devices) may
       
   114   have added the contacts, the timing cannot be determined.
       
   115 
       
   116   The list of ids of contacts added is given by \a contactIds.  There may be one or more
       
   117   ids in the list.
       
   118 
       
   119   \sa dataChanged()
       
   120  */
       
   121 
       
   122 /*!
       
   123   \fn QContactManagerEngine::contactsChanged(const QList<QContactLocalId>& contactIds);
       
   124 
       
   125   This signal is emitted some time after a set of contacts has been modified in
       
   126   this engine where the \l dataChanged() signal was not emitted for those changes.
       
   127   As it is possible that other processes (or other devices) may
       
   128   have modified the contacts, the timing cannot be determined.
       
   129 
       
   130   The list of ids of changed contacts is given by \a contactIds.  There may be one or more
       
   131   ids in the list.
       
   132 
       
   133   \sa dataChanged()
       
   134  */
       
   135 
       
   136 /*!
       
   137   \fn QContactManagerEngine::contactsRemoved(const QList<QContactLocalId>& contactIds);
       
   138 
       
   139   This signal is emitted some time after a set of contacts has been removed from
       
   140   this engine where the \l dataChanged() signal was not emitted for those changes.
       
   141   As it is possible that other processes (or other devices) may
       
   142   have removed the contacts, the timing cannot be determined.
       
   143 
       
   144   The list of ids of removed contacts is given by \a contactIds.  There may be one or more
       
   145   ids in the list.
       
   146 
       
   147   \sa dataChanged()
       
   148  */
       
   149 
       
   150 /*!
       
   151   \fn QContactManagerEngine::relationshipsAdded(const QList<QContactLocalId>& affectedContactIds);
       
   152 
       
   153   This signal is emitted some time after a set of contacts has been added to
       
   154   this engine where the \l dataChanged() signal was not emitted for those changes.
       
   155   As it is possible that other processes (or other devices) may
       
   156   have added the contacts, the timing cannot be determined.
       
   157 
       
   158   The list of ids of affected contacts is given by \a affectedContactIds.  There may be one or more
       
   159   ids in the list.
       
   160 
       
   161   \sa dataChanged()
       
   162  */
       
   163 
       
   164 /*!
       
   165   \fn QContactManagerEngine::relationshipsRemoved(const QList<QContactLocalId>& affectedContactIds);
       
   166 
       
   167   This signal is emitted some time after a set of relationships has been removed from
       
   168   this engine where the \l dataChanged() signal was not emitted for those changes.
       
   169   As it is possible that other processes (or other devices) may
       
   170   have removed the relationships, the timing cannot be determined.
       
   171 
       
   172   The list of ids of affected contacts is given by \a affectedContactIds.  There may be one or more
       
   173   ids in the list.
       
   174 
       
   175   \sa dataChanged()
       
   176  */
       
   177 
       
   178 /*!
       
   179   \fn QContactManagerEngine::selfContactIdChanged(const QContactLocalId& oldId, const QContactLocalId& newId)
       
   180 
       
   181   This signal is emitted at some point after the id of the self-contact is changed from \a oldId to \a newId in the manager.
       
   182   If the \a newId is the invalid, zero id, then the self contact was deleted or no self contact exists.
       
   183   This signal must not be emitted if the dataChanged() signal was previously emitted for this change.
       
   184   As it is possible that other processes (or other devices) may
       
   185   have removed or changed the self contact, the timing cannot be determined.
       
   186 
       
   187   \sa dataChanged()
       
   188  */
       
   189 
       
   190 /*! Returns the manager name for this QContactManagerEngine */
       
   191 QString QContactManagerEngine::managerName() const
       
   192 {
       
   193     return QString(QLatin1String("base"));
       
   194 }
       
   195 
       
   196 /*!
       
   197   Returns the parameters with which this engine was constructed.  Note that
       
   198   the engine may have discarded unused or invalid parameters at the time of
       
   199   construction, and these will not be returned.
       
   200  */
       
   201 QMap<QString, QString> QContactManagerEngine::managerParameters() const
       
   202 {
       
   203     return QMap<QString, QString>(); // default implementation requires no parameters.
       
   204 }
       
   205 
       
   206 /*!
       
   207   Returns the unique URI of this manager, which is built from the manager name and the parameters
       
   208   used to construct it.
       
   209  */
       
   210 QString QContactManagerEngine::managerUri() const
       
   211 {
       
   212     return QContactManager::buildUri(managerName(), managerParameters());
       
   213 }
       
   214 
       
   215 /*!
       
   216   Returns a list of contact ids that match the given \a filter, sorted according to the given list of \a sortOrders.
       
   217   Depending on the backend, this filtering operation may involve retrieving all the contacts.
       
   218   Any error which occurs will be saved in \a error.
       
   219  */
       
   220 QList<QContactLocalId> QContactManagerEngine::contactIds(const QContactFilter& filter, const QList<QContactSortOrder>& sortOrders, QContactManager::Error* error) const
       
   221 {
       
   222     Q_UNUSED(filter);
       
   223     Q_UNUSED(sortOrders);
       
   224 
       
   225     *error = QContactManager::NotSupportedError;
       
   226     return QList<QContactLocalId>();
       
   227 }
       
   228 
       
   229 /*!
       
   230   Returns the list of contacts which match the given \a filter stored in the manager sorted according to the given list of \a sortOrders.
       
   231 
       
   232   Any operation error which occurs will be saved in \a error.
       
   233 
       
   234   The \a fetchHint parameter describes the optimization hints that a manager may take.
       
   235   If the \a fetchHint is the default constructed hint, all existing details, relationships and action preferences
       
   236   in the matching contacts will be returned.  A client should not make changes to a contact which has
       
   237   been retrieved using a fetch hint other than the default fetch hint.  Doing so will result in information
       
   238   loss when saving the contact back to the manager (as the "new" restricted contact will
       
   239   replace the previously saved contact in the backend).
       
   240 
       
   241   \sa QContactFetchHint
       
   242  */
       
   243 QList<QContact> QContactManagerEngine::contacts(const QContactFilter& filter, const QList<QContactSortOrder>& sortOrders, const QContactFetchHint& fetchHint, QContactManager::Error* error) const
       
   244 {
       
   245     Q_UNUSED(filter);
       
   246     Q_UNUSED(sortOrders);
       
   247     Q_UNUSED(fetchHint);
       
   248     *error = QContactManager::NotSupportedError;
       
   249     return QList<QContact>();
       
   250 }
       
   251 
       
   252 /*!
       
   253   Returns the contact in the database identified by \a contactId.
       
   254 
       
   255   If the contact does not exist, an empty, default constructed QContact will be returned,
       
   256   and the \a error will be set to  \c QContactManager::DoesNotExistError.
       
   257 
       
   258   Any operation error which occurs will be saved in \a error.
       
   259 
       
   260   The \a fetchHint parameter describes the optimization hints that a manager may take.
       
   261   If the \a fetchHint is the default constructed hint, all existing details, relationships and action preferences
       
   262   in the matching contact will be returned.  A client should not make changes to a contact which has
       
   263   been retrieved using a fetch hint other than the default fetch hint.  Doing so will result in information
       
   264   loss when saving the contact back to the manager (as the "new" restricted contact will
       
   265   replace the previously saved contact in the backend).
       
   266 
       
   267   \sa QContactFetchHint
       
   268  */
       
   269 QContact QContactManagerEngine::contact(const QContactLocalId& contactId, const QContactFetchHint& fetchHint, QContactManager::Error* error) const
       
   270 {
       
   271     Q_UNUSED(contactId);
       
   272     Q_UNUSED(fetchHint);
       
   273     *error = QContactManager::NotSupportedError;
       
   274     return QContact();
       
   275 }
       
   276 
       
   277 /*!
       
   278   Sets the id of the "self" contact to the given \a contactId.
       
   279   Returns true if the "self" contact id was set successfully.
       
   280   If the given \a contactId does not identify a contact
       
   281   stored in this manager, the \a error will be set to
       
   282   \c QContactManager::DoesNotExistError and the function will
       
   283   return false; if the backend does not support the
       
   284   concept of a "self" contact, the \a error will be set to
       
   285   \c QContactManager::NotSupportedError and the function will
       
   286   return false.
       
   287  */
       
   288 bool QContactManagerEngine::setSelfContactId(const QContactLocalId& contactId, QContactManager::Error* error)
       
   289 {
       
   290     Q_UNUSED(contactId);
       
   291 
       
   292     *error = QContactManager::NotSupportedError;
       
   293     return false;
       
   294 }
       
   295 
       
   296 /*!
       
   297   Returns the id of the "self" contact which has previously been set.
       
   298   If no "self" contact has been set, or if the self contact was removed
       
   299   from the manager after being set, or if the backend does not support
       
   300   the concept of a "self" contact, an invalid id will be returned
       
   301   and the \a error will be set to \c QContactManager::DoesNotExistError.
       
   302  */
       
   303 QContactLocalId QContactManagerEngine::selfContactId(QContactManager::Error* error) const
       
   304 {
       
   305     *error = QContactManager::DoesNotExistError;
       
   306     return QContactLocalId();
       
   307 }
       
   308 
       
   309 /*!
       
   310   Returns a list of relationships of the given \a relationshipType in which the contact identified by the given \a participantId participates in the given \a role.
       
   311   If \a participantId is the default-constructed id, \a role is ignored and all relationships of the given \a relationshipType are returned.
       
   312   If \a relationshipType is empty, relationships of any type are returned.
       
   313   If no relationships of the given \a relationshipType in which the contact identified by the given \a participantId is involved in the given \a role exists,
       
   314   \a error is set to QContactManager::DoesNotExistError.
       
   315  */
       
   316 QList<QContactRelationship> QContactManagerEngine::relationships(const QString& relationshipType, const QContactId& participantId, QContactRelationship::Role role, QContactManager::Error* error) const
       
   317 {
       
   318     Q_UNUSED(relationshipType);
       
   319     Q_UNUSED(participantId);
       
   320     Q_UNUSED(role);
       
   321 
       
   322     *error = QContactManager::NotSupportedError;
       
   323     return QList<QContactRelationship>();
       
   324 }
       
   325 
       
   326 /*!
       
   327   Saves the given \a relationships in the database and returns true if the operation was successful.
       
   328   For any relationship which was unable to be saved, an entry into the \a errorMap will be created,
       
   329   with the key being the index into the input relationships list, and the value being the error which
       
   330   occurred for that index.
       
   331 
       
   332   The supplied \a errorMap parameter may be null, if the client does not desire detailed error information.
       
   333   If supplied, it will be empty upon entry to this function.
       
   334 
       
   335   The overall operation error will be saved in \a error.
       
   336  */
       
   337 bool QContactManagerEngine::saveRelationships(QList<QContactRelationship>* relationships, QMap<int, QContactManager::Error>* errorMap, QContactManager::Error* error)
       
   338 {
       
   339     Q_UNUSED(relationships);
       
   340     Q_UNUSED(errorMap);
       
   341 
       
   342     *error = QContactManager::NotSupportedError;
       
   343     return false;
       
   344 }
       
   345 
       
   346 /*!
       
   347   Saves the given \a relationship in the database.  If the relationship already exists in the database, this function will
       
   348   return \c false and the \a error will be set to \c QContactManager::AlreadyExistsError.
       
   349   If the relationship is saved successfully, this function will return \c true and \a error will be set
       
   350   to \c QContactManager::NoError.  Note that relationships cannot be updated directly using this function; in order
       
   351   to update a relationship, you must remove the old relationship, make the required modifications, and then save it.
       
   352 
       
   353   The given relationship is invalid if it is circular (the first contact is the second contact), or
       
   354   if it references a non-existent local contact (either the first or second contact).  If the given \a relationship is invalid,
       
   355   the function will return \c false and the \a error will be set to \c QContactManager::InvalidRelationshipError.
       
   356 
       
   357   The default implementation of this function converts the argument into a call to saveRelationships.
       
   358  */
       
   359 bool QContactManagerEngine::saveRelationship(QContactRelationship *relationship, QContactManager::Error *error)
       
   360 {
       
   361     // Convert to a list op
       
   362     if (relationship) {
       
   363         QList<QContactRelationship> list;
       
   364         list.append(*relationship);
       
   365 
       
   366         QMap<int, QContactManager::Error> errors;
       
   367         bool ret = saveRelationships(&list, &errors, error);
       
   368 
       
   369         if (errors.count() > 0)
       
   370             *error = errors.begin().value();
       
   371 
       
   372         *relationship = list.value(0);
       
   373         return ret;
       
   374     } else {
       
   375         *error = QContactManager::BadArgumentError;
       
   376         return false;
       
   377     }
       
   378 }
       
   379 
       
   380 /*!
       
   381   Removes the given \a relationship from the manager.  If the relationship exists in the manager, the relationship
       
   382   will be removed, the \a error will be set to \c QContactManager::NoError and this function will return true.  If no such
       
   383   relationship exists in the manager, the \a error will be set to \c QContactManager::DoesNotExistError and this function
       
   384   will return false.
       
   385 
       
   386   The default implementation of this function converts the argument into a call to removeRelationships
       
   387  */
       
   388 bool QContactManagerEngine::removeRelationship(const QContactRelationship& relationship, QContactManager::Error* error)
       
   389 {
       
   390     // Convert to a list op
       
   391     QList<QContactRelationship> list;
       
   392     list.append(relationship);
       
   393 
       
   394     QMap<int, QContactManager::Error> errors;
       
   395     bool ret = removeRelationships(list, &errors, error);
       
   396 
       
   397     if (errors.count() > 0)
       
   398         *error = errors.begin().value();
       
   399 
       
   400     return ret;
       
   401 }
       
   402 
       
   403 
       
   404 /*!
       
   405   Removes the given \a relationships from the database and returns true if the operation was successful.
       
   406   For any relationship which was unable to be removed, an entry into the \a errorMap will be created,
       
   407   with the key being the index into the input relationships list, and the value being the error which
       
   408   occurred for that index.
       
   409 
       
   410   The supplied \a errorMap parameter may be null, if the client does not desire detailed error information.
       
   411   If supplied, it will be empty upon entry to this function.
       
   412 
       
   413   The overall operation error will be saved in \a error.
       
   414  */
       
   415 bool QContactManagerEngine::removeRelationships(const QList<QContactRelationship>& relationships, QMap<int, QContactManager::Error>* errorMap, QContactManager::Error* error)
       
   416 {
       
   417     Q_UNUSED(relationships);
       
   418     Q_UNUSED(errorMap);
       
   419 
       
   420     *error = QContactManager::NotSupportedError;
       
   421     return false;
       
   422 }
       
   423 
       
   424 /*!
       
   425   Synthesizes the display label of the given \a contact in a platform specific manner.
       
   426   Any error that occurs will be stored in \a error.
       
   427   Returns the synthesized display label.
       
   428  */
       
   429 QString QContactManagerEngine::synthesizedDisplayLabel(const QContact& contact, QContactManager::Error* error) const
       
   430 {
       
   431     // synthesize the display name from the name of the contact, or, failing that, the organisation of the contact.
       
   432     *error = QContactManager::NoError;
       
   433     QList<QContactDetail> allNames = contact.details(QContactName::DefinitionName);
       
   434 
       
   435     const QLatin1String space(" ");
       
   436 
       
   437     // synthesize the display label from the name.
       
   438     for (int i=0; i < allNames.size(); i++) {
       
   439         const QContactName& name = allNames.at(i);
       
   440 
       
   441         if (!name.customLabel().isEmpty()) {
       
   442             // default behaviour is to allow the user to define a custom display label.
       
   443             return name.customLabel();
       
   444         }
       
   445 
       
   446         QString result;
       
   447         if (!name.value(QContactName::FieldPrefix).trimmed().isEmpty()) {
       
   448            result += name.value(QContactName::FieldPrefix);
       
   449         }
       
   450 
       
   451         if (!name.value(QContactName::FieldFirstName).trimmed().isEmpty()) {
       
   452             if (!result.isEmpty())
       
   453                 result += space;
       
   454             result += name.value(QContactName::FieldFirstName);
       
   455         }
       
   456 
       
   457         if (!name.value(QContactName::FieldMiddleName).trimmed().isEmpty()) {
       
   458             if (!result.isEmpty())
       
   459                 result += space;
       
   460             result += name.value(QContactName::FieldMiddleName);
       
   461         }
       
   462 
       
   463         if (!name.value(QContactName::FieldLastName).trimmed().isEmpty()) {
       
   464             if (!result.isEmpty())
       
   465                 result += space;
       
   466             result += name.value(QContactName::FieldLastName);
       
   467         }
       
   468 
       
   469         if (!name.value(QContactName::FieldSuffix).trimmed().isEmpty()) {
       
   470             if (!result.isEmpty())
       
   471                 result += space;
       
   472             result += name.value(QContactName::FieldSuffix);
       
   473         }
       
   474 
       
   475         if (!result.isEmpty()) {
       
   476             return result;
       
   477         }
       
   478     }
       
   479 
       
   480     /* Well, we had no non empty names. if we have orgs, fall back to those */
       
   481     QList<QContactDetail> allOrgs = contact.details(QContactOrganization::DefinitionName);
       
   482     for (int i=0; i < allOrgs.size(); i++) {
       
   483         const QContactOrganization& org = allOrgs.at(i);
       
   484         if (!org.name().isEmpty()) {
       
   485             return org.name();
       
   486         }
       
   487     }
       
   488 
       
   489     *error = QContactManager::UnspecifiedError;
       
   490     return QString();
       
   491 }
       
   492 
       
   493 /*!
       
   494   Sets the contact display label of \a contact to the supplied \a displayLabel.
       
   495  */
       
   496 void QContactManagerEngine::setContactDisplayLabel(QContact* contact, const QString& displayLabel)
       
   497 {
       
   498     QContactDisplayLabel dl;
       
   499     dl.setValue(QContactDisplayLabel::FieldLabel, displayLabel);
       
   500     setDetailAccessConstraints(&dl, QContactDetail::Irremovable | QContactDetail::ReadOnly);
       
   501     contact->d->m_details.replace(0, dl);
       
   502 }
       
   503 
       
   504 /*!  
       
   505   \deprecated
       
   506 
       
   507   Returns a copy of \a contact with the contact display label set to the supplied \a displayLabel.
       
   508 
       
   509   This function does not touch the database in any way, and is purely a convenience to allow engine implementations to set the display label.
       
   510 
       
   511   This function has been deprecated - use the function with the same name that accepts different parameters.
       
   512 */
       
   513 QContact QContactManagerEngine::setContactDisplayLabel(const QString& displayLabel, const QContact& contact)
       
   514 {
       
   515     QContact newContact = contact;
       
   516     setContactDisplayLabel(&newContact, displayLabel);
       
   517     return newContact;
       
   518 }
       
   519 
       
   520 /*!
       
   521   Returns true if the given \a feature is supported by this engine for contacts of the given \a contactType
       
   522  */
       
   523 bool QContactManagerEngine::hasFeature(QContactManager::ManagerFeature feature, const QString& contactType) const
       
   524 {
       
   525     Q_UNUSED(feature);
       
   526     Q_UNUSED(contactType);
       
   527 
       
   528     return false;
       
   529 }
       
   530 
       
   531 /*!
       
   532   Given an input \a filter, returns the canonical version of the filter.
       
   533 
       
   534   Some of the following transformations may be applied:
       
   535   \list
       
   536    \o Any QContactActionFilters are transformed into the corresponding
       
   537      QContactFilters returned by matching actions
       
   538    \o Any QContactInvalidFilters contained in a union filter will be removed
       
   539    \o Any default QContactFilters contained in an intersection filter will be removed
       
   540    \o Any QContactIntersectionFilters with a QContactInvalidFilter contained will be
       
   541      replaced with a QContactInvalidFilter
       
   542    \o Any QContactUnionFilters with a default QContactFilter contained will be replaced
       
   543      with a default QContactFilter
       
   544    \o An empty QContactIntersectionFilter will be replaced with a QContactDefaultFilter
       
   545    \o An empty QContactUnionFilter will be replaced with a QContactInvalidFilter
       
   546    \o An empty QContactLocalIdFilter will be replaced with a QContactInvalidFilter
       
   547    \o An intersection or union filter with a single entry will be replaced by that entry
       
   548    \o A QContactDetailFilter or QContactDetailRangeFilter with no definition name will be replaced with a QContactInvalidFilter
       
   549    \o A QContactDetailRangeFilter with no range specified will be converted to a QContactDetailFilter
       
   550   \endlist
       
   551 */
       
   552 QContactFilter QContactManagerEngine::canonicalizedFilter(const QContactFilter &filter)
       
   553 {
       
   554     switch(filter.type()) {
       
   555         case QContactFilter::ActionFilter:
       
   556         {
       
   557             // Find any matching actions, and do a union filter on their filter objects
       
   558             QContactActionFilter af(filter);
       
   559             QList<QContactActionDescriptor> descriptors = QContactAction::actionDescriptors(af.actionName(), af.vendorName(), af.implementationVersion());
       
   560 
       
   561             QList<QContactFilter> filters;
       
   562             // There's a small wrinkle if there's a value specified in the action filter
       
   563             // we have to adjust any contained QContactDetailFilters to have that value
       
   564             // or test if a QContactDetailRangeFilter contains this value already
       
   565             for (int j = 0; j < descriptors.count(); j++) {
       
   566                 QContactAction* action = QContactAction::action(descriptors.at(j));
       
   567 
       
   568                 // Action filters are not allowed to return action filters, at all
       
   569                 // it's too annoying to check for recursion
       
   570                 QContactFilter d = action->contactFilter(af.value());
       
   571                 delete action; // clean up.
       
   572                 if (!validateActionFilter(d))
       
   573                     continue;
       
   574 
       
   575                 filters.append(d);
       
   576             }
       
   577 
       
   578             if (filters.count() == 0)
       
   579                 return QContactInvalidFilter();
       
   580             if (filters.count() == 1)
       
   581                 return filters.first();
       
   582 
       
   583             QContactUnionFilter f;
       
   584             f.setFilters(filters);
       
   585             return canonicalizedFilter(f);
       
   586         }
       
   587         // unreachable
       
   588 
       
   589         case QContactFilter::IntersectionFilter:
       
   590         {
       
   591             QContactIntersectionFilter f(filter);
       
   592             QList<QContactFilter> filters = f.filters();
       
   593             QList<QContactFilter>::iterator it = filters.begin();
       
   594 
       
   595             // XXX in theory we can remove duplicates in a set filter
       
   596             while (it != filters.end()) {
       
   597                 QContactFilter canon = canonicalizedFilter(*it);
       
   598                 if (canon.type() == QContactFilter::DefaultFilter) {
       
   599                     it = filters.erase(it);
       
   600                 } else if (canon.type() == QContactFilter::InvalidFilter) {
       
   601                     return QContactInvalidFilter();
       
   602                 } else {
       
   603                     *it = canon;
       
   604                     ++it;
       
   605                 }
       
   606             }
       
   607 
       
   608             if (filters.count() == 0)
       
   609                 return QContactFilter();
       
   610             if (filters.count() == 1)
       
   611                 return filters.first();
       
   612 
       
   613             f.setFilters(filters);
       
   614             return f;
       
   615         }
       
   616         // unreachable
       
   617 
       
   618         case QContactFilter::UnionFilter:
       
   619         {
       
   620             QContactUnionFilter f(filter);
       
   621             QList<QContactFilter> filters = f.filters();
       
   622             QList<QContactFilter>::iterator it = filters.begin();
       
   623 
       
   624             // XXX in theory we can remove duplicates in a set filter
       
   625             while (it != filters.end()) {
       
   626                 QContactFilter canon = canonicalizedFilter(*it);
       
   627                 if (canon.type() == QContactFilter::InvalidFilter) {
       
   628                     it = filters.erase(it);
       
   629                 } else if (canon.type() == QContactFilter::DefaultFilter) {
       
   630                     return QContactFilter();
       
   631                 } else {
       
   632                     *it = canon;
       
   633                     ++it;
       
   634                 }
       
   635             }
       
   636 
       
   637             if (filters.count() == 0)
       
   638                 return QContactInvalidFilter();
       
   639             if (filters.count() == 1)
       
   640                 return filters.first();
       
   641 
       
   642             f.setFilters(filters);
       
   643             return f;
       
   644         }
       
   645         // unreachable
       
   646 
       
   647         case QContactFilter::LocalIdFilter:
       
   648         {
       
   649             QContactLocalIdFilter f(filter);
       
   650             if (f.ids().count() == 0)
       
   651                 return QContactInvalidFilter();
       
   652         }
       
   653         break; // fall through to return at end
       
   654 
       
   655         case QContactFilter::ContactDetailRangeFilter:
       
   656         {
       
   657             QContactDetailRangeFilter f(filter);
       
   658             if (f.detailDefinitionName().isEmpty())
       
   659                 return QContactInvalidFilter();
       
   660             if (f.minValue() == f.maxValue()
       
   661                 && f.rangeFlags() == (QContactDetailRangeFilter::ExcludeLower | QContactDetailRangeFilter::ExcludeUpper))
       
   662                 return QContactInvalidFilter();
       
   663             if ((f.minValue().isNull() && f.maxValue().isNull()) || (f.minValue() == f.maxValue())) {
       
   664                 QContactDetailFilter df;
       
   665                 df.setDetailDefinitionName(f.detailDefinitionName(), f.detailFieldName());
       
   666                 df.setMatchFlags(f.matchFlags());
       
   667                 df.setValue(f.minValue());
       
   668                 return df;
       
   669             }
       
   670         }
       
   671         break; // fall through to return at end
       
   672 
       
   673         case QContactFilter::ContactDetailFilter:
       
   674         {
       
   675             QContactDetailFilter f(filter);
       
   676             if (f.detailDefinitionName().isEmpty())
       
   677                 return QContactInvalidFilter();
       
   678         }
       
   679         break; // fall through to return at end
       
   680 
       
   681         default:
       
   682             break; // fall through to return at end
       
   683     }
       
   684     return filter;
       
   685 }
       
   686 
       
   687 
       
   688 /*!
       
   689   Returns a whether the supplied \a filter can be implemented
       
   690   natively by this engine.  If not, the base class implementation
       
   691   will emulate the functionality.
       
   692  */
       
   693 bool QContactManagerEngine::isFilterSupported(const QContactFilter& filter) const
       
   694 {
       
   695     Q_UNUSED(filter);
       
   696 
       
   697     return false;
       
   698 }
       
   699 
       
   700 /*!
       
   701   Returns the list of data types supported by this engine.
       
   702  */
       
   703 QList<QVariant::Type> QContactManagerEngine::supportedDataTypes() const
       
   704 {
       
   705     return QList<QVariant::Type>();
       
   706 }
       
   707 
       
   708 /*!
       
   709   Returns true if the manager supports the relationship type specified in \a relationshipType for
       
   710   contacts whose type is the given \a contactType.
       
   711 
       
   712   Note that some managers may support the relationship type for a contact in a limited manner
       
   713   (for example, only as the first contact in the relationship, or only as the second contact
       
   714   in the relationship).  In this case, it will still return true.  It will only return false
       
   715   if the relationship is entirely unsupported for the given type of contact.
       
   716  */
       
   717 bool QContactManagerEngine::isRelationshipTypeSupported(const QString& relationshipType, const QString& contactType) const
       
   718 {
       
   719     Q_UNUSED(relationshipType);
       
   720     Q_UNUSED(contactType);
       
   721 
       
   722     return false;
       
   723 }
       
   724 
       
   725 /*!
       
   726   Returns the list of contact types which are supported by this engine.
       
   727   This is a convenience function, equivalent to retrieving the allowable values
       
   728   for the \c QContactType::FieldType field of the QContactType definition
       
   729   which is valid in this engine.
       
   730  */
       
   731 QStringList QContactManagerEngine::supportedContactTypes() const
       
   732 {
       
   733     QContactManager::Error error;
       
   734     QList<QVariant> allowableVals = detailDefinition(QContactType::DefinitionName, QContactType::TypeContact, &error).fields().value(QContactType::FieldType).allowableValues();
       
   735     QStringList retn;
       
   736     for (int i = 0; i < allowableVals.size(); i++)
       
   737         retn += allowableVals.at(i).toString();
       
   738     return retn;
       
   739 }
       
   740 
       
   741 /*!
       
   742   \fn int QContactManagerEngine::managerVersion() const
       
   743 
       
   744   Returns the engine backend implementation version number
       
   745  */
       
   746 
       
   747 /*! Returns the base schema definitions */
       
   748 QMap<QString, QMap<QString, QContactDetailDefinition> > QContactManagerEngine::schemaDefinitions()
       
   749 {
       
   750     // This implementation provides the base schema.
       
   751     // The schema documentation (contactsschema.qdoc)
       
   752     // MUST BE KEPT UP TO DATE as definitions are added here.
       
   753 
       
   754     // the map we will eventually return
       
   755     QMap<QString, QContactDetailDefinition> retn;
       
   756 
       
   757     // local variables for reuse
       
   758     QMap<QString, QContactDetailFieldDefinition> fields;
       
   759     QContactDetailFieldDefinition f;
       
   760     QContactDetailDefinition d;
       
   761     QVariantList contexts;
       
   762     contexts << QString(QLatin1String(QContactDetail::ContextHome)) << QString(QLatin1String(QContactDetail::ContextWork)) << QString(QLatin1String(QContactDetail::ContextOther));
       
   763     QVariantList subTypes;
       
   764 
       
   765     // sync target
       
   766     d.setName(QContactSyncTarget::DefinitionName);
       
   767     fields.clear();
       
   768     f.setDataType(QVariant::String);
       
   769     f.setAllowableValues(QVariantList());
       
   770     fields.insert(QContactSyncTarget::FieldSyncTarget, f);
       
   771     f.setDataType(QVariant::StringList);
       
   772     f.setAllowableValues(contexts);
       
   773     fields.insert(QContactDetail::FieldContext, f);
       
   774     d.setFields(fields);
       
   775     d.setUnique(true);
       
   776     retn.insert(d.name(), d);
       
   777 
       
   778     // timestamp
       
   779     d.setName(QContactTimestamp::DefinitionName);
       
   780     fields.clear();
       
   781     f.setDataType(QVariant::DateTime);
       
   782     f.setAllowableValues(QVariantList());
       
   783     fields.insert(QContactTimestamp::FieldModificationTimestamp, f);
       
   784     fields.insert(QContactTimestamp::FieldCreationTimestamp, f);
       
   785     f.setDataType(QVariant::StringList);
       
   786     f.setAllowableValues(contexts);
       
   787     fields.insert(QContactDetail::FieldContext, f);
       
   788     d.setFields(fields);
       
   789     d.setUnique(true);
       
   790     retn.insert(d.name(), d);
       
   791 
       
   792     // type
       
   793     d.setName(QContactType::DefinitionName);
       
   794     fields.clear();
       
   795     f.setDataType(QVariant::String);
       
   796     subTypes.clear();
       
   797     subTypes << QString(QLatin1String(QContactType::TypeContact)) << QString(QLatin1String(QContactType::TypeGroup));
       
   798     f.setAllowableValues(subTypes);
       
   799     fields.insert(QContactType::FieldType, f); // note: NO CONTEXT!!
       
   800     d.setFields(fields);
       
   801     d.setUnique(true);
       
   802     retn.insert(d.name(), d);
       
   803 
       
   804     // guid
       
   805     d.setName(QContactGuid::DefinitionName);
       
   806     fields.clear();
       
   807     f.setDataType(QVariant::String);
       
   808     f.setAllowableValues(QVariantList());
       
   809     fields.insert(QContactGuid::FieldGuid, f);
       
   810     f.setDataType(QVariant::StringList);
       
   811     f.setAllowableValues(contexts);
       
   812     fields.insert(QContactDetail::FieldContext, f);
       
   813     d.setFields(fields);
       
   814     d.setUnique(false);
       
   815     retn.insert(d.name(), d);
       
   816 
       
   817     // display label
       
   818     d.setName(QContactDisplayLabel::DefinitionName);
       
   819     fields.clear();
       
   820     f.setDataType(QVariant::String);
       
   821     f.setAllowableValues(QVariantList());
       
   822     fields.insert(QContactDisplayLabel::FieldLabel, f);
       
   823     d.setFields(fields);
       
   824     d.setUnique(true);
       
   825     retn.insert(d.name(), d);
       
   826 
       
   827     // email address
       
   828     d.setName(QContactEmailAddress::DefinitionName);
       
   829     fields.clear();
       
   830     f.setDataType(QVariant::String);
       
   831     f.setAllowableValues(QVariantList());
       
   832     fields.insert(QContactEmailAddress::FieldEmailAddress, f);
       
   833     f.setDataType(QVariant::StringList);
       
   834     f.setAllowableValues(contexts);
       
   835     fields.insert(QContactDetail::FieldContext, f);
       
   836     d.setFields(fields);
       
   837     d.setUnique(false);
       
   838     retn.insert(d.name(), d);
       
   839 
       
   840     // organisation
       
   841     d.setName(QContactOrganization::DefinitionName);
       
   842     fields.clear();
       
   843     f.setDataType(QVariant::String);
       
   844     f.setAllowableValues(QVariantList());
       
   845     fields.insert(QContactOrganization::FieldName, f);
       
   846     fields.insert(QContactOrganization::FieldLocation, f);
       
   847     fields.insert(QContactOrganization::FieldTitle, f);
       
   848     f.setDataType(QVariant::Url);
       
   849     fields.insert(QContactOrganization::FieldLogoUrl, f);
       
   850     f.setDataType(QVariant::StringList);
       
   851     fields.insert(QContactOrganization::FieldDepartment, f);
       
   852     f.setAllowableValues(contexts);
       
   853     fields.insert(QContactDetail::FieldContext, f);
       
   854     d.setFields(fields);
       
   855     d.setUnique(false);
       
   856     retn.insert(d.name(), d);
       
   857 
       
   858     // phone number
       
   859     d.setName(QContactPhoneNumber::DefinitionName);
       
   860     fields.clear();
       
   861     f.setDataType(QVariant::String);
       
   862     f.setAllowableValues(QVariantList());
       
   863     fields.insert(QContactPhoneNumber::FieldNumber, f);
       
   864     f.setDataType(QVariant::StringList); // can implement multiple subtypes
       
   865     subTypes.clear();
       
   866     subTypes << QString(QLatin1String(QContactPhoneNumber::SubTypeAssistant));
       
   867     subTypes << QString(QLatin1String(QContactPhoneNumber::SubTypeBulletinBoardSystem));
       
   868     subTypes << QString(QLatin1String(QContactPhoneNumber::SubTypeCar));
       
   869     subTypes << QString(QLatin1String(QContactPhoneNumber::SubTypeDtmfMenu));
       
   870     subTypes << QString(QLatin1String(QContactPhoneNumber::SubTypeFax));
       
   871     subTypes << QString(QLatin1String(QContactPhoneNumber::SubTypeLandline));
       
   872     subTypes << QString(QLatin1String(QContactPhoneNumber::SubTypeMessagingCapable));
       
   873     subTypes << QString(QLatin1String(QContactPhoneNumber::SubTypeMobile));
       
   874     subTypes << QString(QLatin1String(QContactPhoneNumber::SubTypeModem));
       
   875     subTypes << QString(QLatin1String(QContactPhoneNumber::SubTypePager));
       
   876     subTypes << QString(QLatin1String(QContactPhoneNumber::SubTypeVideo));
       
   877     subTypes << QString(QLatin1String(QContactPhoneNumber::SubTypeVoice));
       
   878     f.setAllowableValues(subTypes);
       
   879     fields.insert(QContactPhoneNumber::FieldSubTypes, f);
       
   880     f.setDataType(QVariant::StringList);
       
   881     f.setAllowableValues(contexts);
       
   882     fields.insert(QContactDetail::FieldContext, f);
       
   883     d.setFields(fields);
       
   884     d.setUnique(false);
       
   885     retn.insert(d.name(), d);
       
   886 
       
   887     // anniversary
       
   888     d.setName(QContactAnniversary::DefinitionName);
       
   889     fields.clear();
       
   890     f.setDataType(QVariant::Date);
       
   891     f.setAllowableValues(QVariantList());
       
   892     fields.insert(QContactAnniversary::FieldOriginalDate, f);
       
   893     f.setDataType(QVariant::String);
       
   894     f.setAllowableValues(QVariantList());
       
   895     fields.insert(QContactAnniversary::FieldCalendarId, f);
       
   896     f.setDataType(QVariant::String);
       
   897     f.setAllowableValues(QVariantList());
       
   898     fields.insert(QContactAnniversary::FieldEvent, f);
       
   899     f.setDataType(QVariant::String); // only allowed to be a single subtype.
       
   900     subTypes.clear();
       
   901     subTypes << QString(QLatin1String(QContactAnniversary::SubTypeEmployment));
       
   902     subTypes << QString(QLatin1String(QContactAnniversary::SubTypeEngagement));
       
   903     subTypes << QString(QLatin1String(QContactAnniversary::SubTypeHouse));
       
   904     subTypes << QString(QLatin1String(QContactAnniversary::SubTypeMemorial));
       
   905     subTypes << QString(QLatin1String(QContactAnniversary::SubTypeWedding));
       
   906     f.setAllowableValues(subTypes);
       
   907     fields.insert(QContactAnniversary::FieldSubType, f);
       
   908     f.setDataType(QVariant::StringList);
       
   909     f.setAllowableValues(contexts);
       
   910     fields.insert(QContactDetail::FieldContext, f);
       
   911     d.setFields(fields);
       
   912     d.setUnique(false);
       
   913     retn.insert(d.name(), d);
       
   914 
       
   915     // birthday
       
   916     d.setName(QContactBirthday::DefinitionName);
       
   917     fields.clear();
       
   918     f.setDataType(QVariant::Date);
       
   919     f.setAllowableValues(QVariantList());
       
   920     fields.insert(QContactBirthday::FieldBirthday, f);
       
   921     f.setDataType(QVariant::StringList);
       
   922     f.setAllowableValues(contexts);
       
   923     fields.insert(QContactDetail::FieldContext, f);
       
   924     d.setFields(fields);
       
   925     d.setUnique(true);
       
   926     retn.insert(d.name(), d);
       
   927 
       
   928     // nickname
       
   929     d.setName(QContactNickname::DefinitionName);
       
   930     fields.clear();
       
   931     f.setDataType(QVariant::String);
       
   932     f.setAllowableValues(QVariantList());
       
   933     fields.insert(QContactNickname::FieldNickname, f);
       
   934     f.setDataType(QVariant::StringList);
       
   935     f.setAllowableValues(contexts);
       
   936     fields.insert(QContactDetail::FieldContext, f);
       
   937     d.setFields(fields);
       
   938     d.setUnique(false);
       
   939     retn.insert(d.name(), d);
       
   940 
       
   941     // note
       
   942     fields.clear();
       
   943     f.setDataType(QVariant::String);
       
   944     f.setAllowableValues(QVariantList());
       
   945     d.setName(QContactNote::DefinitionName);
       
   946     fields.insert(QContactNote::FieldNote, f);
       
   947     f.setDataType(QVariant::StringList);
       
   948     f.setAllowableValues(contexts);
       
   949     fields.insert(QContactDetail::FieldContext, f);
       
   950     d.setFields(fields);
       
   951     d.setUnique(false);
       
   952     retn.insert(d.name(), d);
       
   953 
       
   954     // url
       
   955     d.setName(QContactUrl::DefinitionName);
       
   956     fields.clear();
       
   957     f.setDataType(QVariant::String);
       
   958     f.setAllowableValues(QVariantList());
       
   959     fields.insert(QContactUrl::FieldUrl, f);
       
   960     f.setDataType(QVariant::String); // only allowed to be a single subtype
       
   961     subTypes.clear();
       
   962     subTypes << QString(QLatin1String(QContactUrl::SubTypeFavourite));
       
   963     subTypes << QString(QLatin1String(QContactUrl::SubTypeHomePage));
       
   964     f.setAllowableValues(subTypes);
       
   965     fields.insert(QContactUrl::FieldSubType, f);
       
   966     f.setDataType(QVariant::StringList);
       
   967     f.setAllowableValues(contexts);
       
   968     fields.insert(QContactDetail::FieldContext, f);
       
   969     d.setFields(fields);
       
   970     d.setUnique(false);
       
   971     retn.insert(d.name(), d);
       
   972 
       
   973     // gender
       
   974     d.setName(QContactGender::DefinitionName);
       
   975     fields.clear();
       
   976     f.setDataType(QVariant::String);
       
   977     f.setAllowableValues(QVariantList() << QString(QLatin1String(QContactGender::GenderMale)) << QString(QLatin1String(QContactGender::GenderFemale)) << QString(QLatin1String(QContactGender::GenderUnspecified)));
       
   978     fields.insert(QContactGender::FieldGender, f);
       
   979     f.setDataType(QVariant::StringList);
       
   980     f.setAllowableValues(contexts);
       
   981     fields.insert(QContactDetail::FieldContext, f);
       
   982     d.setFields(fields);
       
   983     d.setUnique(false);
       
   984     retn.insert(d.name(), d);
       
   985 
       
   986     // online account
       
   987     d.setName(QContactOnlineAccount::DefinitionName);
       
   988     fields.clear();
       
   989     f.setAllowableValues(QVariantList());
       
   990     f.setDataType(QVariant::String);
       
   991     fields.insert(QContactOnlineAccount::FieldAccountUri, f);
       
   992     f.setDataType(QVariant::StringList);
       
   993     fields.insert(QContactOnlineAccount::FieldCapabilities, f);
       
   994     f.setDataType(QVariant::String);
       
   995     fields.insert(QContactOnlineAccount::FieldAccountUri, f);
       
   996     fields.insert(QContactOnlineAccount::FieldServiceProvider, f);
       
   997     f.setDataType(QVariant::StringList);
       
   998     f.setAllowableValues(contexts);
       
   999     fields.insert(QContactDetail::FieldContext, f);
       
  1000     f.setAllowableValues(QVariantList()); // allow any subtypes!
       
  1001     fields.insert(QContactOnlineAccount::FieldSubTypes, f);
       
  1002     d.setFields(fields);
       
  1003     d.setUnique(false);
       
  1004     retn.insert(d.name(), d);
       
  1005 
       
  1006     // presence
       
  1007     d.setName(QContactPresence::DefinitionName);
       
  1008     fields.clear();
       
  1009     f.setAllowableValues(QVariantList());
       
  1010     f.setDataType(QVariant::DateTime);
       
  1011     fields.insert(QContactPresence::FieldTimestamp, f);
       
  1012     f.setDataType(QVariant::String);
       
  1013     fields.insert(QContactPresence::FieldNickname, f);
       
  1014     fields.insert(QContactPresence::FieldCustomMessage, f);
       
  1015     fields.insert(QContactPresence::FieldPresenceStateText, f);
       
  1016     QVariantList presenceValues;
       
  1017     presenceValues << QContactPresence::PresenceAvailable;
       
  1018     presenceValues << QContactPresence::PresenceAway;
       
  1019     presenceValues << QContactPresence::PresenceBusy;
       
  1020     presenceValues << QContactPresence::PresenceExtendedAway;
       
  1021     presenceValues << QContactPresence::PresenceHidden;
       
  1022     presenceValues << QContactPresence::PresenceOffline;
       
  1023     presenceValues << QContactPresence::PresenceUnknown;
       
  1024     f.setAllowableValues(presenceValues);
       
  1025     f.setDataType(QVariant::Int);
       
  1026     fields.insert(QContactPresence::FieldPresenceState, f);
       
  1027     f.setAllowableValues(QVariantList());
       
  1028     f.setDataType(QVariant::Url);
       
  1029     fields.insert(QContactPresence::FieldPresenceStateImageUrl, f);
       
  1030     f.setDataType(QVariant::StringList);
       
  1031     f.setAllowableValues(contexts);
       
  1032     fields.insert(QContactDetail::FieldContext, f);
       
  1033     d.setFields(fields);
       
  1034     d.setUnique(false);
       
  1035     retn.insert(d.name(), d);
       
  1036 
       
  1037     // global presence
       
  1038     d.setName(QContactGlobalPresence::DefinitionName);
       
  1039     fields.clear();
       
  1040     f.setAllowableValues(QVariantList());
       
  1041     f.setDataType(QVariant::DateTime);
       
  1042     fields.insert(QContactGlobalPresence::FieldTimestamp, f);
       
  1043     f.setDataType(QVariant::String);
       
  1044     fields.insert(QContactGlobalPresence::FieldNickname, f);
       
  1045     fields.insert(QContactGlobalPresence::FieldCustomMessage, f);
       
  1046     fields.insert(QContactGlobalPresence::FieldPresenceStateText, f);
       
  1047     f.setAllowableValues(presenceValues);
       
  1048     f.setDataType(QVariant::Int);
       
  1049     fields.insert(QContactGlobalPresence::FieldPresenceState, f);
       
  1050     f.setAllowableValues(QVariantList());
       
  1051     f.setDataType(QVariant::Url);
       
  1052     fields.insert(QContactGlobalPresence::FieldPresenceStateImageUrl, f);
       
  1053     f.setDataType(QVariant::StringList);
       
  1054     f.setAllowableValues(contexts);
       
  1055     fields.insert(QContactDetail::FieldContext, f);
       
  1056     d.setFields(fields);
       
  1057     d.setUnique(true); // unique and read only!
       
  1058     retn.insert(d.name(), d);
       
  1059 
       
  1060     // avatar
       
  1061     d.setName(QContactAvatar::DefinitionName);
       
  1062     fields.clear();
       
  1063     f.setDataType(QVariant::Url);
       
  1064     f.setAllowableValues(QVariantList());
       
  1065     fields.insert(QContactAvatar::FieldImageUrl, f);
       
  1066     fields.insert(QContactAvatar::FieldVideoUrl, f);
       
  1067     f.setDataType(QVariant::StringList);
       
  1068     f.setAllowableValues(contexts);
       
  1069     fields.insert(QContactDetail::FieldContext, f);
       
  1070     d.setFields(fields);
       
  1071     d.setUnique(false);
       
  1072     retn.insert(d.name(), d);
       
  1073 
       
  1074     // ringtone
       
  1075     d.setName(QContactRingtone::DefinitionName);
       
  1076     fields.clear();
       
  1077     f.setDataType(QVariant::Url);
       
  1078     f.setAllowableValues(QVariantList());
       
  1079     fields.insert(QContactRingtone::FieldAudioRingtoneUrl, f);
       
  1080     fields.insert(QContactRingtone::FieldVideoRingtoneUrl, f);
       
  1081     fields.insert(QContactRingtone::FieldVibrationRingtoneUrl, f);
       
  1082     f.setDataType(QVariant::StringList);
       
  1083     f.setAllowableValues(contexts);
       
  1084     fields.insert(QContactDetail::FieldContext, f);
       
  1085     d.setFields(fields);
       
  1086     d.setUnique(false);
       
  1087     retn.insert(d.name(), d);
       
  1088 
       
  1089     // thumbnail
       
  1090     d.setName(QContactThumbnail::DefinitionName);
       
  1091     fields.clear();
       
  1092     f.setDataType(QVariant::Image);
       
  1093     f.setAllowableValues(QVariantList());
       
  1094     fields.insert(QContactThumbnail::FieldThumbnail, f);
       
  1095     d.setFields(fields);
       
  1096     d.setUnique(true); // only one thumbnail, no context.
       
  1097     retn.insert(d.name(), d);
       
  1098 
       
  1099     // GeoLocation
       
  1100     d.setName(QContactGeoLocation::DefinitionName);
       
  1101     fields.clear();
       
  1102     f.setDataType(QVariant::String);
       
  1103     f.setAllowableValues(QVariantList());
       
  1104     fields.insert(QContactGeoLocation::FieldLabel, f);
       
  1105     f.setDataType(QVariant::Double);
       
  1106     fields.insert(QContactGeoLocation::FieldLatitude, f);
       
  1107     fields.insert(QContactGeoLocation::FieldLongitude, f);
       
  1108     fields.insert(QContactGeoLocation::FieldAccuracy, f);
       
  1109     fields.insert(QContactGeoLocation::FieldAltitude, f);
       
  1110     fields.insert(QContactGeoLocation::FieldAltitudeAccuracy, f);
       
  1111     fields.insert(QContactGeoLocation::FieldSpeed, f);
       
  1112     fields.insert(QContactGeoLocation::FieldHeading, f);
       
  1113     f.setDataType(QVariant::DateTime);
       
  1114     fields.insert(QContactGeoLocation::FieldTimestamp, f);
       
  1115     f.setDataType(QVariant::StringList);
       
  1116     f.setAllowableValues(contexts);
       
  1117     fields.insert(QContactDetail::FieldContext, f);
       
  1118     d.setFields(fields);
       
  1119     d.setUnique(false);
       
  1120     retn.insert(d.name(), d);
       
  1121 
       
  1122     // street address
       
  1123     d.setName(QContactAddress::DefinitionName);
       
  1124     fields.clear();
       
  1125     f.setDataType(QVariant::String);
       
  1126     f.setAllowableValues(QVariantList());
       
  1127     fields.insert(QContactAddress::FieldPostOfficeBox, f);
       
  1128     fields.insert(QContactAddress::FieldStreet, f);
       
  1129     fields.insert(QContactAddress::FieldLocality, f);
       
  1130     fields.insert(QContactAddress::FieldRegion, f);
       
  1131     fields.insert(QContactAddress::FieldPostcode, f);
       
  1132     fields.insert(QContactAddress::FieldCountry, f);
       
  1133     f.setDataType(QVariant::StringList); // can implement multiple subtypes
       
  1134     subTypes.clear();
       
  1135     subTypes << QString(QLatin1String(QContactAddress::SubTypeDomestic));
       
  1136     subTypes << QString(QLatin1String(QContactAddress::SubTypeInternational));
       
  1137     subTypes << QString(QLatin1String(QContactAddress::SubTypeParcel));
       
  1138     subTypes << QString(QLatin1String(QContactAddress::SubTypePostal));
       
  1139     f.setAllowableValues(subTypes);
       
  1140     fields.insert(QContactAddress::FieldSubTypes, f);
       
  1141     f.setDataType(QVariant::StringList);
       
  1142     f.setAllowableValues(contexts);
       
  1143     fields.insert(QContactDetail::FieldContext, f);
       
  1144     d.setFields(fields);
       
  1145     d.setUnique(false);
       
  1146     retn.insert(d.name(), d);
       
  1147 
       
  1148     // name
       
  1149     d.setName(QContactName::DefinitionName);
       
  1150     fields.clear();
       
  1151     f.setDataType(QVariant::String);
       
  1152     f.setAllowableValues(QVariantList());
       
  1153     fields.insert(QContactName::FieldPrefix, f);
       
  1154     fields.insert(QContactName::FieldFirstName, f);
       
  1155     fields.insert(QContactName::FieldMiddleName, f);
       
  1156     fields.insert(QContactName::FieldLastName, f);
       
  1157     fields.insert(QContactName::FieldSuffix, f);
       
  1158     fields.insert(QContactName::FieldCustomLabel, f);
       
  1159     f.setDataType(QVariant::StringList);
       
  1160     f.setAllowableValues(contexts);
       
  1161     fields.insert(QContactDetail::FieldContext, f);
       
  1162     d.setFields(fields);
       
  1163     d.setUnique(false);
       
  1164     retn.insert(d.name(), d);
       
  1165 
       
  1166     // tag
       
  1167     d.setName(QContactTag::DefinitionName);
       
  1168     fields.clear();
       
  1169     f.setDataType(QVariant::String);
       
  1170     f.setAllowableValues(QVariantList());
       
  1171     fields.insert(QContactTag::FieldTag, f);
       
  1172     f.setDataType(QVariant::StringList);
       
  1173     f.setAllowableValues(contexts);
       
  1174     fields.insert(QContactDetail::FieldContext, f);
       
  1175     d.setFields(fields);
       
  1176     d.setUnique(false);
       
  1177     retn.insert(d.name(), d);
       
  1178 
       
  1179     // in the default schema, we have two contact types: TypeContact, TypeGroup.
       
  1180     // the entire default schema is valid for both types.
       
  1181     QMap<QString, QMap<QString, QContactDetailDefinition> > retnSchema;
       
  1182     retnSchema.insert(QContactType::TypeContact, retn);
       
  1183     retnSchema.insert(QContactType::TypeGroup, retn);
       
  1184 
       
  1185     return retnSchema;
       
  1186 }
       
  1187 
       
  1188 /*!
       
  1189   Checks that the given contact \a contact does not have details which
       
  1190   don't conform to a valid definition, violate uniqueness constraints,
       
  1191   or contain values for nonexistent fields, and that the values contained are
       
  1192   of the correct type for each field, and are allowable values for that field.
       
  1193 
       
  1194   Note that this function is unable to ensure that the access constraints
       
  1195   (such as CreateOnly and ReadOnly) are observed; backend specific code
       
  1196   must be written if you wish to enforce these constraints.
       
  1197 
       
  1198   Returns true if the \a contact is valid according to the definitions for
       
  1199   its details, otherwise returns false.
       
  1200 
       
  1201   Any errors encountered during this operation should be stored to
       
  1202   \a error.
       
  1203  */
       
  1204 bool QContactManagerEngine::validateContact(const QContact& contact, QContactManager::Error* error) const
       
  1205 {
       
  1206     QList<QString> uniqueDefinitionIds;
       
  1207 
       
  1208     // check that each detail conforms to its definition as supported by this manager.
       
  1209     foreach (const QContactDetail& detail, contact.details()) {
       
  1210         QVariantMap values = detail.variantValues();
       
  1211         QContactDetailDefinition def = detailDefinition(detail.definitionName(), contact.type(), error);
       
  1212         // check that the definition is supported
       
  1213         if (*error != QContactManager::NoError) {
       
  1214             *error = QContactManager::InvalidDetailError;
       
  1215             return false; // this definition is not supported.
       
  1216         }
       
  1217 
       
  1218         // check uniqueness
       
  1219         if (def.isUnique()) {
       
  1220             if (uniqueDefinitionIds.contains(def.name())) {
       
  1221                 *error = QContactManager::AlreadyExistsError;
       
  1222                 return false; // can't have two of a unique detail.
       
  1223             }
       
  1224             uniqueDefinitionIds.append(def.name());
       
  1225         }
       
  1226 
       
  1227         QMapIterator<QString,QVariant> fieldIt(values);
       
  1228         while (fieldIt.hasNext()) {
       
  1229             fieldIt.next();
       
  1230             const QString& key = fieldIt.key();
       
  1231             const QVariant& variant = fieldIt.value();
       
  1232             // check that no values exist for nonexistent fields.
       
  1233             if (!def.fields().contains(key)) {
       
  1234                 *error = QContactManager::InvalidDetailError;
       
  1235                 return false; // value for nonexistent field.
       
  1236             }
       
  1237 
       
  1238             QContactDetailFieldDefinition field = def.fields().value(key);
       
  1239             // check that the type of each value corresponds to the allowable field type
       
  1240             if (static_cast<int>(field.dataType()) != variant.userType()) {
       
  1241                 *error = QContactManager::InvalidDetailError;
       
  1242                 return false; // type doesn't match.
       
  1243             }
       
  1244 
       
  1245             // check that the value is allowable
       
  1246             // if the allowable values is an empty list, any are allowed.
       
  1247             if (!field.allowableValues().isEmpty()) {
       
  1248                 // if the field datatype is a list, check that it contains only allowable values
       
  1249                 if (field.dataType() == QVariant::List || field.dataType() == QVariant::StringList) {
       
  1250                     QList<QVariant> innerValues = variant.toList();
       
  1251                     QListIterator<QVariant> it(innerValues);
       
  1252                     while (it.hasNext()) {
       
  1253                         if (!field.allowableValues().contains(it.next())) {
       
  1254                             *error = QContactManager::InvalidDetailError;
       
  1255                             return false; // value not allowed.
       
  1256                         }
       
  1257                     }
       
  1258                 } else if (!field.allowableValues().contains(variant)) {
       
  1259                     // the datatype is not a list; the value wasn't allowed.
       
  1260                     *error = QContactManager::InvalidDetailError;
       
  1261                     return false; // value not allowed.
       
  1262                 }
       
  1263             }
       
  1264         }
       
  1265     }
       
  1266 
       
  1267     return true;
       
  1268 }
       
  1269 
       
  1270 /*!
       
  1271   Checks that the given detail definition \a definition seems valid,
       
  1272   with a correct id, defined fields, and any specified value types
       
  1273   are supported by this engine.  This function is called before
       
  1274   trying to save a definition.
       
  1275 
       
  1276   Returns true if the \a definition seems valid, otherwise returns
       
  1277   false.
       
  1278 
       
  1279   Any errors encountered during this operation should be stored to
       
  1280   \a error.
       
  1281  */
       
  1282 bool QContactManagerEngine::validateDefinition(const QContactDetailDefinition& definition, QContactManager::Error* error) const
       
  1283 {
       
  1284     if (definition.name().isEmpty()) {
       
  1285         *error = QContactManager::BadArgumentError;
       
  1286         return false;
       
  1287     }
       
  1288 
       
  1289     if (definition.fields().count() == 0) {
       
  1290         *error = QContactManager::BadArgumentError;
       
  1291         return false;
       
  1292     }
       
  1293 
       
  1294     // Check each field now
       
  1295     QList<QVariant::Type> types = supportedDataTypes();
       
  1296     QMapIterator<QString, QContactDetailFieldDefinition> it(definition.fields());
       
  1297     while(it.hasNext()) {
       
  1298         it.next();
       
  1299         if (it.key().isEmpty()) {
       
  1300             *error = QContactManager::BadArgumentError;
       
  1301             return false;
       
  1302         }
       
  1303 
       
  1304         if (!types.contains(it.value().dataType())) {
       
  1305             *error = QContactManager::BadArgumentError;
       
  1306             return false;
       
  1307         }
       
  1308 
       
  1309         // Check that each allowed value is the same type
       
  1310         for (int i=0; i < it.value().allowableValues().count(); i++) {
       
  1311             if (it.value().allowableValues().at(i).type() != it.value().dataType()) {
       
  1312                 *error = QContactManager::BadArgumentError;
       
  1313                 return false;
       
  1314             }
       
  1315         }
       
  1316     }
       
  1317     *error = QContactManager::NoError;
       
  1318     return true;
       
  1319 }
       
  1320 
       
  1321 /*!
       
  1322   Returns the registered detail definitions which are valid for contacts whose type is of the given \a contactType in this engine.
       
  1323 
       
  1324   Any errors encountered during this operation should be stored to
       
  1325   \a error.
       
  1326  */
       
  1327 QMap<QString, QContactDetailDefinition> QContactManagerEngine::detailDefinitions(const QString& contactType, QContactManager::Error* error) const
       
  1328 {
       
  1329     Q_UNUSED(contactType);
       
  1330     *error = QContactManager::NotSupportedError;
       
  1331     return QMap<QString, QContactDetailDefinition>();
       
  1332 }
       
  1333 
       
  1334 /*!
       
  1335   Returns the definition identified by the given \a definitionName that
       
  1336   is valid for contacts whose type is of the given \a contactType in this store, or a default-constructed QContactDetailDefinition
       
  1337   if no such definition exists
       
  1338 
       
  1339   Any errors encountered during this operation should be stored to
       
  1340   \a error.
       
  1341  */
       
  1342 QContactDetailDefinition QContactManagerEngine::detailDefinition(const QString& definitionName, const QString& contactType, QContactManager::Error* error) const
       
  1343 {
       
  1344     QMap<QString, QContactDetailDefinition> definitions = detailDefinitions(contactType, error);
       
  1345     if (definitions.contains(definitionName))  {
       
  1346         *error = QContactManager::NoError;
       
  1347         return definitions.value(definitionName);
       
  1348     } else {
       
  1349         *error = QContactManager::DoesNotExistError;
       
  1350         return QContactDetailDefinition();
       
  1351     }
       
  1352 }
       
  1353 
       
  1354 /*!
       
  1355   Persists the given definition \a def in the database, which is valid for contacts whose type is the given \a contactType.
       
  1356 
       
  1357   Returns true if the definition was saved successfully, and otherwise returns false.
       
  1358 
       
  1359   The backend must emit the appropriate signals to inform clients of changes
       
  1360   to the database resulting from this operation.
       
  1361 
       
  1362   Any errors encountered during this operation should be stored to
       
  1363   \a error.
       
  1364  */
       
  1365 bool QContactManagerEngine::saveDetailDefinition(const QContactDetailDefinition& def, const QString& contactType, QContactManager::Error* error)
       
  1366 {
       
  1367     Q_UNUSED(def);
       
  1368     Q_UNUSED(contactType);
       
  1369 
       
  1370     *error = QContactManager::NotSupportedError;
       
  1371     return false;
       
  1372 }
       
  1373 
       
  1374 /*!
       
  1375   Removes the definition identified by the given \a definitionName from the database, where it was valid for contacts whose type was the given \a contactType.
       
  1376 
       
  1377   Returns true if the definition was removed successfully, otherwise returns false.
       
  1378 
       
  1379   The backend must emit the appropriate signals to inform clients of changes
       
  1380   to the database resulting from this operation.
       
  1381 
       
  1382   Any errors encountered during this operation should be stored to
       
  1383   \a error.
       
  1384  */
       
  1385 bool QContactManagerEngine::removeDetailDefinition(const QString& definitionName, const QString& contactType, QContactManager::Error* error)
       
  1386 {
       
  1387     Q_UNUSED(definitionName);
       
  1388     Q_UNUSED(contactType);
       
  1389 
       
  1390     *error = QContactManager::NotSupportedError;
       
  1391     return false;
       
  1392 }
       
  1393 
       
  1394 /*!
       
  1395   Sets the access constraints of \a detail to the supplied \a constraints.
       
  1396 
       
  1397   This function is provided to allow engine implementations to report the
       
  1398   access constraints of retrieved details, without generally allowing the
       
  1399   access constraints to be modified after retrieval.
       
  1400 
       
  1401   Application code should not call this function, since validation of the
       
  1402   detail will happen in the engine in any case.
       
  1403  */
       
  1404 void QContactManagerEngine::setDetailAccessConstraints(QContactDetail *detail, QContactDetail::AccessConstraints constraints)
       
  1405 {
       
  1406     if (detail) {
       
  1407         QContactDetailPrivate::setAccessConstraints(detail, constraints);
       
  1408     }
       
  1409 }
       
  1410 
       
  1411 
       
  1412 /*!
       
  1413   Adds the given \a contact to the database if \a contact has a
       
  1414   default-constructed id, or an id with the manager URI set to the URI of
       
  1415   this manager and a local id of zero, otherwise updates the contact in
       
  1416   the database which has the same id to be the given \a contact.
       
  1417   If the id is non-zero but does not identify any contact stored in the
       
  1418   manager, the function will return false and \a error will be set to
       
  1419   \c QContactManager::DoesNotExistError.
       
  1420 
       
  1421   Returns true if the save operation completed successfully, otherwise
       
  1422   returns false.  Any error which occurs will be saved in \a error.
       
  1423 
       
  1424   The default implementation will convert this into a call to saveContacts.
       
  1425 
       
  1426   \sa managerUri()
       
  1427  */
       
  1428 bool QContactManagerEngine::saveContact(QContact* contact, QContactManager::Error* error)
       
  1429 {
       
  1430     // Convert to a list op
       
  1431     if (contact) {
       
  1432         QList<QContact> list;
       
  1433         list.append(*contact);
       
  1434 
       
  1435         QMap<int, QContactManager::Error> errors;
       
  1436         bool ret = saveContacts(&list, &errors, error);
       
  1437 
       
  1438         if (errors.count() > 0)
       
  1439             *error = errors.begin().value();
       
  1440 
       
  1441         *contact = list.value(0);
       
  1442         return ret;
       
  1443     } else {
       
  1444         *error = QContactManager::BadArgumentError;
       
  1445         return false;
       
  1446     }
       
  1447 }
       
  1448 
       
  1449 /*!
       
  1450   Remove the contact identified by \a contactId from the database,
       
  1451   and also removes any relationships in which the contact was involved.
       
  1452   Returns true if the contact was removed successfully, otherwise
       
  1453   returns false.
       
  1454 
       
  1455   Any error which occurs will be saved in \a error.
       
  1456 
       
  1457   The default implementation will convert this into a call to removeContacts.
       
  1458  */
       
  1459 bool QContactManagerEngine::removeContact(const QContactLocalId& contactId, QContactManager::Error* error)
       
  1460 {
       
  1461     // Convert to a list op
       
  1462     QList<QContactLocalId> list;
       
  1463     list.append(contactId);
       
  1464 
       
  1465     QMap<int, QContactManager::Error> errors;
       
  1466     bool ret = removeContacts(list, &errors, error);
       
  1467 
       
  1468     if (errors.count() > 0)
       
  1469         *error = errors.begin().value();
       
  1470 
       
  1471     return ret;
       
  1472 }
       
  1473 
       
  1474 /*!
       
  1475   Adds the list of contacts given by \a contacts list to the database.
       
  1476   Returns true if the contacts were saved successfully, otherwise false.
       
  1477 
       
  1478   The manager might populate \a errorMap (the map of indices of the \a contacts list to
       
  1479   the error which occurred when saving the contact at that index) for
       
  1480   every index for which the contact could not be saved, if it is able.
       
  1481 
       
  1482   The supplied \a errorMap parameter may be null, if the client does not desire detailed error information.
       
  1483   If supplied, it will be empty upon entry to this function.
       
  1484 
       
  1485   The \l QContactManager::error() function will only return \c QContactManager::NoError
       
  1486   if all contacts were saved successfully.
       
  1487 
       
  1488   For each newly saved contact that was successful, the id of the contact
       
  1489   in the \a contacts list will be updated with the new value.  If a failure occurs
       
  1490   when saving a new contact, the id will be cleared.
       
  1491 
       
  1492   Any errors encountered during this operation should be stored to
       
  1493   \a error.
       
  1494 
       
  1495   \sa QContactManager::saveContact()
       
  1496  */
       
  1497 bool QContactManagerEngine::saveContacts(QList<QContact>* contacts, QMap<int, QContactManager::Error>* errorMap, QContactManager::Error* error)
       
  1498 {
       
  1499     Q_UNUSED(contacts);
       
  1500     Q_UNUSED(errorMap);
       
  1501     *error = QContactManager::NotSupportedError;
       
  1502     return false;
       
  1503 }
       
  1504 
       
  1505 /*!
       
  1506   Remove every contact whose id is contained in the list of contacts ids
       
  1507   \a contactIds.  Returns true if all contacts were removed successfully,
       
  1508   otherwise false.
       
  1509 
       
  1510   Any contact that was removed successfully will have the relationships
       
  1511   in which it was involved removed also.
       
  1512 
       
  1513   The manager might populate \a errorMap (the map of indices of the \a contactIds list to
       
  1514   the error which occurred when saving the contact at that index) for every
       
  1515   index for which the contact could not be removed, if it is able.
       
  1516 
       
  1517   The supplied \a errorMap parameter may be null, if the client does not desire detailed error information.
       
  1518   If supplied, it will be empty upon entry to this function.
       
  1519 
       
  1520   The \l QContactManager::error() function will
       
  1521   only return \c QContactManager::NoError if all contacts were removed
       
  1522   successfully.
       
  1523 
       
  1524   If the list contains ids which do not identify a valid contact in the manager, the function will
       
  1525   remove any contacts which are identified by ids in the \a contactIds list, insert
       
  1526   \c QContactManager::DoesNotExist entries into the \a errorMap for the indices of invalid ids
       
  1527   in the \a contactIds list, return false, and set the overall operation error to
       
  1528   \c QContactManager::DoesNotExistError.
       
  1529 
       
  1530   Any errors encountered during this operation should be stored to
       
  1531   \a error.
       
  1532 
       
  1533   \sa QContactManager::removeContact()
       
  1534  */
       
  1535 bool QContactManagerEngine::removeContacts(const QList<QContactLocalId>& contactIds, QMap<int, QContactManager::Error>* errorMap, QContactManager::Error* error)
       
  1536 {
       
  1537     Q_UNUSED(contactIds);
       
  1538     Q_UNUSED(errorMap);
       
  1539     *error = QContactManager::NotSupportedError;
       
  1540     return false;
       
  1541 }
       
  1542 
       
  1543 /*!
       
  1544   Returns a pruned or modified version of the \a original contact which is valid and can be saved in the manager.
       
  1545   The returned contact might have details removed or arbitrarily changed.  The cache of relationships
       
  1546   in the contact are ignored entirely when considering compatibility with the backend, as they are
       
  1547   saved and validated separately.  Any error which occurs will be saved to \a error.
       
  1548  */
       
  1549 QContact QContactManagerEngine::compatibleContact(const QContact& original, QContactManager::Error* error) const
       
  1550 {
       
  1551     QContact conforming;
       
  1552     conforming.setId(original.id());
       
  1553     QContactManager::Error tempError;
       
  1554     QList<QString> uniqueDefinitionIds;
       
  1555     foreach (QContactDetail detail, original.details()) {
       
  1556         // check that the detail conforms to the definition in this manager.
       
  1557         // if so, then add it to the conforming contact to be returned.  if not, prune it.
       
  1558 
       
  1559         QVariantMap values = detail.variantValues();
       
  1560         QContactDetailDefinition def = detailDefinition(detail.definitionName(), original.type(), &tempError);
       
  1561         // check that the definition is supported
       
  1562         if (tempError != QContactManager::NoError) {
       
  1563             continue; // this definition is not supported.
       
  1564         }
       
  1565 
       
  1566         // check uniqueness
       
  1567         if (def.isUnique()) {
       
  1568             if (uniqueDefinitionIds.contains(def.name())) {
       
  1569                 continue; // can't have two of a unique detail.
       
  1570             }
       
  1571             uniqueDefinitionIds.append(def.name());
       
  1572         }
       
  1573 
       
  1574         QMapIterator<QString,QVariant> fieldIt(values);
       
  1575         while (fieldIt.hasNext()) {
       
  1576             fieldIt.next();
       
  1577             const QString& key = fieldIt.key();
       
  1578             const QVariant& variant = fieldIt.value();
       
  1579             // prune values for nonexistent fields.
       
  1580             if (!def.fields().contains(key)) {
       
  1581                 detail.removeValue(key);
       
  1582             }
       
  1583 
       
  1584             QContactDetailFieldDefinition field = def.fields().value(key);
       
  1585             // prune values that do not correspond to the allowable field type
       
  1586             if (static_cast<int>(field.dataType()) != variant.userType()) {
       
  1587                 detail.removeValue(key);
       
  1588             }
       
  1589 
       
  1590             // check that the value is allowable
       
  1591             // if the allowable values is an empty list, any are allowed.
       
  1592             if (!field.allowableValues().isEmpty()) {
       
  1593                 // if the field datatype is a list, remove non-allowable values
       
  1594                 if (field.dataType() == QVariant::List) {
       
  1595                     QVariantList innerValues = variant.toList();
       
  1596                     QMutableListIterator<QVariant> it(innerValues);
       
  1597                     while (it.hasNext()) {
       
  1598                         if (!field.allowableValues().contains(it.next())) {
       
  1599                             it.remove();
       
  1600                         }
       
  1601                     }
       
  1602                     if (innerValues.isEmpty())
       
  1603                         detail.removeValue(key);
       
  1604                     else
       
  1605                         detail.setValue(key, innerValues);
       
  1606                 } 
       
  1607                 if (field.dataType() == QVariant::StringList) {
       
  1608                     QStringList innerValues = variant.toStringList();
       
  1609                     QMutableListIterator<QString> it(innerValues);
       
  1610                     while (it.hasNext()) {
       
  1611                         if (!field.allowableValues().contains(it.next())) {
       
  1612                             it.remove();
       
  1613                         }
       
  1614                     }
       
  1615                     if (innerValues.isEmpty())
       
  1616                         detail.removeValue(key);
       
  1617                     else
       
  1618                         detail.setValue(key, innerValues);
       
  1619                 } else if (!field.allowableValues().contains(variant)) {
       
  1620                     detail.removeValue(key);
       
  1621                 }
       
  1622             }
       
  1623         }
       
  1624 
       
  1625         // if it hasn't been pruned away to nothing, save it in the conforming contact
       
  1626         if (!detail.isEmpty()) {
       
  1627             conforming.saveDetail(&detail);
       
  1628         }
       
  1629     }
       
  1630 
       
  1631     if (!conforming.isEmpty())
       
  1632         *error = QContactManager::NoError;
       
  1633     else
       
  1634         *error = QContactManager::DoesNotExistError;
       
  1635     return conforming;
       
  1636 }
       
  1637 
       
  1638 
       
  1639 /* This implements the string comparison behaviour required for compareVariant, amongst others */
       
  1640 static inline int compareStrings(const QString& left, const QString& right, Qt::CaseSensitivity sensitivity)
       
  1641 {
       
  1642     if (sensitivity == Qt::CaseSensitive) {
       
  1643         return left.localeAwareCompare(right);
       
  1644     } else {
       
  1645         return left.toCaseFolded().localeAwareCompare(right.toCaseFolded());
       
  1646     }
       
  1647 }
       
  1648 
       
  1649 /*!
       
  1650   Compares \a first against \a second.  If the types are
       
  1651   strings (QVariant::String), the \a sensitivity argument controls
       
  1652   case sensitivity when comparing.  Also, when comparing strings,
       
  1653   a locale aware comparison is used, and if the sensitivity is
       
  1654   CaseSensitive, strings that are identical under a case insensitive
       
  1655   sort are then sorted case sensitively within that context.
       
  1656 
       
  1657 
       
  1658   For example:
       
  1659 
       
  1660   aaron
       
  1661   Bob
       
  1662   Aaron
       
  1663   aAron
       
  1664   Carol
       
  1665 
       
  1666   would sort as:
       
  1667 
       
  1668   aaron
       
  1669   aAron
       
  1670   Aaron
       
  1671   Bob
       
  1672   Carol
       
  1673 
       
  1674   Returns:
       
  1675   <0 if \a first is less than \a second
       
  1676    0 if \a first is equal to \a second
       
  1677   >0 if \a first is greater than \a second.
       
  1678 
       
  1679   The results are undefined if the variants are different types, or
       
  1680   cannot be compared.
       
  1681  */
       
  1682 int QContactManagerEngine::compareVariant(const QVariant& first, const QVariant& second, Qt::CaseSensitivity sensitivity)
       
  1683 {
       
  1684     switch(first.type()) {
       
  1685         case QVariant::Int:
       
  1686             return first.toInt() - second.toInt();
       
  1687 
       
  1688         case QVariant::LongLong:
       
  1689             return first.toLongLong() - second.toLongLong();
       
  1690 
       
  1691         case QVariant::Bool:
       
  1692         case QVariant::Char:
       
  1693         case QVariant::UInt:
       
  1694             return first.toUInt() - second.toUInt();
       
  1695 
       
  1696         case QVariant::ULongLong:
       
  1697             return first.toULongLong() - second.toULongLong();
       
  1698 
       
  1699        case QVariant::String:
       
  1700             return compareStrings(first.toString(), second.toString(), sensitivity);
       
  1701 
       
  1702         case QVariant::Double:
       
  1703             {
       
  1704                 const double a = first.toDouble();
       
  1705                 const double b = second.toDouble();
       
  1706                 return (a < b) ? -1 : ((a == b) ? 0 : 1);
       
  1707             }
       
  1708 
       
  1709         case QVariant::DateTime:
       
  1710             {
       
  1711                 const QDateTime a = first.toDateTime();
       
  1712                 const QDateTime b = second.toDateTime();
       
  1713                 return (a < b) ? -1 : ((a == b) ? 0 : 1);
       
  1714             }
       
  1715 
       
  1716         case QVariant::Date:
       
  1717             return first.toDate().toJulianDay() - second.toDate().toJulianDay();
       
  1718 
       
  1719         case QVariant::Time:
       
  1720             {
       
  1721                 const QTime a = first.toTime();
       
  1722                 const QTime b = second.toTime();
       
  1723                 return (a < b) ? -1 : ((a == b) ? 0 : 1);
       
  1724             }
       
  1725 
       
  1726         default:
       
  1727             return 0;
       
  1728     }
       
  1729 }
       
  1730 
       
  1731 /*!
       
  1732   Returns true if the supplied contact \a contact matches the supplied filter \a filter.
       
  1733 
       
  1734   This function will test each condition in the filter, possibly recursing.
       
  1735  */
       
  1736 bool QContactManagerEngine::testFilter(const QContactFilter &filter, const QContact &contact)
       
  1737 {
       
  1738     switch(filter.type()) {
       
  1739         case QContactFilter::InvalidFilter:
       
  1740             return false;
       
  1741 
       
  1742         case QContactFilter::DefaultFilter:
       
  1743             return true;
       
  1744 
       
  1745         case QContactFilter::LocalIdFilter:
       
  1746             {
       
  1747                 const QContactLocalIdFilter idf(filter);
       
  1748                 if (idf.ids().contains(contact.id().localId()))
       
  1749                     return true;
       
  1750             }
       
  1751             // Fall through to end
       
  1752             break;
       
  1753 
       
  1754         case QContactFilter::ContactDetailFilter:
       
  1755             {
       
  1756                 const QContactDetailFilter cdf(filter);
       
  1757                 if (cdf.detailDefinitionName().isEmpty())
       
  1758                     return false;
       
  1759 
       
  1760                 /* See if this contact has one of these details in it */
       
  1761                 const QList<QContactDetail>& details = contact.details(cdf.detailDefinitionName());
       
  1762 
       
  1763                 if (details.count() == 0)
       
  1764                     return false; /* can't match */
       
  1765 
       
  1766                 /* See if we need to check the values */
       
  1767                 if (cdf.detailFieldName().isEmpty())
       
  1768                     return true;  /* just testing for the presence of a detail of the specified definition */
       
  1769 
       
  1770                 /* Now figure out what tests we are doing */
       
  1771                 const bool valueTest = cdf.value().isValid();
       
  1772                 const bool presenceTest = !valueTest;
       
  1773 
       
  1774                 /* See if we need to test any values at all */
       
  1775                 if (presenceTest) {
       
  1776                     for(int j=0; j < details.count(); j++) {
       
  1777                         const QContactDetail& detail = details.at(j);
       
  1778 
       
  1779                         /* Check that the field is present and has a non-empty value */
       
  1780                         if (detail.variantValues().contains(cdf.detailFieldName()) && !detail.value(cdf.detailFieldName()).isEmpty())
       
  1781                             return true;
       
  1782                     }
       
  1783                     return false;
       
  1784                 }
       
  1785 
       
  1786                 /* Case sensitivity, for those parts that use it */
       
  1787                 Qt::CaseSensitivity cs = (cdf.matchFlags() & QContactFilter::MatchCaseSensitive) ? Qt::CaseSensitive : Qt::CaseInsensitive;
       
  1788 
       
  1789                 /* See what flags are requested, since we're looking at a value */
       
  1790                 if (cdf.matchFlags() & QContactFilter::MatchPhoneNumber) {
       
  1791                     /* Doing phone number filtering.  We hand roll an implementation here, backends will obviously want to override this. */
       
  1792                     QString input = cdf.value().toString();
       
  1793 
       
  1794                     /* preprocess the input - ignore any non-digits (doesn't perform ITU-T collation */
       
  1795                     QString preprocessedInput;
       
  1796                     for (int i = 0; i < input.size(); i++) {
       
  1797                         QChar current = input.at(i).toLower();
       
  1798                         if (current.isDigit()) preprocessedInput.append(current);
       
  1799                         // note: we ignore characters like '+', 'p', 'w', '*' and '#' which may be important.
       
  1800                     }
       
  1801 
       
  1802                     /* Look at every detail in the set of details and compare */
       
  1803                     for (int j = 0; j < details.count(); j++) {
       
  1804                         const QContactDetail& detail = details.at(j);
       
  1805                         const QString& valueString = detail.value(cdf.detailFieldName());
       
  1806                         QString preprocessedValueString;
       
  1807                         for (int i = 0; i < valueString.size(); i++) {
       
  1808                             QChar current = valueString.at(i).toLower();
       
  1809                             if (current.isDigit()) preprocessedValueString.append(current);
       
  1810                             // note: we ignore characters like '+', 'p', 'w', '*' and '#' which may be important.
       
  1811                         }
       
  1812 
       
  1813                         // if the matchflags input don't require a particular criteria to pass, we assume that it has passed.
       
  1814                         // the "default" match strategy is an "endsWith" strategy.
       
  1815                         bool me = (cdf.matchFlags() & 7) == QContactFilter::MatchExactly;
       
  1816                         bool mc = (cdf.matchFlags() & 7) == QContactFilter::MatchContains;
       
  1817                         bool msw = (cdf.matchFlags() & 7) == QContactFilter::MatchStartsWith;
       
  1818                         bool mew = (cdf.matchFlags() & 7) == QContactFilter::MatchEndsWith;
       
  1819 
       
  1820                         bool mer = (me ? preprocessedValueString == preprocessedInput : true);
       
  1821                         bool mcr = (mc ? preprocessedValueString.contains(preprocessedInput) : true);
       
  1822                         bool mswr = (msw ? preprocessedValueString.startsWith(preprocessedInput) : true);
       
  1823                         bool mewr = (mew ? preprocessedValueString.endsWith(preprocessedInput) : true);
       
  1824                         if (mewr && mswr && mcr && mer) {
       
  1825                             return true; // this detail meets all of the criteria which were required, and hence must match.
       
  1826                         }
       
  1827                     }
       
  1828                 } else if (cdf.matchFlags() & QContactFilter::MatchKeypadCollation) {
       
  1829                     // XXX TODO: not sure about the filtering semantics for MatchKeypadCollation.
       
  1830                     QString input = cdf.value().toString();
       
  1831 
       
  1832                     /* Look at every detail in the set of details and compare */
       
  1833                     for (int j = 0; j < details.count(); j++) {
       
  1834                         const QContactDetail& detail = details.at(j);
       
  1835                         const QString& valueString = detail.value(cdf.detailFieldName()).toLower();
       
  1836 
       
  1837                         // preprocess the valueString
       
  1838                         QString preprocessedValue;
       
  1839                         for (int i = 0; i < valueString.size(); i++) {
       
  1840                             // we use ITU-T keypad collation by default.
       
  1841                             QChar currentValueChar = valueString.at(i);
       
  1842                             if (currentValueChar == QLatin1Char('a') || currentValueChar == QLatin1Char('b') || currentValueChar == QLatin1Char('c'))
       
  1843                                 preprocessedValue.append(QLatin1Char('2'));
       
  1844                             else if (currentValueChar == QLatin1Char('d') || currentValueChar == QLatin1Char('e') || currentValueChar == QLatin1Char('f'))
       
  1845                                 preprocessedValue.append(QLatin1Char('3'));
       
  1846                             else if (currentValueChar == QLatin1Char('g') || currentValueChar == QLatin1Char('h') || currentValueChar == QLatin1Char('i'))
       
  1847                                 preprocessedValue.append(QLatin1Char('4'));
       
  1848                             else if (currentValueChar == QLatin1Char('j') || currentValueChar == QLatin1Char('k') || currentValueChar == QLatin1Char('l'))
       
  1849                                 preprocessedValue.append(QLatin1Char('5'));
       
  1850                             else if (currentValueChar == QLatin1Char('m') || currentValueChar == QLatin1Char('n') || currentValueChar == QLatin1Char('o'))
       
  1851                                 preprocessedValue.append(QLatin1Char('6'));
       
  1852                             else if (currentValueChar == QLatin1Char('p') || currentValueChar == QLatin1Char('q') || currentValueChar == QLatin1Char('r') || currentValueChar == QLatin1Char('s'))
       
  1853                                 preprocessedValue.append(QLatin1Char('7'));
       
  1854                             else if (currentValueChar == QLatin1Char('t') || currentValueChar == QLatin1Char('u') || currentValueChar == QLatin1Char('v'))
       
  1855                                 preprocessedValue.append(QLatin1Char('8'));
       
  1856                             else if (currentValueChar == QLatin1Char('w') || currentValueChar == QLatin1Char('x') || currentValueChar == QLatin1Char('y') || currentValueChar == QLatin1Char('z'))
       
  1857                                 preprocessedValue.append(QLatin1Char('9'));
       
  1858                             else
       
  1859                                 preprocessedValue.append(currentValueChar);
       
  1860                         }
       
  1861 
       
  1862                         bool me = (cdf.matchFlags() & 7) == QContactFilter::MatchExactly;
       
  1863                         bool mc = (cdf.matchFlags() & 7) == QContactFilter::MatchContains;
       
  1864                         bool msw = (cdf.matchFlags() & 7) == QContactFilter::MatchStartsWith;
       
  1865                         bool mew = (cdf.matchFlags() & 7) == QContactFilter::MatchEndsWith;
       
  1866 
       
  1867                         bool mer = (me ? preprocessedValue == input : true);
       
  1868                         bool mcr = (mc ? preprocessedValue.contains(input) : true);
       
  1869                         bool mswr = (msw ? preprocessedValue.startsWith(input) : true);
       
  1870                         bool mewr = (mew ? preprocessedValue.endsWith(input) : true);
       
  1871                         if (mewr && mswr && mcr && mer) {
       
  1872                             return true; // this detail meets all of the criteria which were required, and hence must match.
       
  1873                         }
       
  1874                     }
       
  1875                 } else if (cdf.matchFlags() & (QContactFilter::MatchEndsWith | QContactFilter::MatchStartsWith | QContactFilter::MatchContains | QContactFilter::MatchFixedString)) {
       
  1876                     /* We're strictly doing string comparisons here */
       
  1877                     bool matchStarts = (cdf.matchFlags() & 7) == QContactFilter::MatchStartsWith;
       
  1878                     bool matchEnds = (cdf.matchFlags() & 7) == QContactFilter::MatchEndsWith;
       
  1879                     bool matchContains = (cdf.matchFlags() & 7) == QContactFilter::MatchContains;
       
  1880 
       
  1881                     /* Value equality test */
       
  1882                     for(int j=0; j < details.count(); j++) {
       
  1883                         const QContactDetail& detail = details.at(j);
       
  1884                         const QString& var = detail.value(cdf.detailFieldName());
       
  1885                         const QString& needle = cdf.value().toString();
       
  1886                         if (matchStarts && var.startsWith(needle, cs))
       
  1887                             return true;
       
  1888                         if (matchEnds && var.endsWith(needle, cs))
       
  1889                             return true;
       
  1890                         if (matchContains && var.contains(needle, cs))
       
  1891                             return true;
       
  1892                         if (compareStrings(var, needle, cs) == 0)
       
  1893                             return true;
       
  1894                     }
       
  1895                     return false;
       
  1896                 } else {
       
  1897                     /* Nope, testing the values as a variant */
       
  1898                     /* Value equality test */
       
  1899                     for(int j = 0; j < details.count(); j++) {
       
  1900                         const QContactDetail& detail = details.at(j);
       
  1901                         const QVariant& var = detail.variantValue(cdf.detailFieldName());
       
  1902                         if (!var.isNull() && compareVariant(var, cdf.value(), cs) == 0)
       
  1903                             return true;
       
  1904                     }
       
  1905                 }
       
  1906             }
       
  1907             break;
       
  1908 
       
  1909         case QContactFilter::ContactDetailRangeFilter:
       
  1910             {
       
  1911                 /* The only supported flags are: MatchExactly, MatchFixedString, MatchCaseSensitive */
       
  1912 
       
  1913                 const QContactDetailRangeFilter cdf(filter);
       
  1914                 if (cdf.detailDefinitionName().isEmpty())
       
  1915                     return false; /* we do not know which field to check */
       
  1916 
       
  1917                 /* See if this contact has one of these details in it */
       
  1918                 const QList<QContactDetail>& details = contact.details(cdf.detailDefinitionName());
       
  1919 
       
  1920                 if (details.count() == 0)
       
  1921                     return false; /* can't match */
       
  1922 
       
  1923                 /* Check for a detail presence test */
       
  1924                 if (cdf.detailFieldName().isEmpty())
       
  1925                     return true;
       
  1926 
       
  1927                 /* See if this is a field presence test */
       
  1928                 if (!cdf.minValue().isValid() && !cdf.maxValue().isValid()) {
       
  1929                     for(int j=0; j < details.count(); j++) {
       
  1930                         const QContactDetail& detail = details.at(j);
       
  1931                         if (detail.variantValues().contains(cdf.detailFieldName()))
       
  1932                             return true;
       
  1933                     }
       
  1934                     return false;
       
  1935                 }
       
  1936 
       
  1937                 /* open or closed interval testing support */
       
  1938                 const int minComp = cdf.rangeFlags() & QContactDetailRangeFilter::ExcludeLower ? 1 : 0;
       
  1939                 const int maxComp = cdf.rangeFlags() & QContactDetailRangeFilter::IncludeUpper ? 1 : 0;
       
  1940 
       
  1941                 /* Case sensitivity, for those parts that use it */
       
  1942                 Qt::CaseSensitivity cs = (cdf.matchFlags() & QContactFilter::MatchCaseSensitive) ? Qt::CaseSensitive : Qt::CaseInsensitive;
       
  1943 
       
  1944                 /* See what flags are requested, since we're looking at a value */
       
  1945                 if (cdf.matchFlags() & QContactFilter::MatchFixedString) {
       
  1946                     /* We're strictly doing string comparisons here */
       
  1947                     QString minVal = cdf.minValue().toString();
       
  1948                     QString maxVal = cdf.maxValue().toString();
       
  1949 
       
  1950                     const bool testMin = !minVal.isEmpty();
       
  1951                     const bool testMax = !maxVal.isEmpty();
       
  1952 
       
  1953                     for(int j=0; j < details.count(); j++) {
       
  1954                         const QContactDetail& detail = details.at(j);
       
  1955 
       
  1956                         // The detail has to have a field of this type in order to be compared.
       
  1957                         if (!detail.variantValue(cdf.detailFieldName()).isValid())
       
  1958                             continue;
       
  1959                         const QString& var = detail.value(cdf.detailFieldName());
       
  1960                         if (testMin && compareStrings(var, minVal, cs) < minComp)
       
  1961                             continue;
       
  1962                         if (testMax && compareStrings(var, maxVal, cs) >= maxComp)
       
  1963                             continue;
       
  1964                         return true;
       
  1965                     }
       
  1966                     // Fall through to end
       
  1967                 } else {
       
  1968                     const bool testMin = cdf.minValue().isValid();
       
  1969                     const bool testMax = cdf.maxValue().isValid();
       
  1970 
       
  1971                     /* Nope, testing the values as a variant */
       
  1972                     for(int j=0; j < details.count(); j++) {
       
  1973                         const QContactDetail& detail = details.at(j);
       
  1974                         const QVariant& var = detail.variantValue(cdf.detailFieldName());
       
  1975 
       
  1976                         // The detail has to have a field of this type in order to be compared.
       
  1977                         if (!var.isValid())
       
  1978                             continue;
       
  1979 
       
  1980                         if (testMin && compareVariant(var, cdf.minValue(), cs) < minComp)
       
  1981                             continue;
       
  1982                         if (testMax && compareVariant(var, cdf.maxValue(), cs) >= maxComp)
       
  1983                             continue;
       
  1984                         return true;
       
  1985                     }
       
  1986                     // Fall through to end
       
  1987                 }
       
  1988             }
       
  1989             break;
       
  1990 
       
  1991         case QContactFilter::RelationshipFilter:
       
  1992             {
       
  1993                 // matches any contact that plays the specified role in a relationship
       
  1994                 // of the specified type with the specified other participant.
       
  1995                 const QContactRelationshipFilter rf(filter);
       
  1996 
       
  1997                 // first, retrieve contact uris
       
  1998                 QContactId contactUri = contact.id();
       
  1999                 QContactId relatedContactId = rf.relatedContactId();
       
  2000 
       
  2001                 // get the relationships in which this contact is involved.
       
  2002                 QList<QContactRelationship> allRelationships;
       
  2003                 allRelationships = contact.relationships();
       
  2004 
       
  2005 // simplify the comparison of two contact id's depending on their fields.
       
  2006 #define CONTACT_IDS_MATCH(specific, other) \
       
  2007             ((specific == QContactId()) \
       
  2008                 || (specific.managerUri().isEmpty() && specific.localId() == other.localId()) \
       
  2009                 || (specific.managerUri() == other.managerUri() && specific.localId() == QContactLocalId(0)) \
       
  2010                 || (specific.managerUri() == other.managerUri() && specific.localId() == other.localId()))
       
  2011 
       
  2012                 // now check to see if we have a match.
       
  2013                 foreach (const QContactRelationship& rel, allRelationships) {
       
  2014                     // perform the matching.
       
  2015                     if (rf.relatedContactRole() == QContactRelationship::Second) { // this is the role of the related contact; ie, to match, contact.id() must be the first in the relationship.
       
  2016                         if ((rf.relationshipType().isEmpty() || rel.relationshipType() == rf.relationshipType())
       
  2017                                 && CONTACT_IDS_MATCH(rel.first(), contact.id()) && CONTACT_IDS_MATCH(relatedContactId, rel.second())) {
       
  2018                             return true;
       
  2019                         }
       
  2020                     } else if (rf.relatedContactRole() == QContactRelationship::First) { // this is the role of the related contact; ie, to match, contact.id() must be the second in the relationship.
       
  2021                         if ((rf.relationshipType().isEmpty() || rel.relationshipType() == rf.relationshipType())
       
  2022                                 && CONTACT_IDS_MATCH(rel.second(), contact.id()) && CONTACT_IDS_MATCH(relatedContactId, rel.first())) {
       
  2023                             return true;
       
  2024                         }
       
  2025                     } else { // QContactRelationship::Either
       
  2026                         if ((rf.relationshipType().isEmpty() || rel.relationshipType() == rf.relationshipType())
       
  2027                                 && ((CONTACT_IDS_MATCH(relatedContactId, rel.first()) && !CONTACT_IDS_MATCH(contactUri, relatedContactId)) || (CONTACT_IDS_MATCH(relatedContactId, rel.second()) && !CONTACT_IDS_MATCH(contactUri, relatedContactId)))) {
       
  2028                             return true;
       
  2029                         }
       
  2030                     }
       
  2031                 }
       
  2032 
       
  2033                 // if not found by now, it doesn't match the filter.
       
  2034                 return false;
       
  2035             }
       
  2036             //break; // unreachable.
       
  2037 
       
  2038         case QContactFilter::ChangeLogFilter:
       
  2039             {
       
  2040                 QContactChangeLogFilter ccf(filter);
       
  2041 
       
  2042                 // See what we can do...
       
  2043                 QContactTimestamp ts = contact.detail(QContactTimestamp::DefinitionName);
       
  2044 
       
  2045                 // See if timestamps are even supported
       
  2046                 if (ts.isEmpty())
       
  2047                     break;
       
  2048 
       
  2049                 if (ccf.eventType() == QContactChangeLogFilter::EventAdded)
       
  2050                     return ccf.since() <= ts.created();
       
  2051                 if (ccf.eventType() == QContactChangeLogFilter::EventChanged)
       
  2052                     return ccf.since() <= ts.lastModified();
       
  2053 
       
  2054                 // You can't emulate a removed..
       
  2055                 // Fall through to end
       
  2056             }
       
  2057             break;
       
  2058 
       
  2059         case QContactFilter::ActionFilter:
       
  2060             {
       
  2061                 // Find any matching actions, and do a union filter on their filter objects
       
  2062                 QContactActionFilter af(filter);
       
  2063                 QList<QContactActionDescriptor> descriptors = QContactAction::actionDescriptors(af.actionName(), af.vendorName(), af.implementationVersion());
       
  2064 
       
  2065                 // There's a small wrinkle if there's a value specified in the action filter
       
  2066                 // we have to adjust any contained QContactDetailFilters to have that value
       
  2067                 // or test if a QContactDetailRangeFilter contains this value already
       
  2068                 for (int j = 0; j < descriptors.count(); j++) {
       
  2069                     QContactAction* action = QContactAction::action(descriptors.at(j));
       
  2070 
       
  2071                     // Action filters are not allowed to return action filters, at all
       
  2072                     // it's too annoying to check for recursion
       
  2073                     QContactFilter d = action->contactFilter(af.value());
       
  2074                     delete action; // clean up.
       
  2075                     if (!validateActionFilter(d))
       
  2076                         return false;
       
  2077 
       
  2078                     // Check for values etc...
       
  2079                     if (testFilter(d, contact))
       
  2080                         return true;
       
  2081                 }
       
  2082                 // Fall through to end
       
  2083             }
       
  2084             break;
       
  2085 
       
  2086         case QContactFilter::IntersectionFilter:
       
  2087             {
       
  2088                 /* XXX In theory we could reorder the terms to put the native tests first */
       
  2089                 const QContactIntersectionFilter bf(filter);
       
  2090                 const QList<QContactFilter>& terms = bf.filters();
       
  2091                 if (terms.count() > 0) {
       
  2092                     for(int j = 0; j < terms.count(); j++) {
       
  2093                         if (!testFilter(terms.at(j), contact)) {
       
  2094                             return false;
       
  2095                         }
       
  2096                     }
       
  2097                     return true;
       
  2098                 }
       
  2099                 // Fall through to end
       
  2100             }
       
  2101             break;
       
  2102 
       
  2103         case QContactFilter::UnionFilter:
       
  2104             {
       
  2105                 /* XXX In theory we could reorder the terms to put the native tests first */
       
  2106                 const QContactUnionFilter bf(filter);
       
  2107                 const QList<QContactFilter>& terms = bf.filters();
       
  2108                 if (terms.count() > 0) {
       
  2109                     for(int j = 0; j < terms.count(); j++) {
       
  2110                         if (testFilter(terms.at(j), contact)) {
       
  2111                             return true;
       
  2112                         }
       
  2113                     }
       
  2114                     return false;
       
  2115                 }
       
  2116                 // Fall through to end
       
  2117             }
       
  2118             break;
       
  2119     }
       
  2120     return false;
       
  2121 }
       
  2122 
       
  2123 /*!
       
  2124   Given a QContactFilter \a filter retrieved from a QContactAction,
       
  2125   check that it is valid and cannot cause infinite recursion.
       
  2126 
       
  2127   In particular, a filter from a QContactAction cannot contain
       
  2128   any instances of a QContactActionFilter.
       
  2129 
       
  2130   Returns true if \a filter seems ok, or false otherwise.
       
  2131  */
       
  2132 
       
  2133 bool QContactManagerEngine::validateActionFilter(const QContactFilter& filter)
       
  2134 {
       
  2135     QList<QContactFilter> toVerify;
       
  2136     toVerify << filter;
       
  2137 
       
  2138     while(toVerify.count() > 0) {
       
  2139         QContactFilter f = toVerify.takeFirst();
       
  2140         if (f.type() == QContactFilter::ActionFilter)
       
  2141             return false;
       
  2142         if (f.type() == QContactFilter::IntersectionFilter)
       
  2143             toVerify.append(QContactIntersectionFilter(f).filters());
       
  2144         if (f.type() == QContactFilter::UnionFilter)
       
  2145             toVerify.append(QContactUnionFilter(f).filters());
       
  2146     }
       
  2147 
       
  2148     return true;
       
  2149 }
       
  2150 
       
  2151 /*!
       
  2152   Sets the cached relationships in the given \a contact to \a relationships
       
  2153  */
       
  2154 void QContactManagerEngine::setContactRelationships(QContact* contact, const QList<QContactRelationship>& relationships)
       
  2155 {
       
  2156     contact->d->m_relationshipsCache = relationships;
       
  2157 }
       
  2158 
       
  2159 
       
  2160 /*!
       
  2161   Compares two contacts (\a a and \a b) using the given list of \a sortOrders.  Returns a negative number if \a a should appear
       
  2162   before \a b according to the sort order, a positive number if \a a should appear after \a b according to the sort order,
       
  2163   and zero if the two are unable to be sorted.
       
  2164  */
       
  2165 int QContactManagerEngine::compareContact(const QContact& a, const QContact& b, const QList<QContactSortOrder>& sortOrders)
       
  2166 {
       
  2167     foreach(const QContactSortOrder& sortOrder, sortOrders) {
       
  2168         if (!sortOrder.isValid())
       
  2169             break;
       
  2170 
       
  2171         // obtain the values which this sort order concerns
       
  2172         const QVariant& aVal = a.detail(sortOrder.detailDefinitionName()).variantValue(sortOrder.detailFieldName());
       
  2173         const QVariant& bVal = b.detail(sortOrder.detailDefinitionName()).variantValue(sortOrder.detailFieldName());
       
  2174 
       
  2175         bool aIsNull = false;
       
  2176         bool bIsNull = false;
       
  2177 
       
  2178         // treat empty strings as null qvariants.
       
  2179         if ((aVal.type() == QVariant::String && aVal.toString().isEmpty()) || aVal.isNull()) {
       
  2180             aIsNull = true;
       
  2181         }
       
  2182         if ((bVal.type() == QVariant::String && bVal.toString().isEmpty()) || bVal.isNull()) {
       
  2183             bIsNull = true;
       
  2184         }
       
  2185 
       
  2186         // early exit error checking
       
  2187         if (aIsNull && bIsNull)
       
  2188             continue; // use next sort criteria.
       
  2189         if (aIsNull)
       
  2190             return (sortOrder.blankPolicy() == QContactSortOrder::BlanksFirst ? -1 : 1);
       
  2191         if (bIsNull)
       
  2192             return (sortOrder.blankPolicy() == QContactSortOrder::BlanksFirst ? 1 : -1);
       
  2193 
       
  2194         // real comparison
       
  2195         int comparison = compareVariant(aVal, bVal, sortOrder.caseSensitivity()) * (sortOrder.direction() == Qt::AscendingOrder ? 1 : -1);
       
  2196         if (comparison == 0)
       
  2197             continue;
       
  2198         return comparison;
       
  2199     }
       
  2200 
       
  2201     return 0; // or according to id? return (a.id() < b.id() ? -1 : 1);
       
  2202 }
       
  2203 
       
  2204 /* A functor that returns true iff a is less than b, according to the sortOrders passed in to the
       
  2205  * ctor.  The sortOrders pointer passed in must remain valid for the lifetime of the functor. */
       
  2206 class ContactLessThan {
       
  2207     public:
       
  2208         ContactLessThan(const QList<QContactSortOrder>* sortOrders) : mSortOrders(sortOrders) {}
       
  2209         bool operator()(const QContact& a, const QContact& b) const
       
  2210         {
       
  2211             return QContactManagerEngine::compareContact(a, b, *mSortOrders) < 0;
       
  2212         }
       
  2213     private:
       
  2214         const QList<QContactSortOrder>* mSortOrders;
       
  2215 };
       
  2216 
       
  2217 /*!
       
  2218   Performs insertion sort of the contact \a toAdd into the \a sorted list, according to the provided \a sortOrders list.
       
  2219   The first QContactSortOrder in the list has the highest priority: if the contact \a toAdd is deemed equal to another
       
  2220   in the \a sorted list according to the first QContactSortOrder, the second QContactSortOrder in the list is used (and
       
  2221   so on until either the contact is inserted or there are no more sort order objects in the list).
       
  2222 
       
  2223   If a contact is equal to another contact according to all sort orders, it is inserted after the previously-added contact.
       
  2224  */
       
  2225 void QContactManagerEngine::addSorted(QList<QContact>* sorted, const QContact& toAdd, const QList<QContactSortOrder>& sortOrders)
       
  2226 {
       
  2227     if (sortOrders.count() > 0) {
       
  2228         ContactLessThan lessThan(&sortOrders);
       
  2229         QList<QContact>::iterator it(qUpperBound(sorted->begin(), sorted->end(), toAdd, lessThan));
       
  2230         sorted->insert(it, toAdd);
       
  2231     } else {
       
  2232         // no sort order? just add it to the end
       
  2233         sorted->append(toAdd);
       
  2234     }
       
  2235 }
       
  2236 
       
  2237 /*! Sorts the given list of contacts \a cs according to the provided \a sortOrders */
       
  2238 QList<QContactLocalId> QContactManagerEngine::sortContacts(const QList<QContact>& cs, const QList<QContactSortOrder>& sortOrders)
       
  2239 {
       
  2240     QList<QContactLocalId> sortedIds;
       
  2241     QList<QContact> sortedContacts = cs;
       
  2242     if (!sortOrders.isEmpty()) {
       
  2243         ContactLessThan lessThan(&sortOrders);
       
  2244         qStableSort(sortedContacts.begin(), sortedContacts.end(), lessThan);
       
  2245     }
       
  2246 
       
  2247     foreach(const QContact& c, sortedContacts) {
       
  2248         sortedIds.append(c.localId());
       
  2249     }
       
  2250     return sortedIds;
       
  2251 }
       
  2252 
       
  2253 /*!
       
  2254   Notifies the manager engine that the given request \a req has been destroyed
       
  2255  */
       
  2256 void QContactManagerEngine::requestDestroyed(QContactAbstractRequest* req)
       
  2257 {
       
  2258     Q_UNUSED(req);
       
  2259 }
       
  2260 
       
  2261 /*!
       
  2262   Asks the manager engine to begin the given request \a req which
       
  2263   is currently in a (re)startable state.
       
  2264   Returns true if the request was started successfully, else returns false.
       
  2265 
       
  2266   \sa QContactAbstractRequest::start()
       
  2267  */
       
  2268 bool QContactManagerEngine::startRequest(QContactAbstractRequest* req)
       
  2269 {
       
  2270     Q_UNUSED(req);
       
  2271     return false;
       
  2272 }
       
  2273 
       
  2274 /*!
       
  2275   Asks the manager engine to cancel the given request \a req which was
       
  2276   previously started and is currently in a cancellable state.
       
  2277   Returns true if cancellation of the request was started successfully,
       
  2278   otherwise returns false.
       
  2279 
       
  2280   \sa startRequest(), QContactAbstractRequest::cancel()
       
  2281  */
       
  2282 bool QContactManagerEngine::cancelRequest(QContactAbstractRequest* req)
       
  2283 {
       
  2284     Q_UNUSED(req);
       
  2285     return false;
       
  2286 }
       
  2287 
       
  2288 /*!
       
  2289   Blocks until the manager engine has completed the given request \a req
       
  2290   which was previously started, or until \a msecs milliseconds have passed.
       
  2291   Returns true if the request was completed, and false if the request was not in the
       
  2292   \c QContactAbstractRequest::Active state or no progress could be reported.
       
  2293 
       
  2294   \sa startRequest()
       
  2295  */
       
  2296 bool QContactManagerEngine::waitForRequestFinished(QContactAbstractRequest* req, int msecs)
       
  2297 {
       
  2298     Q_UNUSED(req);
       
  2299     Q_UNUSED(msecs);
       
  2300     return false;
       
  2301 }
       
  2302 
       
  2303 /*!
       
  2304   Updates the given asynchronous request \a req by setting the new \a state
       
  2305   of the request.  If the new state is different, the stateChanged() signal
       
  2306   will be emitted by the request.
       
  2307  */
       
  2308 void QContactManagerEngine::updateRequestState(QContactAbstractRequest* req, QContactAbstractRequest::State state)
       
  2309 {
       
  2310     if (req) {
       
  2311         QMutexLocker ml(&req->d_ptr->m_mutex);
       
  2312         if (req->d_ptr->m_state != state) {
       
  2313             req->d_ptr->m_state = state;
       
  2314             ml.unlock();
       
  2315             emit req->stateChanged(state);
       
  2316         }
       
  2317     }
       
  2318 }
       
  2319 
       
  2320 /*!
       
  2321   Updates the given QContactLocalIdFetchRequest \a req with the latest results \a result, and operation error \a error.
       
  2322   In addition, the state of the request will be changed to \a newState.
       
  2323 
       
  2324   It then causes the request to emit its resultsAvailable() signal to notify clients of the request progress.
       
  2325 
       
  2326   If the new request state is different from the previous state, the stateChanged() signal will also be emitted from the request.
       
  2327  */
       
  2328 void QContactManagerEngine::updateContactLocalIdFetchRequest(QContactLocalIdFetchRequest* req, const QList<QContactLocalId>& result, QContactManager::Error error, QContactAbstractRequest::State newState)
       
  2329 {
       
  2330     if (req) {
       
  2331         QWeakPointer<QContactLocalIdFetchRequest> ireq(req); // Take this in case the first emit deletes us
       
  2332         QContactLocalIdFetchRequestPrivate* rd = static_cast<QContactLocalIdFetchRequestPrivate*>(ireq.data()->d_ptr);
       
  2333         QMutexLocker ml(&rd->m_mutex);
       
  2334         bool emitState = rd->m_state != newState;
       
  2335         rd->m_ids = result;
       
  2336         rd->m_error = error;
       
  2337         rd->m_state = newState;
       
  2338         ml.unlock();
       
  2339         emit ireq.data()->resultsAvailable();
       
  2340         if (emitState && ireq)
       
  2341             emit ireq.data()->stateChanged(newState);
       
  2342     }
       
  2343 }
       
  2344 
       
  2345 /*!
       
  2346   Updates the given QContactFetchRequest \a req with the latest results \a result, and operation error \a error.
       
  2347   In addition, the state of the request will be changed to \a newState.
       
  2348 
       
  2349   It then causes the request to emit its resultsAvailable() signal to notify clients of the request progress.
       
  2350 
       
  2351   If the new request state is different from the previous state, the stateChanged() signal will also be emitted from the request.
       
  2352  */
       
  2353 void QContactManagerEngine::updateContactFetchRequest(QContactFetchRequest* req, const QList<QContact>& result, QContactManager::Error error, QContactAbstractRequest::State newState)
       
  2354 {
       
  2355     if (req) {
       
  2356         QWeakPointer<QContactFetchRequest> ireq(req); // Take this in case the first emit deletes us
       
  2357         QContactFetchRequestPrivate* rd = static_cast<QContactFetchRequestPrivate*>(ireq.data()->d_ptr);
       
  2358         QMutexLocker ml(&rd->m_mutex);
       
  2359         bool emitState = rd->m_state != newState;
       
  2360         rd->m_contacts = result;
       
  2361         rd->m_error = error;
       
  2362         rd->m_state = newState;
       
  2363         ml.unlock();
       
  2364         emit ireq.data()->resultsAvailable();
       
  2365         if (emitState && ireq)
       
  2366             emit ireq.data()->stateChanged(newState);
       
  2367     }
       
  2368 }
       
  2369 
       
  2370 /*!
       
  2371   Updates the given QContactRemoveRequest \a req with the operation error \a error, and map of input index to individual error \a errorMap.
       
  2372   In addition, the state of the request will be changed to \a newState.
       
  2373 
       
  2374   It then causes the request to emit its resultsAvailable() signal to notify clients of the request progress.
       
  2375 
       
  2376   If the new request state is different from the previous state, the stateChanged() signal will also be emitted from the request.
       
  2377  */
       
  2378 void QContactManagerEngine::updateContactRemoveRequest(QContactRemoveRequest* req, QContactManager::Error error, const QMap<int, QContactManager::Error>& errorMap, QContactAbstractRequest::State newState)
       
  2379 {
       
  2380     if (req) {
       
  2381         QWeakPointer<QContactRemoveRequest> ireq(req); // Take this in case the first emit deletes us
       
  2382         QContactRemoveRequestPrivate* rd = static_cast<QContactRemoveRequestPrivate*>(ireq.data()->d_ptr);
       
  2383         QMutexLocker ml(&rd->m_mutex);
       
  2384         bool emitState = rd->m_state != newState;
       
  2385         rd->m_errors = errorMap;
       
  2386         rd->m_error = error;
       
  2387         rd->m_state = newState;
       
  2388         ml.unlock();
       
  2389         emit ireq.data()->resultsAvailable();
       
  2390         if (emitState && ireq)
       
  2391             emit ireq.data()->stateChanged(newState);
       
  2392     }
       
  2393 }
       
  2394 
       
  2395 /*!
       
  2396   Updates the given QContactSaveRequest \a req with the latest results \a result, operation error \a error, and map of input index to individual error \a errorMap.
       
  2397   In addition, the state of the request will be changed to \a newState.
       
  2398 
       
  2399   It then causes the request to emit its resultsAvailable() signal to notify clients of the request progress.
       
  2400 
       
  2401   If the new request state is different from the previous state, the stateChanged() signal will also be emitted from the request.
       
  2402  */
       
  2403 void QContactManagerEngine::updateContactSaveRequest(QContactSaveRequest* req, const QList<QContact>& result, QContactManager::Error error, const QMap<int, QContactManager::Error>& errorMap, QContactAbstractRequest::State newState)
       
  2404 {
       
  2405     if (req) {
       
  2406         QWeakPointer<QContactSaveRequest> ireq(req); // Take this in case the first emit deletes us
       
  2407         QContactSaveRequestPrivate* rd = static_cast<QContactSaveRequestPrivate*>(ireq.data()->d_ptr);
       
  2408         QMutexLocker ml(&rd->m_mutex);
       
  2409         bool emitState = rd->m_state != newState;
       
  2410         rd->m_contacts = result;
       
  2411         rd->m_errors = errorMap;
       
  2412         rd->m_error = error;
       
  2413         rd->m_state = newState;
       
  2414         ml.unlock();
       
  2415         emit ireq.data()->resultsAvailable();
       
  2416         if (emitState && ireq)
       
  2417             emit ireq.data()->stateChanged(newState);
       
  2418     }
       
  2419 }
       
  2420 
       
  2421 /*!
       
  2422   Updates the given QContactDetailDefinitionSaveRequest \a req with the latest results \a result, operation error \a error, and map of input index to individual error \a errorMap.
       
  2423   In addition, the state of the request will be changed to \a newState.
       
  2424 
       
  2425   It then causes the request to emit its resultsAvailable() signal to notify clients of the request progress.
       
  2426 
       
  2427   If the new request state is different from the previous state, the stateChanged() signal will also be emitted from the request.
       
  2428  */
       
  2429 void QContactManagerEngine::updateDefinitionSaveRequest(QContactDetailDefinitionSaveRequest* req, const QList<QContactDetailDefinition>& result, QContactManager::Error error, const QMap<int, QContactManager::Error>& errorMap, QContactAbstractRequest::State newState)
       
  2430 {
       
  2431     if (req) {
       
  2432         QWeakPointer<QContactDetailDefinitionSaveRequest> ireq(req); // Take this in case the first emit deletes us
       
  2433         QContactDetailDefinitionSaveRequestPrivate* rd = static_cast<QContactDetailDefinitionSaveRequestPrivate*>(req->d_ptr);
       
  2434         QMutexLocker ml(&rd->m_mutex);
       
  2435         bool emitState = rd->m_state != newState;
       
  2436         rd->m_definitions = result;
       
  2437         rd->m_errors = errorMap;
       
  2438         rd->m_error = error;
       
  2439         rd->m_state = newState;
       
  2440         ml.unlock();
       
  2441         emit ireq.data()->resultsAvailable();
       
  2442         if (emitState && ireq)
       
  2443             emit ireq.data()->stateChanged(newState);
       
  2444     }
       
  2445 }
       
  2446 
       
  2447 /*!
       
  2448   Updates the given QContactDetailDefinitionRemoveRequest \a req with the operation error \a error, and map of input index to individual error \a errorMap.
       
  2449   In addition, the state of the request will be changed to \a newState.
       
  2450 
       
  2451   It then causes the request to emit its resultsAvailable() signal to notify clients of the request progress.
       
  2452 
       
  2453   If the new request state is different from the previous state, the stateChanged() signal will also be emitted from the request.
       
  2454  */
       
  2455 void QContactManagerEngine::updateDefinitionRemoveRequest(QContactDetailDefinitionRemoveRequest* req, QContactManager::Error error, const QMap<int, QContactManager::Error>& errorMap, QContactAbstractRequest::State newState)
       
  2456 {
       
  2457     if (req) {
       
  2458         QWeakPointer<QContactDetailDefinitionRemoveRequest> ireq(req); // Take this in case the first emit deletes us
       
  2459         QContactDetailDefinitionRemoveRequestPrivate* rd = static_cast<QContactDetailDefinitionRemoveRequestPrivate*>(req->d_ptr);
       
  2460         QMutexLocker ml(&rd->m_mutex);
       
  2461         bool emitState = rd->m_state != newState;
       
  2462         rd->m_errors = errorMap;
       
  2463         rd->m_error = error;
       
  2464         rd->m_state = newState;
       
  2465         ml.unlock();
       
  2466         emit ireq.data()->resultsAvailable();
       
  2467         if (emitState && ireq)
       
  2468             emit ireq.data()->stateChanged(newState);
       
  2469     }
       
  2470 }
       
  2471 
       
  2472 /*!
       
  2473   Updates the given QContactDetailDefinitionFetchRequest \a req with the latest results \a result, operation error \a error, and map of input index to individual error \a errorMap.
       
  2474   In addition, the state of the request will be changed to \a newState.
       
  2475 
       
  2476   It then causes the request to emit its resultsAvailable() signal to notify clients of the request progress.
       
  2477 
       
  2478   If the new request state is different from the previous state, the stateChanged() signal will also be emitted from the request.
       
  2479  */
       
  2480 void QContactManagerEngine::updateDefinitionFetchRequest(QContactDetailDefinitionFetchRequest* req, const QMap<QString, QContactDetailDefinition>& result, QContactManager::Error error, const QMap<int, QContactManager::Error>& errorMap, QContactAbstractRequest::State newState)
       
  2481 {
       
  2482     if (req) {
       
  2483         QWeakPointer<QContactDetailDefinitionFetchRequest> ireq(req); // Take this in case the first emit deletes us
       
  2484         QContactDetailDefinitionFetchRequestPrivate* rd = static_cast<QContactDetailDefinitionFetchRequestPrivate*>(req->d_ptr);
       
  2485         QMutexLocker ml(&rd->m_mutex);
       
  2486         bool emitState = rd->m_state != newState;
       
  2487         rd->m_definitions = result;
       
  2488         rd->m_errors = errorMap;
       
  2489         rd->m_error = error;
       
  2490         rd->m_state = newState;
       
  2491         ml.unlock();
       
  2492         emit ireq.data()->resultsAvailable();
       
  2493         if (emitState && ireq)
       
  2494             emit ireq.data()->stateChanged(newState);
       
  2495     }
       
  2496 }
       
  2497 
       
  2498 /*!
       
  2499   Updates the given QContactRelationshipSaveRequest \a req with the latest results \a result, operation error \a error, and map of input index to individual error \a errorMap.
       
  2500   In addition, the state of the request will be changed to \a newState.
       
  2501 
       
  2502   It then causes the request to emit its resultsAvailable() signal to notify clients of the request progress.
       
  2503 
       
  2504   If the new request state is different from the previous state, the stateChanged() signal will also be emitted from the request.
       
  2505  */
       
  2506 void QContactManagerEngine::updateRelationshipSaveRequest(QContactRelationshipSaveRequest* req, const QList<QContactRelationship>& result, QContactManager::Error error, const QMap<int, QContactManager::Error>& errorMap, QContactAbstractRequest::State newState)
       
  2507 {
       
  2508     if (req) {
       
  2509         QWeakPointer<QContactRelationshipSaveRequest> ireq(req); // Take this in case the first emit deletes us
       
  2510         QContactRelationshipSaveRequestPrivate* rd = static_cast<QContactRelationshipSaveRequestPrivate*>(req->d_ptr);
       
  2511         QMutexLocker ml(&rd->m_mutex);
       
  2512         bool emitState = rd->m_state != newState;
       
  2513         rd->m_relationships = result;
       
  2514         rd->m_errors = errorMap;
       
  2515         rd->m_error = error;
       
  2516         rd->m_state = newState;
       
  2517         ml.unlock();
       
  2518         emit ireq.data()->resultsAvailable();
       
  2519         if (emitState && ireq)
       
  2520             emit ireq.data()->stateChanged(newState);
       
  2521     }
       
  2522 }
       
  2523 
       
  2524 /*!
       
  2525   Updates the given QContactRelationshipRemoveRequest \a req with the operation error \a error, and map of input index to individual error \a errorMap.
       
  2526   In addition, the state of the request will be changed to \a newState.
       
  2527 
       
  2528   It then causes the request to emit its resultsAvailable() signal to notify clients of the request progress.
       
  2529 
       
  2530   If the new request state is different from the previous state, the stateChanged() signal will also be emitted from the request.
       
  2531  */
       
  2532 void QContactManagerEngine::updateRelationshipRemoveRequest(QContactRelationshipRemoveRequest* req, QContactManager::Error error, const QMap<int, QContactManager::Error>& errorMap, QContactAbstractRequest::State newState)
       
  2533 {
       
  2534     if (req) {
       
  2535         QWeakPointer<QContactRelationshipRemoveRequest> ireq(req); // Take this in case the first emit deletes us
       
  2536         QContactRelationshipRemoveRequestPrivate* rd = static_cast<QContactRelationshipRemoveRequestPrivate*>(req->d_ptr);
       
  2537         QMutexLocker ml(&rd->m_mutex);
       
  2538         bool emitState = rd->m_state != newState;
       
  2539         rd->m_errors = errorMap;
       
  2540         rd->m_error = error;
       
  2541         rd->m_state = newState;
       
  2542         ml.unlock();
       
  2543         emit ireq.data()->resultsAvailable();
       
  2544         if (emitState && ireq)
       
  2545             emit ireq.data()->stateChanged(newState);
       
  2546     }
       
  2547 }
       
  2548 
       
  2549 /*!
       
  2550   Updates the given QContactRelationshipFetchRequest \a req with the latest results \a result, and operation error \a error.
       
  2551   In addition, the state of the request will be changed to \a newState.
       
  2552 
       
  2553   It then causes the request to emit its resultsAvailable() signal to notify clients of the request progress.
       
  2554 
       
  2555   If the new request state is different from the previous state, the stateChanged() signal will also be emitted from the request.
       
  2556  */
       
  2557 void QContactManagerEngine::updateRelationshipFetchRequest(QContactRelationshipFetchRequest* req, const QList<QContactRelationship>& result, QContactManager::Error error, QContactAbstractRequest::State newState)
       
  2558 {
       
  2559     if (req) {
       
  2560         QWeakPointer<QContactRelationshipFetchRequest> ireq(req); // Take this in case the first emit deletes us
       
  2561         QContactRelationshipFetchRequestPrivate* rd = static_cast<QContactRelationshipFetchRequestPrivate*>(req->d_ptr);
       
  2562         QMutexLocker ml(&rd->m_mutex);
       
  2563         bool emitState = rd->m_state != newState;
       
  2564         rd->m_relationships = result;
       
  2565         rd->m_error = error;
       
  2566         rd->m_state = newState;
       
  2567         ml.unlock();
       
  2568         emit ireq.data()->resultsAvailable();
       
  2569         if (emitState && ireq)
       
  2570             emit ireq.data()->stateChanged(newState);
       
  2571     }
       
  2572 }
       
  2573 
       
  2574 #include "moc_qcontactmanagerengine.cpp"
       
  2575 
       
  2576 QTM_END_NAMESPACE