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(); |
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; |
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) |