qtmobility/src/contacts/qcontactmanagerengine.cpp
changeset 5 453da2cfceef
parent 4 90517678cc4f
child 8 71781823f776
equal deleted inserted replaced
4:90517678cc4f 5:453da2cfceef
    44 #include "qcontactdetaildefinition.h"
    44 #include "qcontactdetaildefinition.h"
    45 #include "qcontactdetailfielddefinition.h"
    45 #include "qcontactdetailfielddefinition.h"
    46 #include "qcontactdetails.h"
    46 #include "qcontactdetails.h"
    47 #include "qcontactsortorder.h"
    47 #include "qcontactsortorder.h"
    48 #include "qcontactfilters.h"
    48 #include "qcontactfilters.h"
    49 #include "qcontactaction.h"
       
    50 #include "qcontactactiondescriptor.h"
       
    51 #include "qcontactabstractrequest.h"
    49 #include "qcontactabstractrequest.h"
    52 #include "qcontactabstractrequest_p.h"
    50 #include "qcontactabstractrequest_p.h"
    53 #include "qcontactrequests.h"
    51 #include "qcontactrequests.h"
    54 #include "qcontactrequests_p.h"
    52 #include "qcontactrequests_p.h"
    55 #include "qcontact.h"
    53 #include "qcontact.h"
   226   Returns the list of contacts which match the given \a filter stored in the manager sorted according to the given list of \a sortOrders.
   224   Returns the list of contacts which match the given \a filter stored in the manager sorted according to the given list of \a sortOrders.
   227 
   225 
   228   Any operation error which occurs will be saved in \a error.
   226   Any operation error which occurs will be saved in \a error.
   229 
   227 
   230   The \a fetchHint parameter describes the optimization hints that a manager may take.
   228   The \a fetchHint parameter describes the optimization hints that a manager may take.
   231   If the \a fetchHint is the default constructed hint, all existing details, relationships and action preferences
   229   If the \a fetchHint is the default constructed hint, all existing details and relationships
   232   in the matching contacts will be returned.  A client should not make changes to a contact which has
   230   in the matching contacts will be returned.  A client should not make changes to a contact which has
   233   been retrieved using a fetch hint other than the default fetch hint.  Doing so will result in information
   231   been retrieved using a fetch hint other than the default fetch hint.  Doing so will result in information
   234   loss when saving the contact back to the manager (as the "new" restricted contact will
   232   loss when saving the contact back to the manager (as the "new" restricted contact will
   235   replace the previously saved contact in the backend).
   233   replace the previously saved contact in the backend).
   236 
   234 
   252   and the \a error will be set to  \c QContactManager::DoesNotExistError.
   250   and the \a error will be set to  \c QContactManager::DoesNotExistError.
   253 
   251 
   254   Any operation error which occurs will be saved in \a error.
   252   Any operation error which occurs will be saved in \a error.
   255 
   253 
   256   The \a fetchHint parameter describes the optimization hints that a manager may take.
   254   The \a fetchHint parameter describes the optimization hints that a manager may take.
   257   If the \a fetchHint is the default constructed hint, all existing details, relationships and action preferences
   255   If the \a fetchHint is the default constructed hint, all existing details and relationships
   258   in the matching contact will be returned.  A client should not make changes to a contact which has
   256   in the matching contact will be returned.  A client should not make changes to a contact which has
   259   been retrieved using a fetch hint other than the default fetch hint.  Doing so will result in information
   257   been retrieved using a fetch hint other than the default fetch hint.  Doing so will result in information
   260   loss when saving the contact back to the manager (as the "new" restricted contact will
   258   loss when saving the contact back to the manager (as the "new" restricted contact will
   261   replace the previously saved contact in the backend).
   259   replace the previously saved contact in the backend).
   262 
   260 
   487  */
   485  */
   488 void QContactManagerEngine::setContactDisplayLabel(QContact* contact, const QString& displayLabel)
   486 void QContactManagerEngine::setContactDisplayLabel(QContact* contact, const QString& displayLabel)
   489 {
   487 {
   490     QContactDisplayLabel dl;
   488     QContactDisplayLabel dl;
   491     dl.setValue(QContactDisplayLabel::FieldLabel, displayLabel);
   489     dl.setValue(QContactDisplayLabel::FieldLabel, displayLabel);
   492     setDetailAccessConstraints(&dl, QContactDetail::Irremovable);
   490     setDetailAccessConstraints(&dl, QContactDetail::Irremovable | QContactDetail::ReadOnly);
   493     contact->d->m_details.replace(0, dl);
   491     contact->d->m_details.replace(0, dl);
   494 }
   492 }
   495 
   493 
   496 /*!
   494 /*!
   497   Returns true if the given \a feature is supported by this engine for contacts of the given \a contactType
   495   Returns true if the given \a feature is supported by this engine for contacts of the given \a contactType
   507 /*!
   505 /*!
   508   Given an input \a filter, returns the canonical version of the filter.
   506   Given an input \a filter, returns the canonical version of the filter.
   509 
   507 
   510   Some of the following transformations may be applied:
   508   Some of the following transformations may be applied:
   511   \list
   509   \list
   512    \o Any QContactActionFilters are transformed into the corresponding
       
   513      QContactFilters returned by matching actions
       
   514    \o Any QContactInvalidFilters contained in a union filter will be removed
   510    \o Any QContactInvalidFilters contained in a union filter will be removed
   515    \o Any default QContactFilters contained in an intersection filter will be removed
   511    \o Any default QContactFilters contained in an intersection filter will be removed
   516    \o Any QContactIntersectionFilters with a QContactInvalidFilter contained will be
   512    \o Any QContactIntersectionFilters with a QContactInvalidFilter contained will be
   517      replaced with a QContactInvalidFilter
   513      replaced with a QContactInvalidFilter
   518    \o Any QContactUnionFilters with a default QContactFilter contained will be replaced
   514    \o Any QContactUnionFilters with a default QContactFilter contained will be replaced
   526   \endlist
   522   \endlist
   527 */
   523 */
   528 QContactFilter QContactManagerEngine::canonicalizedFilter(const QContactFilter &filter)
   524 QContactFilter QContactManagerEngine::canonicalizedFilter(const QContactFilter &filter)
   529 {
   525 {
   530     switch(filter.type()) {
   526     switch(filter.type()) {
   531         case QContactFilter::ActionFilter:
       
   532         {
       
   533             // Find any matching actions, and do a union filter on their filter objects
       
   534             QContactActionFilter af(filter);
       
   535             QList<QContactActionDescriptor> descriptors = QContactAction::actionDescriptors(af.actionName(), af.vendorName(), af.implementationVersion());
       
   536 
       
   537             QList<QContactFilter> filters;
       
   538             // There's a small wrinkle if there's a value specified in the action filter
       
   539             // we have to adjust any contained QContactDetailFilters to have that value
       
   540             // or test if a QContactDetailRangeFilter contains this value already
       
   541             for (int j = 0; j < descriptors.count(); j++) {
       
   542                 QContactAction* action = QContactAction::action(descriptors.at(j));
       
   543 
       
   544                 // Action filters are not allowed to return action filters, at all
       
   545                 // it's too annoying to check for recursion
       
   546                 QContactFilter d = action->contactFilter(af.value());
       
   547                 delete action; // clean up.
       
   548                 if (!validateActionFilter(d))
       
   549                     continue;
       
   550 
       
   551                 filters.append(d);
       
   552             }
       
   553 
       
   554             if (filters.count() == 0)
       
   555                 return QContactInvalidFilter();
       
   556             if (filters.count() == 1)
       
   557                 return filters.first();
       
   558 
       
   559             QContactUnionFilter f;
       
   560             f.setFilters(filters);
       
   561             return canonicalizedFilter(f);
       
   562         }
       
   563         break;
       
   564 
       
   565         case QContactFilter::IntersectionFilter:
   527         case QContactFilter::IntersectionFilter:
   566         {
   528         {
   567             QContactIntersectionFilter f(filter);
   529             QContactIntersectionFilter f(filter);
   568             QList<QContactFilter> filters = f.filters();
   530             QList<QContactFilter> filters = f.filters();
   569             QList<QContactFilter>::iterator it = filters.begin();
   531             QList<QContactFilter>::iterator it = filters.begin();
   587                 return filters.first();
   549                 return filters.first();
   588 
   550 
   589             f.setFilters(filters);
   551             f.setFilters(filters);
   590             return f;
   552             return f;
   591         }
   553         }
   592         break;
   554         // unreachable
   593 
   555 
   594         case QContactFilter::UnionFilter:
   556         case QContactFilter::UnionFilter:
   595         {
   557         {
   596             QContactUnionFilter f(filter);
   558             QContactUnionFilter f(filter);
   597             QList<QContactFilter> filters = f.filters();
   559             QList<QContactFilter> filters = f.filters();
   616                 return filters.first();
   578                 return filters.first();
   617 
   579 
   618             f.setFilters(filters);
   580             f.setFilters(filters);
   619             return f;
   581             return f;
   620         }
   582         }
   621         break;
   583         // unreachable
   622 
   584 
   623         case QContactFilter::LocalIdFilter:
   585         case QContactFilter::LocalIdFilter:
   624         {
   586         {
   625             QContactLocalIdFilter f(filter);
   587             QContactLocalIdFilter f(filter);
   626             if (f.ids().count() == 0)
   588             if (f.ids().count() == 0)
  1180 bool QContactManagerEngine::validateContact(const QContact& contact, QContactManager::Error* error) const
  1142 bool QContactManagerEngine::validateContact(const QContact& contact, QContactManager::Error* error) const
  1181 {
  1143 {
  1182     QList<QString> uniqueDefinitionIds;
  1144     QList<QString> uniqueDefinitionIds;
  1183 
  1145 
  1184     // check that each detail conforms to its definition as supported by this manager.
  1146     // check that each detail conforms to its definition as supported by this manager.
  1185     for (int i=0; i < contact.details().count(); i++) {
  1147     foreach (const QContactDetail& detail, contact.details()) {
  1186         const QContactDetail& d = contact.details().at(i);
  1148         QVariantMap values = detail.variantValues();
  1187         QVariantMap values = d.variantValues();
  1149         QContactDetailDefinition def = detailDefinition(detail.definitionName(), contact.type(), error);
  1188         QContactDetailDefinition def = detailDefinition(d.definitionName(), contact.type(), error);
       
  1189         // check that the definition is supported
  1150         // check that the definition is supported
  1190         if (*error != QContactManager::NoError) {
  1151         if (*error != QContactManager::NoError) {
  1191             *error = QContactManager::InvalidDetailError;
  1152             *error = QContactManager::InvalidDetailError;
  1192             return false; // this definition is not supported.
  1153             return false; // this definition is not supported.
  1193         }
  1154         }
  1199                 return false; // can't have two of a unique detail.
  1160                 return false; // can't have two of a unique detail.
  1200             }
  1161             }
  1201             uniqueDefinitionIds.append(def.name());
  1162             uniqueDefinitionIds.append(def.name());
  1202         }
  1163         }
  1203 
  1164 
  1204         QList<QString> keys = values.keys();
  1165         QMapIterator<QString,QVariant> fieldIt(values);
  1205         for (int i=0; i < keys.count(); i++) {
  1166         while (fieldIt.hasNext()) {
  1206             const QString& key = keys.at(i);
  1167             fieldIt.next();
       
  1168             const QString& key = fieldIt.key();
       
  1169             const QVariant& variant = fieldIt.value();
  1207             // check that no values exist for nonexistent fields.
  1170             // check that no values exist for nonexistent fields.
  1208             if (!def.fields().contains(key)) {
  1171             if (!def.fields().contains(key)) {
  1209                 *error = QContactManager::InvalidDetailError;
  1172                 *error = QContactManager::InvalidDetailError;
  1210                 return false; // value for nonexistent field.
  1173                 return false; // value for nonexistent field.
  1211             }
  1174             }
  1212 
  1175 
  1213             QContactDetailFieldDefinition field = def.fields().value(key);
  1176             QContactDetailFieldDefinition field = def.fields().value(key);
  1214             // check that the type of each value corresponds to the allowable field type
  1177             // check that the type of each value corresponds to the allowable field type
  1215             if (static_cast<int>(field.dataType()) != values.value(key).userType()) {
  1178             if (static_cast<int>(field.dataType()) != variant.userType()) {
  1216                 *error = QContactManager::InvalidDetailError;
  1179                 *error = QContactManager::InvalidDetailError;
  1217                 return false; // type doesn't match.
  1180                 return false; // type doesn't match.
  1218             }
  1181             }
  1219 
  1182 
  1220             // check that the value is allowable
  1183             // check that the value is allowable
  1221             // if the allowable values is an empty list, any are allowed.
  1184             // if the allowable values is an empty list, any are allowed.
  1222             if (!field.allowableValues().isEmpty()) {
  1185             if (!field.allowableValues().isEmpty()) {
  1223                 // if the field datatype is a list, check that it contains only allowable values
  1186                 // if the field datatype is a list, check that it contains only allowable values
  1224                 if (field.dataType() == QVariant::List || field.dataType() == QVariant::StringList) {
  1187                 if (field.dataType() == QVariant::List || field.dataType() == QVariant::StringList) {
  1225                     QList<QVariant> innerValues = values.value(key).toList();
  1188                     QList<QVariant> innerValues = variant.toList();
  1226                     for (int i = 0; i < innerValues.size(); i++) {
  1189                     QListIterator<QVariant> it(innerValues);
  1227                         if (!field.allowableValues().contains(innerValues.at(i))) {
  1190                     while (it.hasNext()) {
       
  1191                         if (!field.allowableValues().contains(it.next())) {
  1228                             *error = QContactManager::InvalidDetailError;
  1192                             *error = QContactManager::InvalidDetailError;
  1229                             return false; // value not allowed.
  1193                             return false; // value not allowed.
  1230                         }
  1194                         }
  1231                     }
  1195                     }
  1232                 } else if (!field.allowableValues().contains(values.value(key))) {
  1196                 } else if (!field.allowableValues().contains(variant)) {
  1233                     // the datatype is not a list; the value wasn't allowed.
  1197                     // the datatype is not a list; the value wasn't allowed.
  1234                     *error = QContactManager::InvalidDetailError;
  1198                     *error = QContactManager::InvalidDetailError;
  1235                     return false; // value not allowed.
  1199                     return false; // value not allowed.
  1236                 }
  1200                 }
  1237             }
  1201             }
  1506     return false;
  1470     return false;
  1507 }
  1471 }
  1508 
  1472 
  1509 /*!
  1473 /*!
  1510   Returns a pruned or modified version of the \a original contact which is valid and can be saved in the manager.
  1474   Returns a pruned or modified version of the \a original contact which is valid and can be saved in the manager.
  1511   The returned contact might have entire details removed or arbitrarily changed.  The cache of relationships
  1475   The returned contact might have details removed or arbitrarily changed.  The cache of relationships
  1512   in the contact are ignored entirely when considering compatibility with the backend, as they are
  1476   in the contact are ignored entirely when considering compatibility with the backend, as they are
  1513   saved and validated separately.  Any error which occurs will be saved to \a error.
  1477   saved and validated separately.  Any error which occurs will be saved to \a error.
  1514  */
  1478  */
  1515 QContact QContactManagerEngine::compatibleContact(const QContact& original, QContactManager::Error* error) const
  1479 QContact QContactManagerEngine::compatibleContact(const QContact& original, QContactManager::Error* error) const
  1516 {
  1480 {
  1517     QContact conforming;
  1481     QContact conforming;
       
  1482     conforming.setId(original.id());
  1518     QContactManager::Error tempError;
  1483     QContactManager::Error tempError;
  1519     QList<QString> uniqueDefinitionIds;
  1484     QList<QString> uniqueDefinitionIds;
  1520     QList<QContactDetail> allDetails = original.details();
  1485     foreach (QContactDetail detail, original.details()) {
  1521     QMap<QString, QContactDetailDefinition> defs = detailDefinitions(original.type(), &tempError);
       
  1522     for (int j = 0; j < allDetails.size(); j++) {
       
  1523         // check that the detail conforms to the definition in this manager.
  1486         // check that the detail conforms to the definition in this manager.
  1524         // if so, then add it to the conforming contact to be returned.  if not, prune it.
  1487         // if so, then add it to the conforming contact to be returned.  if not, prune it.
  1525         const QContactDetail& d = allDetails.at(j);
  1488 
  1526 
  1489         QVariantMap values = detail.variantValues();
  1527         QVariantMap values = d.variantValues();
  1490         QContactDetailDefinition def = detailDefinition(detail.definitionName(), original.type(), &tempError);
  1528         QContactDetailDefinition def = detailDefinition(d.definitionName(), original.type(), &tempError);
       
  1529         // check that the definition is supported
  1491         // check that the definition is supported
  1530         if (*error != QContactManager::NoError) {
  1492         if (tempError != QContactManager::NoError) {
  1531             continue; // this definition is not supported.
  1493             continue; // this definition is not supported.
  1532         }
  1494         }
  1533 
  1495 
  1534         // check uniqueness
  1496         // check uniqueness
  1535         if (def.isUnique()) {
  1497         if (def.isUnique()) {
  1537                 continue; // can't have two of a unique detail.
  1499                 continue; // can't have two of a unique detail.
  1538             }
  1500             }
  1539             uniqueDefinitionIds.append(def.name());
  1501             uniqueDefinitionIds.append(def.name());
  1540         }
  1502         }
  1541 
  1503 
  1542         bool addToConforming = true;
  1504         QMapIterator<QString,QVariant> fieldIt(values);
  1543         QList<QString> keys = values.keys();
  1505         while (fieldIt.hasNext()) {
  1544         for (int i=0; i < keys.count(); i++) {
  1506             fieldIt.next();
  1545             const QString& key = keys.at(i);
  1507             const QString& key = fieldIt.key();
  1546             // check that no values exist for nonexistent fields.
  1508             const QVariant& variant = fieldIt.value();
       
  1509             // prune values for nonexistent fields.
  1547             if (!def.fields().contains(key)) {
  1510             if (!def.fields().contains(key)) {
  1548                 addToConforming = false;
  1511                 detail.removeValue(key);
  1549                 break; // value for nonexistent field.
       
  1550             }
  1512             }
  1551 
  1513 
  1552             QContactDetailFieldDefinition field = def.fields().value(key);
  1514             QContactDetailFieldDefinition field = def.fields().value(key);
  1553             // check that the type of each value corresponds to the allowable field type
  1515             // prune values that do not correspond to the allowable field type
  1554             if (static_cast<int>(field.dataType()) != values.value(key).userType()) {
  1516             if (static_cast<int>(field.dataType()) != variant.userType()) {
  1555                 addToConforming = false;
  1517                 detail.removeValue(key);
  1556                 break; // type doesn't match.
       
  1557             }
  1518             }
  1558 
  1519 
  1559             // check that the value is allowable
  1520             // check that the value is allowable
  1560             // if the allowable values is an empty list, any are allowed.
  1521             // if the allowable values is an empty list, any are allowed.
  1561             if (!field.allowableValues().isEmpty()) {
  1522             if (!field.allowableValues().isEmpty()) {
  1562                 // if the field datatype is a list, check that it contains only allowable values
  1523                 // if the field datatype is a list, remove non-allowable values
  1563                 if (field.dataType() == QVariant::List || field.dataType() == QVariant::StringList) {
  1524                 if (field.dataType() == QVariant::List || field.dataType() == QVariant::StringList) {
  1564                     QList<QVariant> innerValues = values.value(key).toList();
  1525                     QList<QVariant> innerValues = variant.toList();
  1565                     for (int i = 0; i < innerValues.size(); i++) {
  1526                     QMutableListIterator<QVariant> it(innerValues);
  1566                         if (!field.allowableValues().contains(innerValues.at(i))) {
  1527                     while (it.hasNext()) {
  1567                             addToConforming = false;
  1528                         if (!field.allowableValues().contains(it.next())) {
  1568                             break; // value not allowed.
  1529                             it.remove();
  1569                         }
  1530                         }
  1570                     }
  1531                     }
  1571                 } else if (!field.allowableValues().contains(values.value(key))) {
  1532                     if (innerValues.isEmpty())
  1572                     // the datatype is not a list; the value wasn't allowed.
  1533                         detail.removeValue(key);
  1573                     addToConforming = false;
  1534                     else
  1574                     break; // value not allowed.
  1535                         detail.setValue(key, innerValues);
       
  1536                 } else if (!field.allowableValues().contains(variant)) {
       
  1537                     detail.removeValue(key);
  1575                 }
  1538                 }
  1576             }
  1539             }
  1577         }
  1540         }
  1578 
  1541 
  1579         // if it conforms to this manager's schema, save it in the conforming contact
  1542         // if it hasn't been pruned away to nothing, save it in the conforming contact
  1580         // else, ignore it (prune it out of the conforming contact).
  1543         if (!detail.isEmpty()) {
  1581         if (addToConforming) {
  1544             conforming.saveDetail(&detail);
  1582             QContactDetail saveCopy = d;
       
  1583             conforming.saveDetail(&saveCopy);
       
  1584         }
  1545         }
  1585     }
  1546     }
  1586 
  1547 
  1587     if (!conforming.isEmpty())
  1548     if (!conforming.isEmpty())
  1588         *error = QContactManager::NoError;
  1549         *error = QContactManager::NoError;
  1660  */
  1621  */
  1661 bool QContactManagerEngine::testFilter(const QContactFilter &filter, const QContact &contact)
  1622 bool QContactManagerEngine::testFilter(const QContactFilter &filter, const QContact &contact)
  1662 {
  1623 {
  1663     switch(filter.type()) {
  1624     switch(filter.type()) {
  1664         case QContactFilter::InvalidFilter:
  1625         case QContactFilter::InvalidFilter:
       
  1626         case QContactFilter::ActionFilter:
  1665             return false;
  1627             return false;
  1666 
  1628 
  1667         case QContactFilter::DefaultFilter:
  1629         case QContactFilter::DefaultFilter:
  1668             return true;
  1630             return true;
  1669 
  1631 
  1988                 // You can't emulate a removed..
  1950                 // You can't emulate a removed..
  1989                 // Fall through to end
  1951                 // Fall through to end
  1990             }
  1952             }
  1991             break;
  1953             break;
  1992 
  1954 
  1993         case QContactFilter::ActionFilter:
       
  1994             {
       
  1995                 // Find any matching actions, and do a union filter on their filter objects
       
  1996                 QContactActionFilter af(filter);
       
  1997                 QList<QContactActionDescriptor> descriptors = QContactAction::actionDescriptors(af.actionName(), af.vendorName(), af.implementationVersion());
       
  1998 
       
  1999                 // There's a small wrinkle if there's a value specified in the action filter
       
  2000                 // we have to adjust any contained QContactDetailFilters to have that value
       
  2001                 // or test if a QContactDetailRangeFilter contains this value already
       
  2002                 for (int j = 0; j < descriptors.count(); j++) {
       
  2003                     QContactAction* action = QContactAction::action(descriptors.at(j));
       
  2004 
       
  2005                     // Action filters are not allowed to return action filters, at all
       
  2006                     // it's too annoying to check for recursion
       
  2007                     QContactFilter d = action->contactFilter(af.value());
       
  2008                     delete action; // clean up.
       
  2009                     if (!validateActionFilter(d))
       
  2010                         return false;
       
  2011 
       
  2012                     // Check for values etc...
       
  2013                     if (testFilter(d, contact))
       
  2014                         return true;
       
  2015                 }
       
  2016                 // Fall through to end
       
  2017             }
       
  2018             break;
       
  2019 
       
  2020         case QContactFilter::IntersectionFilter:
  1955         case QContactFilter::IntersectionFilter:
  2021             {
  1956             {
  2022                 /* XXX In theory we could reorder the terms to put the native tests first */
  1957                 /* XXX In theory we could reorder the terms to put the native tests first */
  2023                 const QContactIntersectionFilter bf(filter);
  1958                 const QContactIntersectionFilter bf(filter);
  2024                 const QList<QContactFilter>& terms = bf.filters();
  1959                 const QList<QContactFilter>& terms = bf.filters();
  2053     }
  1988     }
  2054     return false;
  1989     return false;
  2055 }
  1990 }
  2056 
  1991 
  2057 /*!
  1992 /*!
  2058   Given a QContactFilter \a filter retrieved from a QContactAction,
       
  2059   check that it is valid and cannot cause infinite recursion.
       
  2060 
       
  2061   In particular, a filter from a QContactAction cannot contain
       
  2062   any instances of a QContactActionFilter.
       
  2063 
       
  2064   Returns true if \a filter seems ok, or false otherwise.
       
  2065  */
       
  2066 
       
  2067 bool QContactManagerEngine::validateActionFilter(const QContactFilter& filter)
       
  2068 {
       
  2069     QList<QContactFilter> toVerify;
       
  2070     toVerify << filter;
       
  2071 
       
  2072     while(toVerify.count() > 0) {
       
  2073         QContactFilter f = toVerify.takeFirst();
       
  2074         if (f.type() == QContactFilter::ActionFilter)
       
  2075             return false;
       
  2076         if (f.type() == QContactFilter::IntersectionFilter)
       
  2077             toVerify.append(QContactIntersectionFilter(f).filters());
       
  2078         if (f.type() == QContactFilter::UnionFilter)
       
  2079             toVerify.append(QContactUnionFilter(f).filters());
       
  2080     }
       
  2081 
       
  2082     return true;
       
  2083 }
       
  2084 
       
  2085 /*!
       
  2086   Sets the cached relationships in the given \a contact to \a relationships
  1993   Sets the cached relationships in the given \a contact to \a relationships
  2087  */
  1994  */
  2088 void QContactManagerEngine::setContactRelationships(QContact* contact, const QList<QContactRelationship>& relationships)
  1995 void QContactManagerEngine::setContactRelationships(QContact* contact, const QList<QContactRelationship>& relationships)
  2089 {
  1996 {
  2090     contact->d->m_relationshipsCache = relationships;
  1997     contact->d->m_relationshipsCache = relationships;
  2091     contact->d->m_reorderedRelationshipsCache = relationships;
       
  2092 }
  1998 }
  2093 
  1999 
  2094 
  2000 
  2095 /*!
  2001 /*!
  2096   Compares two contacts (\a a and \a b) using the given list of \a sortOrders.  Returns a negative number if \a a should appear
  2002   Compares two contacts (\a a and \a b) using the given list of \a sortOrders.  Returns a negative number if \a a should appear
  2108 
  2014 
  2109         // obtain the values which this sort order concerns
  2015         // obtain the values which this sort order concerns
  2110         const QVariant& aVal = a.detail(sortOrder.detailDefinitionName()).variantValue(sortOrder.detailFieldName());
  2016         const QVariant& aVal = a.detail(sortOrder.detailDefinitionName()).variantValue(sortOrder.detailFieldName());
  2111         const QVariant& bVal = b.detail(sortOrder.detailDefinitionName()).variantValue(sortOrder.detailFieldName());
  2017         const QVariant& bVal = b.detail(sortOrder.detailDefinitionName()).variantValue(sortOrder.detailFieldName());
  2112 
  2018 
       
  2019         bool aIsNull = false;
       
  2020         bool bIsNull = false;
       
  2021 
       
  2022         // treat empty strings as null qvariants.
       
  2023         if ((aVal.type() == QVariant::String && aVal.toString().isEmpty()) || aVal.isNull()) {
       
  2024             aIsNull = true;
       
  2025         }
       
  2026         if ((bVal.type() == QVariant::String && bVal.toString().isEmpty()) || bVal.isNull()) {
       
  2027             bIsNull = true;
       
  2028         }
       
  2029 
  2113         // early exit error checking
  2030         // early exit error checking
  2114         if (aVal.isNull())
  2031         if (aIsNull && bIsNull)
       
  2032             continue; // use next sort criteria.
       
  2033         if (aIsNull)
  2115             return (sortOrder.blankPolicy() == QContactSortOrder::BlanksFirst ? -1 : 1);
  2034             return (sortOrder.blankPolicy() == QContactSortOrder::BlanksFirst ? -1 : 1);
  2116         if (bVal.isNull())
  2035         if (bIsNull)
  2117             return (sortOrder.blankPolicy() == QContactSortOrder::BlanksFirst ? 1 : -1);
  2036             return (sortOrder.blankPolicy() == QContactSortOrder::BlanksFirst ? 1 : -1);
  2118 
  2037 
  2119         // real comparison
  2038         // real comparison
  2120         int comparison = compareVariant(aVal, bVal, sortOrder.caseSensitivity()) * (sortOrder.direction() == Qt::AscendingOrder ? 1 : -1);
  2039         int comparison = compareVariant(aVal, bVal, sortOrder.caseSensitivity()) * (sortOrder.direction() == Qt::AscendingOrder ? 1 : -1);
  2121         if (comparison == 0)
  2040         if (comparison == 0)