| 1 | /**************************************************************************** |
| 2 | ** |
| 3 | ** Copyright (C) 2015 The Qt Company Ltd. |
| 4 | ** Contact: http://www.qt.io/licensing/ |
| 5 | ** |
| 6 | ** This file is part of the test suite of the Qt Toolkit. |
| 7 | ** |
| 8 | ** $QT_BEGIN_LICENSE:LGPL21$ |
| 9 | ** Commercial License Usage |
| 10 | ** Licensees holding valid commercial Qt licenses may use this file in |
| 11 | ** accordance with the commercial license agreement provided with the |
| 12 | ** Software or, alternatively, in accordance with the terms contained in |
| 13 | ** a written agreement between you and The Qt Company. For licensing terms |
| 14 | ** and conditions see http://www.qt.io/terms-conditions. For further |
| 15 | ** information use the contact form at http://www.qt.io/contact-us. |
| 16 | ** |
| 17 | ** GNU Lesser General Public License Usage |
| 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
| 19 | ** General Public License version 2.1 or version 3 as published by the Free |
| 20 | ** Software Foundation and appearing in the file LICENSE.LGPLv21 and |
| 21 | ** LICENSE.LGPLv3 included in the packaging of this file. Please review the |
| 22 | ** following information to ensure the GNU Lesser General Public License |
| 23 | ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and |
| 24 | ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
| 25 | ** |
| 26 | ** As a special exception, The Qt Company gives you certain additional |
| 27 | ** rights. These rights are described in The Qt Company LGPL Exception |
| 28 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
| 29 | ** |
| 30 | ** $QT_END_LICENSE$ |
| 31 | ** |
| 32 | ****************************************************************************/ |
| 33 | |
| 34 | #define QT_STATICPLUGIN |
| 35 | #include <QtTest/QtTest> |
| 36 | |
| 37 | #ifdef INCLUDE_TESTACTIONS |
| 38 | #include <QServiceManager> |
| 39 | #endif |
| 40 | #include <QtContacts> |
| 41 | #include "qcontactmanagerdataholder.h" //QContactManagerDataHolder |
| 42 | |
| 43 | #include <QLocale> |
| 44 | #ifdef Q_OS_UNIX |
| 45 | #include <locale.h> |
| 46 | #endif |
| 47 | |
| 48 | //TESTED_COMPONENT=src/contacts |
| 49 | |
| 50 | // Q_ASSERT replacement, since we often run in release builds |
| 51 | #define Q_FATAL_VERIFY(statement) \ |
| 52 | do { \ |
| 53 | if (!QTest::qVerify((statement), #statement, "", __FILE__, __LINE__)) \ |
| 54 | qFatal("severe failure encountered, test cannot continue"); \ |
| 55 | } while (0) |
| 56 | |
| 57 | QTCONTACTS_USE_NAMESPACE |
| 58 | /* |
| 59 | * This test is mostly just for testing sorting and filtering - |
| 60 | * having it in tst_QContactManager makes maintenance more |
| 61 | * difficult! |
| 62 | */ |
| 63 | |
| 64 | Q_DECLARE_METATYPE(QVariant) |
| 65 | Q_DECLARE_METATYPE(QContactManager*) |
| 66 | Q_DECLARE_METATYPE(QContactDetail::DetailType) |
| 67 | |
| 68 | /* |
| 69 | * Global variables: |
| 70 | * These are the definition and field names used by the actions for their matching. |
| 71 | */ |
| 72 | QMap<QString, QPair<QContactDetail::DetailType, int> > defAndFieldNamesForTypeForActions; |
| 73 | |
| 74 | namespace { |
| 75 | |
| 76 | bool validDetailType(const QPair<QContactDetail::DetailType, int> &pair) |
| 77 | { |
| 78 | return pair.first != QContactDetail::TypeUndefined; |
| 79 | } |
| 80 | |
| 81 | bool validDetailField(const QPair<QContactDetail::DetailType, int> &pair) |
| 82 | { |
| 83 | return pair.first != QContactDetail::TypeUndefined && pair.second != -1; |
| 84 | } |
| 85 | |
| 86 | } |
| 87 | |
| 88 | /* |
| 89 | * We use this code to compare the output and expected lists of filtering |
| 90 | * where no sort order is implied. |
| 91 | * TODO: use this instead of QCOMPARE in the various filtering tests! |
| 92 | */ |
| 93 | #define QCOMPARE_UNSORTED(output, expected) if (output.size() != expected.size()) { \ |
| 94 | QCOMPARE(output, expected); \ |
| 95 | } else { \ |
| 96 | for (int i = 0; i < output.size(); i++) { \ |
| 97 | if (!expected.contains(output.at(i))) { \ |
| 98 | QCOMPARE(output, expected); \ |
| 99 | } \ |
| 100 | } \ |
| 101 | } |
| 102 | |
| 103 | class tst_QContactManagerFiltering : public QObject |
| 104 | { |
| 105 | Q_OBJECT |
| 106 | |
| 107 | public: |
| 108 | tst_QContactManagerFiltering(); |
| 109 | virtual ~tst_QContactManagerFiltering(); |
| 110 | |
| 111 | private: |
| 112 | void dumpContactDifferences(const QContact& a, const QContact& b); |
| 113 | void dumpContact(const QContact &c); |
| 114 | void dumpContacts(); |
| 115 | bool isSuperset(const QContact& ca, const QContact& cb); |
| 116 | |
| 117 | QList<QContactId> prepareModel(QContactManager* cm); // add the standard contacts |
| 118 | |
| 119 | QString convertIds(QList<QContactId> allIds, QList<QContactId> ids, QChar minimumContact = 'a', QChar maximumContact = 'z'); // convert back to "abcd" |
| 120 | QContact createContact(QContactManager* cm, QContactType::TypeValues type, const QString &name); |
| 121 | |
| 122 | QMap<QContactManager*, QMap<QString, QPair<QContactDetail::DetailType, int> > > defAndFieldNamesForTypePerManager; |
| 123 | QMultiMap<QContactManager*, QContactId> contactsAddedToManagers; |
| 124 | QList<QContactManager*> managers; |
| 125 | QScopedPointer<QContactManagerDataHolder> managerDataHolder; |
| 126 | |
| 127 | QTestData& newMRow(const char *tag, QContactManager *cm); |
| 128 | |
| 129 | private slots: |
| 130 | |
| 131 | void initTestCase(); |
| 132 | void cleanupTestCase(); |
| 133 | |
| 134 | void rangeFiltering(); // XXX should take all managers |
| 135 | void rangeFiltering_data(); |
| 136 | |
| 137 | void detailStringFiltering(); // XXX should take all managers |
| 138 | void detailStringFiltering_data(); |
| 139 | |
| 140 | void detailPhoneNumberFiltering(); |
| 141 | void detailPhoneNumberFiltering_data(); |
| 142 | |
| 143 | #ifdef INCLUDE_TESTACTIONS |
| 144 | void actionPlugins(); |
| 145 | void actionFiltering(); |
| 146 | void actionFiltering_data(); |
| 147 | #endif |
| 148 | |
| 149 | void detailVariantFiltering(); |
| 150 | void detailVariantFiltering_data(); |
| 151 | |
| 152 | void intersectionFiltering(); |
| 153 | void intersectionFiltering_data(); |
| 154 | |
| 155 | void unionFiltering(); |
| 156 | void unionFiltering_data(); |
| 157 | |
| 158 | void relationshipFiltering(); |
| 159 | void relationshipFiltering_data(); |
| 160 | |
| 161 | void changelogFiltering(); |
| 162 | void changelogFiltering_data(); |
| 163 | |
| 164 | void idListFiltering(); |
| 165 | void idListFiltering_data(); |
| 166 | |
| 167 | void convenienceFiltering(); |
| 168 | void convenienceFiltering_data(); |
| 169 | |
| 170 | void sorting(); // XXX should take all managers |
| 171 | void sorting_data(); |
| 172 | |
| 173 | void multiSorting(); |
| 174 | void multiSorting_data(); |
| 175 | |
| 176 | void invalidFiltering_data(); |
| 177 | void invalidFiltering(); |
| 178 | |
| 179 | void allFiltering_data(); |
| 180 | void allFiltering(); |
| 181 | |
| 182 | void fetchHint_data(); |
| 183 | void fetchHint(); |
| 184 | |
| 185 | private: |
| 186 | enum CollationSemantics { |
| 187 | UpperFirst = 0, // XYxy |
| 188 | LowerFirst = 1, // xyXY |
| 189 | InterleavedUpperFirst = 2, // XxYy |
| 190 | InterleavedLowerFirst = 3, // xXyY |
| 191 | FirstPassInterleavedUpperFirst = 4, // xxy < Xxz even though xxy > Xxy |
| 192 | FirstPassInterleavedLowerFirst = 5, // XXY < Xxz even though XXY > Xxy |
| 193 | UnknownCollation = 6 |
| 194 | }; |
| 195 | QHash<QContactManager *, int> m_collation; |
| 196 | QString expectedSorting(QContactManager *m, const QString &ufs, const QString &lfs, const QString &iufs, const QString &ilfs, const QString &fpiufs, const QString &fpilfs) { |
| 197 | switch (m_collation[m]) { |
| 198 | case UpperFirst: return ufs; |
| 199 | case LowerFirst: return lfs; |
| 200 | case InterleavedUpperFirst: return iufs; |
| 201 | case InterleavedLowerFirst: return ilfs; |
| 202 | case FirstPassInterleavedUpperFirst: return fpiufs; |
| 203 | case FirstPassInterleavedLowerFirst: return fpilfs; |
| 204 | default: return QLatin1String("unknowncollation" ); |
| 205 | } |
| 206 | } |
| 207 | }; |
| 208 | |
| 209 | tst_QContactManagerFiltering::tst_QContactManagerFiltering() |
| 210 | { |
| 211 | // In order to make our tests reliable, set the C locale |
| 212 | QLocale::setDefault(QLocale::c()); |
| 213 | |
| 214 | #if defined(Q_OS_UNIX) && !defined(QT_USE_ICU) |
| 215 | // Without ICU, we also need to set the locale on unix |
| 216 | ::setlocale(LC_ALL, locale: "C" ); |
| 217 | #endif |
| 218 | } |
| 219 | |
| 220 | tst_QContactManagerFiltering::~tst_QContactManagerFiltering() |
| 221 | { |
| 222 | } |
| 223 | |
| 224 | void tst_QContactManagerFiltering::initTestCase() |
| 225 | { |
| 226 | managerDataHolder.reset(other: new QContactManagerDataHolder()); |
| 227 | |
| 228 | // firstly, build a list of the managers we wish to test. |
| 229 | QStringList managerNames = QContactManager::availableManagers(); |
| 230 | |
| 231 | /* Known one that will not pass */ |
| 232 | managerNames.removeAll(t: "invalid" ); |
| 233 | managerNames.removeAll(t: "testdummy" ); |
| 234 | managerNames.removeAll(t: "teststaticdummy" ); |
| 235 | managerNames.removeAll(t: "maliciousplugin" ); |
| 236 | |
| 237 | // Some internal engines on Maemo6 |
| 238 | managerNames.removeAll(t: "social" ); |
| 239 | managerNames.removeAll(t: "simcard" ); |
| 240 | managerNames.removeAll(t: "com.nokia.messaging.contacts.engines.mail.contactslookup" ); |
| 241 | |
| 242 | foreach(QString mgr, managerNames) { |
| 243 | QMap<QString, QString> params; |
| 244 | QString mgrUri = QContactManager::buildUri(managerName: mgr, params); |
| 245 | QContactManager* cm = QContactManager::fromUri(uri: mgrUri); |
| 246 | cm->setObjectName(mgr); |
| 247 | managers.append(t: cm); |
| 248 | |
| 249 | if (mgr == "memory" ) { |
| 250 | params.insert(akey: "id" , avalue: "tst_QContactManager" ); |
| 251 | mgrUri = QContactManager::buildUri(managerName: mgr, params); |
| 252 | cm = QContactManager::fromUri(uri: mgrUri); |
| 253 | cm->setObjectName("memory[params]" ); |
| 254 | managers.append(t: cm); |
| 255 | } |
| 256 | } |
| 257 | |
| 258 | // for each manager that we wish to test, prepare the model. |
| 259 | foreach (QContactManager* cm, managers) { |
| 260 | QList<QContactId> addedContacts = prepareModel(cm); |
| 261 | if (addedContacts != contactsAddedToManagers.values(akey: cm)) { |
| 262 | qDebug() << "prepareModel returned:" << addedContacts; |
| 263 | qDebug() << "contactsAdded are: " << contactsAddedToManagers.values(akey: cm); |
| 264 | qFatal(msg: "returned list different from saved contacts list!" ); |
| 265 | } |
| 266 | |
| 267 | // Also determine the string collation / sorting semantics. |
| 268 | // Case sensitivity is handled differently with/without ICU |
| 269 | // (in one case, the char sequence is 'A-Za-z', in the other it |
| 270 | // is 'AaBb..Zz') - the results are therefore highly divergent. |
| 271 | // To do so, we need to add some extra contacts. |
| 272 | QContact contactxxy, contactXxy, contactXXY, contactXxz; |
| 273 | QContactName xxn; |
| 274 | xxn.setFirstName("xxy" ); |
| 275 | contactxxy.saveDetail(detail: &xxn); |
| 276 | xxn.setFirstName("Xxy" ); |
| 277 | contactXxy.saveDetail(detail: &xxn); |
| 278 | xxn.setFirstName("XXY" ); |
| 279 | contactXXY.saveDetail(detail: &xxn); |
| 280 | xxn.setFirstName("Xxz" ); |
| 281 | contactXxz.saveDetail(detail: &xxn); |
| 282 | Q_FATAL_VERIFY(cm->saveContact(&contactxxy)); |
| 283 | Q_FATAL_VERIFY(cm->saveContact(&contactXxy)); |
| 284 | Q_FATAL_VERIFY(cm->saveContact(&contactXXY)); |
| 285 | Q_FATAL_VERIFY(cm->saveContact(&contactXxz)); |
| 286 | |
| 287 | // Now fetch sorted contacts to determine sorting semantics. |
| 288 | QContactSortOrder s; |
| 289 | s.setDetailType(type: QContactName::Type, field: QContactName::FieldFirstName); |
| 290 | s.setDirection(Qt::AscendingOrder); |
| 291 | QList<QContact> sortedContacts = cm->contacts(sortOrders: s); |
| 292 | int xanderIndex = -1, XanderIndex = -1, yarrowIndex = -1, YarrowIndex = -1; |
| 293 | int xxyIndex = -1, XxyIndex = -1, XXYIndex = -1, XxzIndex = -1; |
| 294 | for (int i = 0; i < sortedContacts.size(); ++i) { |
| 295 | if (sortedContacts[i].detail<QContactName>().firstName() == QStringLiteral("xander" )) { |
| 296 | xanderIndex = i; |
| 297 | } else if (sortedContacts[i].detail<QContactName>().firstName() == QStringLiteral("Xander" )) { |
| 298 | XanderIndex = i; |
| 299 | } else if (sortedContacts[i].detail<QContactName>().firstName() == QStringLiteral("yarrow" )) { |
| 300 | yarrowIndex = i; |
| 301 | } else if (sortedContacts[i].detail<QContactName>().firstName() == QStringLiteral("Yarrow" )) { |
| 302 | YarrowIndex = i; |
| 303 | } else if (sortedContacts[i].detail<QContactName>().firstName() == QStringLiteral("xxy" )) { |
| 304 | xxyIndex = i; |
| 305 | } else if (sortedContacts[i].detail<QContactName>().firstName() == QStringLiteral("Xxy" )) { |
| 306 | XxyIndex = i; |
| 307 | } else if (sortedContacts[i].detail<QContactName>().firstName() == QStringLiteral("XXY" )) { |
| 308 | XXYIndex = i; |
| 309 | } else if (sortedContacts[i].detail<QContactName>().firstName() == QStringLiteral("Xxz" )) { |
| 310 | XxzIndex = i; |
| 311 | } |
| 312 | } |
| 313 | |
| 314 | if (XanderIndex < YarrowIndex && YarrowIndex < xanderIndex && xanderIndex < yarrowIndex && |
| 315 | XXYIndex < XxyIndex && XxyIndex < XxzIndex && XxzIndex < xxyIndex) { |
| 316 | //qDebug() << "XYxy, and XXY<Xxy<Xxz<xxy :. upper first sorting:" |
| 317 | // << "x:" << xanderIndex << "X:" << XanderIndex << "y:" << yarrowIndex << "Y:" << YarrowIndex |
| 318 | // << "xxy:" << xxyIndex << "Xxy:" << XxyIndex << "XXY:" << XXYIndex << "Xxz:" << XxzIndex; |
| 319 | m_collation[cm] = UpperFirst; |
| 320 | } else if (xanderIndex < yarrowIndex && yarrowIndex < XanderIndex && XanderIndex < YarrowIndex && |
| 321 | xxyIndex < XxyIndex && XxyIndex < XxzIndex && XxzIndex < XXYIndex) { |
| 322 | //qDebug() << "xyXY, and xxy<Xxy<Xxz<XXY :. lower first sorting:" |
| 323 | // << "x:" << xanderIndex << "X:" << XanderIndex << "y:" << yarrowIndex << "Y:" << YarrowIndex |
| 324 | // << "xxy:" << xxyIndex << "Xxy:" << XxyIndex << "XXY:" << XXYIndex << "Xxz:" << XxzIndex; |
| 325 | m_collation[cm] = LowerFirst; |
| 326 | } else if (XanderIndex < xanderIndex && xanderIndex < YarrowIndex && YarrowIndex < yarrowIndex && |
| 327 | XXYIndex < XxyIndex && XxyIndex < XxzIndex && XxzIndex < xxyIndex) { |
| 328 | //qDebug() << "XxYy, and XXY<Xxy<Xxz<xxy :. interleaved upper first sorting without first-pass case-insensitive characterwise comparison:" |
| 329 | // << "x:" << xanderIndex << "X:" << XanderIndex << "y:" << yarrowIndex << "Y:" << YarrowIndex |
| 330 | // << "xxy:" << xxyIndex << "Xxy:" << XxyIndex << "XXY:" << XXYIndex << "Xxz:" << XxzIndex; |
| 331 | m_collation[cm] = InterleavedUpperFirst; |
| 332 | } else if (xanderIndex < XanderIndex && XanderIndex < yarrowIndex && yarrowIndex < YarrowIndex && |
| 333 | xxyIndex < XxyIndex && XxyIndex < XxzIndex && XxzIndex < XXYIndex) { |
| 334 | //qDebug() << "xXyY, and xxy<Xxy<Xxz<XXY :. interleaved lower first sorting without first-pass case-insensitive characterwise comparison:" |
| 335 | // << "x:" << xanderIndex << "X:" << XanderIndex << "y:" << yarrowIndex << "Y:" << YarrowIndex |
| 336 | // << "xxy:" << xxyIndex << "Xxy:" << XxyIndex << "XXY:" << XXYIndex << "Xxz:" << XxzIndex; |
| 337 | m_collation[cm] = InterleavedLowerFirst; |
| 338 | } else if (XanderIndex < xanderIndex && xanderIndex < YarrowIndex && YarrowIndex < yarrowIndex && |
| 339 | XXYIndex < XxyIndex && XxyIndex < xxyIndex && xxyIndex < XxzIndex) { |
| 340 | //qDebug() << "XxYy, and XXY<Xxy<xxy<Xxz :. interleaved upper first sorting without first-pass case-insensitive characterwise comparison:" |
| 341 | // << "x:" << xanderIndex << "X:" << XanderIndex << "y:" << yarrowIndex << "Y:" << YarrowIndex |
| 342 | // << "xxy:" << xxyIndex << "Xxy:" << XxyIndex << "XXY:" << XXYIndex << "Xxz:" << XxzIndex; |
| 343 | m_collation[cm] = FirstPassInterleavedUpperFirst; |
| 344 | } else if (xanderIndex < XanderIndex && XanderIndex < yarrowIndex && yarrowIndex < YarrowIndex && |
| 345 | xxyIndex < XxyIndex && XxyIndex < XXYIndex && XXYIndex < XxzIndex) { |
| 346 | //qDebug() << "xXyY, and xxy<Xxy<XXY<Xxz :. interleaved lower first sorting with first-pass case-insensitive characterwise comparison:" |
| 347 | // << "x:" << xanderIndex << "X:" << XanderIndex << "y:" << yarrowIndex << "Y:" << YarrowIndex |
| 348 | // << "xxy:" << xxyIndex << "Xxy:" << XxyIndex << "XXY:" << XXYIndex << "Xxz:" << XxzIndex; |
| 349 | m_collation[cm] = FirstPassInterleavedLowerFirst; |
| 350 | } else { |
| 351 | qDebug() << "unknown sorting:" |
| 352 | << "x:" << xanderIndex << "X:" << XanderIndex << "y:" << yarrowIndex << "Y:" << YarrowIndex |
| 353 | << "xxy:" << xxyIndex << "Xxy:" << XxyIndex << "XXY:" << XXYIndex << "Xxz:" << XxzIndex; |
| 354 | m_collation[cm] = UnknownCollation; |
| 355 | } |
| 356 | |
| 357 | QList<QContactId> cleanup; |
| 358 | cleanup << contactxxy.id() << contactXxy.id() << contactXXY.id() << contactXxz.id(); |
| 359 | Q_FATAL_VERIFY(cm->removeContacts(cleanup)); |
| 360 | } |
| 361 | |
| 362 | #ifdef INCLUDE_TESTACTIONS |
| 363 | qDebug() << "Finished preparing each manager for test! About to load test actions:" ; |
| 364 | QServiceManager sm; |
| 365 | QStringList allServices = sm.findServices(); |
| 366 | foreach(const QString& serv, allServices) { |
| 367 | if (serv.startsWith("tst_qcontactmanagerfiltering:" )) { |
| 368 | if (!sm.removeService(serv)) { |
| 369 | qDebug() << " tst_qca: ctor: cleaning up test service" << serv << "failed:" << sm.error(); |
| 370 | } |
| 371 | } |
| 372 | } |
| 373 | QStringList myServices; |
| 374 | myServices << "BooleanAction" << "DateAction" << "IntegerAction" << "NumberAction" << "PhoneNumberAction" ; |
| 375 | foreach (const QString& serv, myServices) { |
| 376 | QString builtPath = QCoreApplication::applicationDirPath() + "/plugins/contacts/xmldata/" + serv.toLower() + "service.xml" ; |
| 377 | if (!sm.addService(builtPath)) { |
| 378 | qDebug() << " tst_qca: ctor: unable to add" << serv << "service:" << sm.error(); |
| 379 | } |
| 380 | } |
| 381 | #endif |
| 382 | qDebug() << "Done!" ; |
| 383 | } |
| 384 | |
| 385 | void tst_QContactManagerFiltering::cleanupTestCase() |
| 386 | { |
| 387 | // first, remove any contacts that we've added to any managers. |
| 388 | foreach (QContactManager* manager, managers) { |
| 389 | QList<QContactId> contactIds = contactsAddedToManagers.values(akey: manager); |
| 390 | manager->removeContacts(contactIds, errorMap: 0); |
| 391 | } |
| 392 | contactsAddedToManagers.clear(); |
| 393 | |
| 394 | // finally, we can delete all of our manager instances |
| 395 | qDeleteAll(c: managers); |
| 396 | managers.clear(); |
| 397 | defAndFieldNamesForTypePerManager.clear(); |
| 398 | |
| 399 | // And restore old contacts |
| 400 | managerDataHolder.reset(other: 0); |
| 401 | |
| 402 | #ifdef INCLUDE_TESTACTIONS |
| 403 | // clean up any actions/services. |
| 404 | QServiceManager sm; |
| 405 | QStringList allServices = sm.findServices(); |
| 406 | foreach(const QString& serv, allServices) { |
| 407 | if (serv.startsWith("tst_qcontactmanagerfiltering:" )) { |
| 408 | if (!sm.removeService(serv)) { |
| 409 | qDebug() << " tst_qca: ctor: cleaning up test service" << serv << "failed:" << sm.error(); |
| 410 | } |
| 411 | } |
| 412 | } |
| 413 | #endif |
| 414 | } |
| 415 | |
| 416 | QString tst_QContactManagerFiltering::convertIds(QList<QContactId> allIds, QList<QContactId> ids, QChar minimumContact, QChar maximumContact) |
| 417 | { |
| 418 | QString ret; |
| 419 | /* Expected is of the form "abcd".. it's possible that there are some extra contacts */ |
| 420 | for (int i = 0; i < ids.size(); i++) { |
| 421 | if (allIds.indexOf(t: ids.at(i)) >= 0) { |
| 422 | QChar curr = ('a' + allIds.indexOf(t: ids.at(i))); |
| 423 | if (curr >= minimumContact && curr <= maximumContact) { |
| 424 | ret += curr; |
| 425 | } |
| 426 | } |
| 427 | } |
| 428 | |
| 429 | return ret; |
| 430 | } |
| 431 | |
| 432 | QTestData& tst_QContactManagerFiltering::newMRow(const char *tag, QContactManager *cm) |
| 433 | { |
| 434 | // allocate a tag |
| 435 | QString foo = QString("%1[%2]" ).arg(a: tag).arg(a: cm->objectName()); |
| 436 | return QTest::newRow(dataTag: foo.toLatin1().constData()); |
| 437 | } |
| 438 | |
| 439 | |
| 440 | void tst_QContactManagerFiltering::detailStringFiltering_data() |
| 441 | { |
| 442 | QTest::addColumn<QContactManager *>(name: "cm" ); |
| 443 | QTest::addColumn<QContactDetail::DetailType>(name: "detailType" ); |
| 444 | QTest::addColumn<int>(name: "detailField" ); |
| 445 | QTest::addColumn<QVariant>(name: "value" ); |
| 446 | QTest::addColumn<int>(name: "matchflags" ); |
| 447 | QTest::addColumn<QString>(name: "expected" ); |
| 448 | |
| 449 | QVariant ev; // empty variant |
| 450 | QString es; // empty string |
| 451 | |
| 452 | QContactDetail::DetailType name = QContactName::Type; |
| 453 | int firstname = QContactName::FieldFirstName; |
| 454 | int lastname = QContactName::FieldLastName; |
| 455 | int middlename = QContactName::FieldMiddleName; |
| 456 | int prefixname = QContactName::FieldPrefix; |
| 457 | int suffixname = QContactName::FieldSuffix; |
| 458 | QContactDetail::DetailType nickname = QContactNickname::Type; |
| 459 | int nicknameField = QContactNickname::FieldNickname; |
| 460 | QContactDetail::DetailType emailaddr = QContactEmailAddress::Type; |
| 461 | int emailfield = QContactEmailAddress::FieldEmailAddress; |
| 462 | QContactDetail::DetailType phonenumber = QContactPhoneNumber::Type; |
| 463 | int number = QContactPhoneNumber::FieldNumber; |
| 464 | |
| 465 | for (int i = 0; i < managers.size(); i++) { |
| 466 | QContactManager *manager = managers.at(i); |
| 467 | newMRow(tag: "Name == Aaro" , cm: manager) << manager << name << firstname << QVariant("Aaro" ) << 0 << es; |
| 468 | newMRow(tag: "Name == Aaron" , cm: manager) << manager << name << firstname << QVariant("Aaron" ) << 0 << "a" ; |
| 469 | newMRow(tag: "Name == aaron" , cm: manager) << manager << name << firstname << QVariant("aaron" ) << 0 << "a" ; |
| 470 | newMRow(tag: "Name == Aaron, case sensitive" , cm: manager) << manager << name << firstname << QVariant("Aaron" ) << (int)(QContactFilter::MatchCaseSensitive) << "a" ; |
| 471 | newMRow(tag: "Name == aaron, case sensitive" , cm: manager) << manager << name << firstname << QVariant("aaron" ) << (int)(QContactFilter::MatchCaseSensitive) << es; |
| 472 | |
| 473 | newMRow(tag: "Name == A, begins" , cm: manager) << manager << name << firstname << QVariant("A" ) << (int)(QContactFilter::MatchStartsWith) << "a" ; |
| 474 | newMRow(tag: "Name == Aaron, begins" , cm: manager) << manager << name << firstname << QVariant("Aaron" ) << (int)(QContactFilter::MatchStartsWith) << "a" ; |
| 475 | newMRow(tag: "Name == aaron, begins" , cm: manager) << manager << name << firstname << QVariant("aaron" ) << (int)(QContactFilter::MatchStartsWith) << "a" ; |
| 476 | newMRow(tag: "Name == Aaron, begins, case sensitive" , cm: manager) << manager << name << firstname << QVariant("Aaron" ) << (int)(QContactFilter::MatchStartsWith | QContactFilter::MatchCaseSensitive) << "a" ; |
| 477 | newMRow(tag: "Name == aaron, begins, case sensitive" , cm: manager) << manager << name << firstname << QVariant("aaron" ) << (int)(QContactFilter::MatchStartsWith | QContactFilter::MatchCaseSensitive) << es; |
| 478 | newMRow(tag: "Name == Aaron1, begins" , cm: manager) << manager << name << firstname << QVariant("Aaron1" ) << (int)(QContactFilter::MatchStartsWith) << es; |
| 479 | newMRow(tag: "Last name == A, begins" , cm: manager) << manager << name << lastname << QVariant("A" ) << (int)(QContactFilter::MatchStartsWith) << "abc" ; |
| 480 | newMRow(tag: "Last name == Aaronson, begins" , cm: manager) << manager << name << lastname << QVariant("Aaronson" ) << (int)(QContactFilter::MatchStartsWith) << "a" ; |
| 481 | newMRow(tag: "Last Name == Aaronson1, begins" , cm: manager) << manager << name << lastname << QVariant("Aaronson1" ) << (int)(QContactFilter::MatchStartsWith) << es; |
| 482 | |
| 483 | newMRow(tag: "Name == Aar, begins" , cm: manager) << manager << name << firstname << QVariant("Aar" ) << (int)(QContactFilter::MatchStartsWith) << "a" ; |
| 484 | newMRow(tag: "Name == aar, begins" , cm: manager) << manager << name << firstname << QVariant("aar" ) << (int)(QContactFilter::MatchStartsWith) << "a" ; |
| 485 | newMRow(tag: "Name == Aar, begins, case sensitive" , cm: manager) << manager << name << firstname << QVariant("Aar" ) << (int)(QContactFilter::MatchStartsWith | QContactFilter::MatchCaseSensitive) << "a" ; |
| 486 | newMRow(tag: "Name == aar, begins, case sensitive" , cm: manager) << manager << name << firstname << QVariant("aar" ) << (int)(QContactFilter::MatchStartsWith | QContactFilter::MatchCaseSensitive) << es; |
| 487 | |
| 488 | newMRow(tag: "Name == aro, contains" , cm: manager) << manager << name << firstname << QVariant("aro" ) << (int)(QContactFilter::MatchContains) << "a" ; |
| 489 | newMRow(tag: "Name == ARO, contains" , cm: manager) << manager << name << firstname << QVariant("ARO" ) << (int)(QContactFilter::MatchContains) << "a" ; |
| 490 | newMRow(tag: "Name == aro, contains, case sensitive" , cm: manager) << manager << name << firstname << QVariant("aro" ) << (int)(QContactFilter::MatchContains | QContactFilter::MatchCaseSensitive) << "a" ; |
| 491 | newMRow(tag: "Name == ARO, contains, case sensitive" , cm: manager) << manager << name << firstname << QVariant("ARO" ) << (int)(QContactFilter::MatchContains | QContactFilter::MatchCaseSensitive) << es; |
| 492 | |
| 493 | newMRow(tag: "Name == ron, ends" , cm: manager) << manager << name << firstname << QVariant("ron" ) << (int)(QContactFilter::MatchEndsWith) << "a" ; |
| 494 | newMRow(tag: "Name == ARON, ends" , cm: manager) << manager << name << firstname << QVariant("ARON" ) << (int)(QContactFilter::MatchEndsWith) << "a" ; |
| 495 | newMRow(tag: "Name == aron, ends, case sensitive" , cm: manager) << manager << name << firstname << QVariant("aron" ) << (int)(QContactFilter::MatchEndsWith | QContactFilter::MatchCaseSensitive) << "a" ; |
| 496 | newMRow(tag: "Name == ARON, ends, case sensitive" , cm: manager) << manager << name << firstname << QVariant("ARON" ) << (int)(QContactFilter::MatchEndsWith | QContactFilter::MatchCaseSensitive) << es; |
| 497 | newMRow(tag: "Last name == n, ends" , cm: manager) << manager << name << lastname << QVariant("n" ) << (int)(QContactFilter::MatchEndsWith) << "abc" ; |
| 498 | |
| 499 | newMRow(tag: "Name == Aaron, fixed" , cm: manager) << manager << name << firstname << QVariant("Aaron" ) << (int)(QContactFilter::MatchFixedString) << "a" ; |
| 500 | newMRow(tag: "Name == aaron, fixed" , cm: manager) << manager << name << firstname << QVariant("aaron" ) << (int)(QContactFilter::MatchFixedString) << "a" ; |
| 501 | newMRow(tag: "Name == Aaron, fixed, case sensitive" , cm: manager) << manager << name << firstname << QVariant("Aaron" ) << (int)(QContactFilter::MatchFixedString | QContactFilter::MatchCaseSensitive) << "a" ; |
| 502 | newMRow(tag: "Name == aaron, fixed, case sensitive" , cm: manager) << manager << name << firstname << QVariant("aaron" ) << (int)(QContactFilter::MatchFixedString | QContactFilter::MatchCaseSensitive) << es; |
| 503 | |
| 504 | // middle name |
| 505 | newMRow(tag: "MName == Arne" , cm: manager) << manager << name << middlename << QVariant("Arne" ) << (int)(QContactFilter::MatchContains) << "a" ; |
| 506 | |
| 507 | // prefix |
| 508 | newMRow(tag: "Prefix == Sir" , cm: manager) << manager << name << prefixname << QVariant("Sir" ) << (int)(QContactFilter::MatchContains) << "a" ; |
| 509 | |
| 510 | // suffix |
| 511 | newMRow(tag: "Suffix == Dr." , cm: manager) << manager << name << suffixname << QVariant("Dr." ) << (int)(QContactFilter::MatchContains) << "a" ; |
| 512 | |
| 513 | // nickname |
| 514 | newMRow(tag: "Nickname detail exists" , cm: manager) << manager << nickname << -1 << QVariant() << 0 << "ab" ; |
| 515 | newMRow(tag: "Nickname == Aaron, contains" , cm: manager) << manager << nickname << nicknameField << QVariant("Aaron" ) << (int)(QContactFilter::MatchContains) << "a" ; |
| 516 | |
| 517 | // email |
| 518 | newMRow(tag: "Email == Aaron@Aaronson.com" , cm: manager) << manager << emailaddr << emailfield << QVariant("Aaron@Aaronson.com" ) << 0 << "a" ; |
| 519 | newMRow(tag: "Email == Aaron@Aaronsen.com" , cm: manager) << manager << emailaddr << emailfield << QVariant("Aaron@Aaronsen.com" ) << 0 << es; |
| 520 | |
| 521 | // phone number |
| 522 | newMRow(tag: "Phone number detail exists" , cm: manager) << manager << phonenumber << -1 << QVariant("" ) << 0 << "ab" ; |
| 523 | newMRow(tag: "Phone number = 5551212" , cm: manager) << manager << phonenumber << number << QVariant("5551212" ) << (int) QContactFilter::MatchExactly << "a" ; |
| 524 | newMRow(tag: "Phone number = 34, contains" , cm: manager) << manager << phonenumber << number << QVariant("34" ) << (int) QContactFilter::MatchContains << "b" ; |
| 525 | newMRow(tag: "Phone number = 555, starts with" , cm: manager) << manager << phonenumber << number << QVariant("555" ) << (int) QContactFilter::MatchStartsWith << "ab" ; |
| 526 | newMRow(tag: "Phone number = 1212, ends with" , cm: manager) << manager << phonenumber << number << QVariant("1212" ) << (int) QContactFilter::MatchEndsWith << "a" ; |
| 527 | newMRow(tag: "Phone number = 555-1212, match phone number" , cm: manager) << manager << phonenumber << number << QVariant("555-1212" ) << (int) QContactFilter::MatchPhoneNumber << "a" ; // hyphens will be ignored by the match algorithm |
| 528 | newMRow(tag: "Phone number = 555, keypad collation" , cm: manager) << manager << phonenumber << number << QVariant("555" ) << (int) (QContactFilter::MatchKeypadCollation | QContactFilter::MatchStartsWith) << "ab" ; |
| 529 | |
| 530 | /* Converting other types to strings */ |
| 531 | QPair<QContactDetail::DetailType, int> defAndFieldNames = defAndFieldNamesForTypePerManager.value(akey: manager).value(akey: "Integer" ); |
| 532 | if (validDetailField(pair: defAndFieldNames)) { |
| 533 | QTest::newRow(dataTag: "integer == 20" ) << manager << defAndFieldNames.first << defAndFieldNames.second << QVariant("20" ) << 0 << es; |
| 534 | QTest::newRow(dataTag: "integer == 20, as string" ) << manager << defAndFieldNames.first << defAndFieldNames.second << QVariant("20" ) << (int)(QContactFilter::MatchFixedString) << "b" ; |
| 535 | QTest::newRow(dataTag: "integer == 20, begins with, string" ) << manager << defAndFieldNames.first << defAndFieldNames.second << QVariant("20" ) << (int)(QContactFilter::MatchFixedString | QContactFilter::MatchStartsWith) << "b" ; |
| 536 | QTest::newRow(dataTag: "integer == 2, begins with, string" ) << manager << defAndFieldNames.first << defAndFieldNames.second << QVariant("2" ) << (int)(QContactFilter::MatchFixedString | QContactFilter::MatchStartsWith) << "b" ; |
| 537 | QTest::newRow(dataTag: "integer == 20, ends with, string" ) << manager << defAndFieldNames.first << defAndFieldNames.second << QVariant("20" ) << (int)(QContactFilter::MatchFixedString | QContactFilter::MatchEndsWith) << "bc" ; |
| 538 | QTest::newRow(dataTag: "integer == 0, ends with, string" ) << manager << defAndFieldNames.first << defAndFieldNames.second << QVariant("0" ) << (int)(QContactFilter::MatchFixedString | QContactFilter::MatchEndsWith) << "abc" ; |
| 539 | QTest::newRow(dataTag: "integer == 20, contains, string" ) << manager << defAndFieldNames.first << defAndFieldNames.second << QVariant("20" ) << (int)(QContactFilter::MatchFixedString | QContactFilter::MatchContains) << "bc" ; |
| 540 | QTest::newRow(dataTag: "integer == 0, contains, string" ) << manager << defAndFieldNames.first << defAndFieldNames.second << QVariant("0" ) << (int)(QContactFilter::MatchFixedString | QContactFilter::MatchContains) << "abc" ; |
| 541 | } |
| 542 | |
| 543 | /* Detail filter semantics: empty definition or field */ |
| 544 | newMRow(tag: "Invalid type" , cm: manager) << manager << static_cast<QContactDetail::DetailType>(-1) << -1 << QVariant("A" ) << (int)(QContactFilter::MatchStartsWith) << es; // empty definition name means filter matches nothing |
| 545 | newMRow(tag: "Invalid field" , cm: manager) << manager << name << -1 << QVariant("A" ) << (int)(QContactFilter::MatchStartsWith) << "abcdefghijk" ; // invalid field matches any with a name detail |
| 546 | } |
| 547 | } |
| 548 | |
| 549 | void tst_QContactManagerFiltering::detailStringFiltering() |
| 550 | { |
| 551 | QFETCH(QContactManager*, cm); |
| 552 | QFETCH(QContactDetail::DetailType, detailType); |
| 553 | QFETCH(int, detailField); |
| 554 | QFETCH(QVariant, value); |
| 555 | QFETCH(int, matchflags); |
| 556 | QFETCH(QString, expected); |
| 557 | |
| 558 | QList<QContactId> contacts = contactsAddedToManagers.values(akey: cm); |
| 559 | QList<QContactId> ids; |
| 560 | |
| 561 | QContactDetailFilter df; |
| 562 | df.setDetailType(type: detailType, field: detailField); |
| 563 | df.setValue(value); |
| 564 | df.setMatchFlags(QContactFilter::MatchFlags(matchflags)); |
| 565 | |
| 566 | if (cm->managerName() == "memory" ) { |
| 567 | /* At this point, since we're using memory, assume the filter isn't really supported */ |
| 568 | QVERIFY(cm->isFilterSupported(df) == false); |
| 569 | } |
| 570 | |
| 571 | ids = cm->contactIds(filter: df); |
| 572 | |
| 573 | QString output = convertIds(allIds: contacts, ids, minimumContact: 'a', maximumContact: 'k'); // don't include the convenience filtering contacts |
| 574 | QEXPECT_FAIL("integer == 20" , "Not sure if this should pass or fail" , Continue); |
| 575 | QCOMPARE_UNSORTED(output, expected); |
| 576 | } |
| 577 | |
| 578 | void tst_QContactManagerFiltering::detailPhoneNumberFiltering_data() |
| 579 | { |
| 580 | QTest::addColumn<QContactManager *>(name: "cm" ); |
| 581 | QTest::addColumn<QContactDetail::DetailType>(name: "detailType" ); |
| 582 | QTest::addColumn<int>(name: "detailField" ); |
| 583 | QTest::addColumn<QVariant>(name: "value" ); |
| 584 | QTest::addColumn<int>(name: "matchflags" ); |
| 585 | QTest::addColumn<QString>(name: "expected" ); |
| 586 | |
| 587 | // ITU-T standard keypad collation: |
| 588 | // 2 = abc, 3 = def, 4 = ghi, 5 = jkl, 6 = mno, 7 = pqrs, 8 = tuv, 9 = wxyz, 0 = space |
| 589 | |
| 590 | QContactDetail::DetailType phoneType = QContactPhoneNumber::Type; |
| 591 | int phoneField = QContactPhoneNumber::FieldNumber; |
| 592 | QContactDetail::DetailType nameType = QContactName::Type; |
| 593 | int nameField = QContactName::FieldFirstName; // just test the first name. |
| 594 | |
| 595 | // purely to test phone number filtering. |
| 596 | for (int i = 0; i < managers.size(); i++) { |
| 597 | QContactManager *manager = managers.at(i); |
| 598 | |
| 599 | // first, keypad collation testing (ITU-T / T9 testing) |
| 600 | QTest::newRow(dataTag: "t9 aaron" ) << manager << nameType << nameField << QVariant(QString("22766" )) << (int)(QContactFilter::MatchKeypadCollation) << "a" ; |
| 601 | QTest::newRow(dataTag: "t9 bob" ) << manager << nameType << nameField << QVariant(QString("262" )) << (int)(QContactFilter::MatchKeypadCollation) << "b" ; |
| 602 | QTest::newRow(dataTag: "t9 john" ) << manager << nameType << nameField << QVariant(QString("5646" )) << (int)(QContactFilter::MatchKeypadCollation) << "efg" ; |
| 603 | QTest::newRow(dataTag: "t9 bo" ) << manager << nameType << nameField << QVariant(QString("26" )) << (int)(QContactFilter::MatchKeypadCollation | QContactFilter::MatchStartsWith) << "bc" ; // bob, boris |
| 604 | QTest::newRow(dataTag: "t9 zzzz" ) << manager << nameType << nameField << QVariant(QString("9999" )) << (int)(QContactFilter::MatchKeypadCollation) << "" ; // nobody. |
| 605 | |
| 606 | // now do phone number matching - first, aaron's phone number |
| 607 | QTest::newRow(dataTag: "a phone hyphen" ) << manager << phoneType << phoneField << QVariant(QString("555-1212" )) << (int)(QContactFilter::MatchPhoneNumber) << "a" ; |
| 608 | QTest::newRow(dataTag: "a phone plus" ) << manager << phoneType << phoneField << QVariant(QString("+5551212" )) << (int)(QContactFilter::MatchPhoneNumber) << "a" ; |
| 609 | QTest::newRow(dataTag: "a phone brackets" ) << manager << phoneType << phoneField << QVariant(QString("(555)1212" )) << (int)(QContactFilter::MatchPhoneNumber) << "a" ; |
| 610 | QTest::newRow(dataTag: "a phone nospaces" ) << manager << phoneType << phoneField << QVariant(QString("5551212" )) << (int)(QContactFilter::MatchPhoneNumber) << "a" ; |
| 611 | QTest::newRow(dataTag: "a phone single space" ) << manager << phoneType << phoneField << QVariant(QString("555 1212" )) << (int)(QContactFilter::MatchPhoneNumber) << "a" ; |
| 612 | QTest::newRow(dataTag: "a phone random spaces" ) << manager << phoneType << phoneField << QVariant(QString("55 512 12" )) << (int)(QContactFilter::MatchPhoneNumber) << "a" ; |
| 613 | QTest::newRow(dataTag: "a phone every space" ) << manager << phoneType << phoneField << QVariant(QString("5 5 5 1 2 1 2" )) << (int)(QContactFilter::MatchPhoneNumber) << "a" ; |
| 614 | QTest::newRow(dataTag: "a phone plus hyphen" ) << manager << phoneType << phoneField << QVariant(QString("+555-1212" )) << (int)(QContactFilter::MatchPhoneNumber) << "a" ; |
| 615 | QTest::newRow(dataTag: "a phone plus brackets" ) << manager << phoneType << phoneField << QVariant(QString("+5(55)1212" )) << (int)(QContactFilter::MatchPhoneNumber) << "a" ; |
| 616 | QTest::newRow(dataTag: "a phone plus brackets hyphen" ) << manager << phoneType << phoneField << QVariant(QString("+5(55)1-212" )) << (int)(QContactFilter::MatchPhoneNumber) << "a" ; |
| 617 | QTest::newRow(dataTag: "a phone plus brackets hyphen spaces" ) << manager << phoneType << phoneField << QVariant(QString("+5 (55) 1-212" )) << (int)(QContactFilter::MatchPhoneNumber) << "a" ; |
| 618 | |
| 619 | // XXX TODO: should we test for character to number conversions (eg, dial 1800-PESTCONTROL) etc ? |
| 620 | //QTest::newRow("a phone characters") << manager << phoneType << phoneField << QVariant(QString("jjj1a1a")) << (int)(QContactFilter::MatchPhoneNumber) << "a"; // 5551212 |
| 621 | //QTest::newRow("a phone characters") << manager << phoneType << phoneField << QVariant(QString("jkl1b1a")) << (int)(QContactFilter::MatchPhoneNumber) << "a"; // 5551212 |
| 622 | |
| 623 | // then matches bob's phone number |
| 624 | QTest::newRow(dataTag: "b phone hyphen" ) << manager << phoneType << phoneField << QVariant(QString("555-3456" )) << (int)(QContactFilter::MatchPhoneNumber) << "b" ; |
| 625 | QTest::newRow(dataTag: "b phone plus" ) << manager << phoneType << phoneField << QVariant(QString("+5553456" )) << (int)(QContactFilter::MatchPhoneNumber) << "b" ; |
| 626 | QTest::newRow(dataTag: "b phone brackets" ) << manager << phoneType << phoneField << QVariant(QString("(555)3456" )) << (int)(QContactFilter::MatchPhoneNumber) << "b" ; |
| 627 | QTest::newRow(dataTag: "b phone nospaces" ) << manager << phoneType << phoneField << QVariant(QString("5553456" )) << (int)(QContactFilter::MatchPhoneNumber) << "b" ; |
| 628 | QTest::newRow(dataTag: "b phone single space" ) << manager << phoneType << phoneField << QVariant(QString("555 3456" )) << (int)(QContactFilter::MatchPhoneNumber) << "b" ; |
| 629 | QTest::newRow(dataTag: "b phone random spaces" ) << manager << phoneType << phoneField << QVariant(QString("55 534 56" )) << (int)(QContactFilter::MatchPhoneNumber) << "b" ; |
| 630 | QTest::newRow(dataTag: "b phone every space" ) << manager << phoneType << phoneField << QVariant(QString("5 5 5 3 4 5 6" )) << (int)(QContactFilter::MatchPhoneNumber) << "b" ; |
| 631 | QTest::newRow(dataTag: "b phone plus hyphen" ) << manager << phoneType << phoneField << QVariant(QString("+555-3456" )) << (int)(QContactFilter::MatchPhoneNumber) << "b" ; |
| 632 | QTest::newRow(dataTag: "b phone plus brackets" ) << manager << phoneType << phoneField << QVariant(QString("+5(55)3456" )) << (int)(QContactFilter::MatchPhoneNumber) << "b" ; |
| 633 | QTest::newRow(dataTag: "b phone plus brackets hyphen" ) << manager << phoneType << phoneField << QVariant(QString("+5(55)3-456" )) << (int)(QContactFilter::MatchPhoneNumber) << "b" ; |
| 634 | QTest::newRow(dataTag: "b phone plus brackets hyphen spaces" ) << manager << phoneType << phoneField << QVariant(QString("+5 (55) 3-456" )) << (int)(QContactFilter::MatchPhoneNumber) << "b" ; |
| 635 | |
| 636 | // then match no phone numbers (negative testing) -- 555-9999 matches nobody in our test set. |
| 637 | QTest::newRow(dataTag: "no phone hyphen" ) << manager << phoneType << phoneField << QVariant(QString("555-9999" )) << (int)(QContactFilter::MatchPhoneNumber) << "" ; |
| 638 | QTest::newRow(dataTag: "no phone plus" ) << manager << phoneType << phoneField << QVariant(QString("+5559999" )) << (int)(QContactFilter::MatchPhoneNumber) << "" ; |
| 639 | QTest::newRow(dataTag: "no phone brackets" ) << manager << phoneType << phoneField << QVariant(QString("(555)9999" )) << (int)(QContactFilter::MatchPhoneNumber) << "" ; |
| 640 | QTest::newRow(dataTag: "no phone nospaces" ) << manager << phoneType << phoneField << QVariant(QString("5559999" )) << (int)(QContactFilter::MatchPhoneNumber) << "" ; |
| 641 | QTest::newRow(dataTag: "no phone single space" ) << manager << phoneType << phoneField << QVariant(QString("555 9999" )) << (int)(QContactFilter::MatchPhoneNumber) << "" ; |
| 642 | QTest::newRow(dataTag: "no phone random spaces" ) << manager << phoneType << phoneField << QVariant(QString("55 599 99" )) << (int)(QContactFilter::MatchPhoneNumber) << "" ; |
| 643 | QTest::newRow(dataTag: "no phone every space" ) << manager << phoneType << phoneField << QVariant(QString("5 5 5 9 9 9 9" )) << (int)(QContactFilter::MatchPhoneNumber) << "" ; |
| 644 | QTest::newRow(dataTag: "no phone plus hyphen" ) << manager << phoneType << phoneField << QVariant(QString("+555-9999" )) << (int)(QContactFilter::MatchPhoneNumber) << "" ; |
| 645 | QTest::newRow(dataTag: "no phone plus brackets" ) << manager << phoneType << phoneField << QVariant(QString("+5(55)9999" )) << (int)(QContactFilter::MatchPhoneNumber) << "" ; |
| 646 | QTest::newRow(dataTag: "no phone plus brackets hyphen" ) << manager << phoneType << phoneField << QVariant(QString("+5(55)9-999" )) << (int)(QContactFilter::MatchPhoneNumber) << "" ; |
| 647 | QTest::newRow(dataTag: "no phone plus brackets hyphen spaces" ) << manager << phoneType << phoneField << QVariant(QString("+5 (55) 9-999" )) << (int)(QContactFilter::MatchPhoneNumber) << "" ; |
| 648 | |
| 649 | // then match both aaron and bob via starts with |
| 650 | QTest::newRow(dataTag: "ab phone starts nospace" ) << manager << phoneType << phoneField << QVariant(QString("555" )) << (int)(QContactFilter::MatchPhoneNumber | QContactFilter::MatchStartsWith) << "ab" ; |
| 651 | QTest::newRow(dataTag: "ab phone starts hyphen" ) << manager << phoneType << phoneField << QVariant(QString("555-" )) << (int)(QContactFilter::MatchPhoneNumber | QContactFilter::MatchStartsWith) << "ab" ; |
| 652 | QTest::newRow(dataTag: "ab phone starts space" ) << manager << phoneType << phoneField << QVariant(QString("55 5" )) << (int)(QContactFilter::MatchPhoneNumber | QContactFilter::MatchStartsWith) << "ab" ; |
| 653 | QTest::newRow(dataTag: "ab phone starts brackets" ) << manager << phoneType << phoneField << QVariant(QString("(555)" )) << (int)(QContactFilter::MatchPhoneNumber | QContactFilter::MatchStartsWith) << "ab" ; |
| 654 | QTest::newRow(dataTag: "ab phone starts plus" ) << manager << phoneType << phoneField << QVariant(QString("+555" )) << (int)(QContactFilter::MatchPhoneNumber | QContactFilter::MatchStartsWith) << "ab" ; |
| 655 | QTest::newRow(dataTag: "ab phone starts hyphen space" ) << manager << phoneType << phoneField << QVariant(QString("5 55-" )) << (int)(QContactFilter::MatchPhoneNumber | QContactFilter::MatchStartsWith) << "ab" ; |
| 656 | QTest::newRow(dataTag: "ab phone starts hyphen space brackets" ) << manager << phoneType << phoneField << QVariant(QString("5 (55)-" )) << (int)(QContactFilter::MatchPhoneNumber | QContactFilter::MatchStartsWith) << "ab" ; |
| 657 | QTest::newRow(dataTag: "ab phone starts hyphen space brackets plus" ) << manager << phoneType << phoneField << QVariant(QString("+5 (55)-" )) << (int)(QContactFilter::MatchPhoneNumber | QContactFilter::MatchStartsWith) << "ab" ; |
| 658 | } |
| 659 | } |
| 660 | |
| 661 | void tst_QContactManagerFiltering::detailPhoneNumberFiltering() |
| 662 | { |
| 663 | QFETCH(QContactManager*, cm); |
| 664 | QFETCH(QContactDetail::DetailType, detailType); |
| 665 | QFETCH(int, detailField); |
| 666 | QFETCH(QVariant, value); |
| 667 | QFETCH(int, matchflags); |
| 668 | QFETCH(QString, expected); |
| 669 | |
| 670 | // note: this test is exactly the same as string filtering, but uses different fields and specific matchflags. |
| 671 | |
| 672 | QList<QContactId> contacts = contactsAddedToManagers.values(akey: cm); |
| 673 | QList<QContactId> ids; |
| 674 | |
| 675 | QContactDetailFilter df; |
| 676 | df.setDetailType(type: detailType, field: detailField); |
| 677 | df.setValue(value); |
| 678 | df.setMatchFlags(QContactFilter::MatchFlags(matchflags)); |
| 679 | |
| 680 | if (cm->managerName() == "memory" ) { |
| 681 | /* At this point, since we're using memory, assume the filter isn't really supported */ |
| 682 | QVERIFY(cm->isFilterSupported(df) == false); |
| 683 | } |
| 684 | |
| 685 | ids = cm->contactIds(filter: df); |
| 686 | |
| 687 | QString output = convertIds(allIds: contacts, ids, minimumContact: 'a', maximumContact: 'k'); // don't include the convenience filtering contacts |
| 688 | //QSKIP("TODO: fix default implementation of phone number matching!"); |
| 689 | QCOMPARE_UNSORTED(output, expected); |
| 690 | } |
| 691 | |
| 692 | void tst_QContactManagerFiltering::detailVariantFiltering_data() |
| 693 | { |
| 694 | QTest::addColumn<QContactManager *>(name: "cm" ); |
| 695 | QTest::addColumn<QContactDetail::DetailType>(name: "detailType" ); |
| 696 | QTest::addColumn<int>(name: "detailField" ); |
| 697 | QTest::addColumn<bool>(name: "setValue" ); |
| 698 | QTest::addColumn<QVariant>(name: "value" ); |
| 699 | QTest::addColumn<QString>(name: "expected" ); |
| 700 | |
| 701 | QVariant ev; // empty variant |
| 702 | QString es; // empty string |
| 703 | const int invalidField(666); |
| 704 | |
| 705 | for (int i = 0; i < managers.size(); i++) { |
| 706 | QContactManager *manager = managers.at(i); |
| 707 | |
| 708 | /* Nothings */ |
| 709 | newMRow(tag: "no field" , cm: manager) << manager << static_cast<QContactDetail::DetailType>(-1) << -1 << false << ev << es; |
| 710 | newMRow(tag: "no type" , cm: manager) << manager << static_cast<QContactDetail::DetailType>(-1) << static_cast<int>(QContactName::FieldFirstName) << false << ev << es; |
| 711 | |
| 712 | /* Strings (name) */ |
| 713 | newMRow(tag: "first name presence" , cm: manager) << manager << QContactName::Type << static_cast<int>(QContactName::FieldFirstName) << false << ev << "abcdefghijk" ; |
| 714 | newMRow(tag: "first name == Aaron" , cm: manager) << manager << QContactName::Type << static_cast<int>(QContactName::FieldFirstName) << true << QVariant("Aaron" ) << "a" ; |
| 715 | |
| 716 | /* |
| 717 | * Doubles |
| 718 | * B has double(4.0) |
| 719 | * C has double(4.0) |
| 720 | * D has double(-128.0) |
| 721 | */ |
| 722 | QPair<QContactDetail::DetailType, int> defAndFieldNames = defAndFieldNamesForTypePerManager.value(akey: manager).value(akey: "Double" ); |
| 723 | if (validDetailField(pair: defAndFieldNames)) { |
| 724 | newMRow(tag: "double presence" , cm: manager) << manager << defAndFieldNames.first << -1 << false << ev << "bcd" ; |
| 725 | QTest::newRow(dataTag: "double presence (inc field)" ) << manager << defAndFieldNames.first << defAndFieldNames.second << false << ev << "bcd" ; |
| 726 | QTest::newRow(dataTag: "double presence (wrong field)" ) << manager << defAndFieldNames.first << invalidField << false << ev << es; |
| 727 | QTest::newRow(dataTag: "double value (no match)" ) << manager << defAndFieldNames.first << defAndFieldNames.second << true << QVariant(3.5) << es; |
| 728 | QTest::newRow(dataTag: "double value (wrong type)" ) << manager << defAndFieldNames.first << defAndFieldNames.second << true << QVariant(QDateTime()) << es; |
| 729 | QTest::newRow(dataTag: "double value (wrong field, no match)" ) << manager << defAndFieldNames.first << invalidField << true << QVariant(3.5) << es; |
| 730 | newMRow(tag: "double value" , cm: manager) << manager << defAndFieldNames.first << defAndFieldNames.second << true << QVariant(4.0) << "bc" ; |
| 731 | QTest::newRow(dataTag: "double value (wrong field)" ) << manager << defAndFieldNames.first << invalidField << true << QVariant(4.0) << es; |
| 732 | QTest::newRow(dataTag: "double value 2" ) << manager << defAndFieldNames.first << defAndFieldNames.second << true << QVariant(-128.0) << "d" ; |
| 733 | QTest::newRow(dataTag: "double value 2 (wrong field)" ) << manager << defAndFieldNames.first << invalidField << true << QVariant(-128.0) << es; |
| 734 | } |
| 735 | |
| 736 | /* |
| 737 | * Integers |
| 738 | * A has 10 |
| 739 | * B has 20 |
| 740 | * C has -20 |
| 741 | */ |
| 742 | defAndFieldNames = defAndFieldNamesForTypePerManager.value(akey: manager).value(akey: "Integer" ); |
| 743 | if (validDetailField(pair: defAndFieldNames)) { |
| 744 | newMRow(tag: "integer presence" , cm: manager) << manager << defAndFieldNames.first << -1 << false << ev << "abc" ; |
| 745 | QTest::newRow(dataTag: "integer presence (inc field)" ) << manager << defAndFieldNames.first << defAndFieldNames.second << false << ev << "abc" ; |
| 746 | QTest::newRow(dataTag: "integer presence (wrong field)" ) << manager << defAndFieldNames.first << invalidField << false << ev << es; |
| 747 | QTest::newRow(dataTag: "integer value (no match)" ) << manager << defAndFieldNames.first << defAndFieldNames.second << true << QVariant(50) << es; |
| 748 | QTest::newRow(dataTag: "integer value (wrong type)" ) << manager << defAndFieldNames.first << defAndFieldNames.second << true << QVariant(3.5) << es; |
| 749 | QTest::newRow(dataTag: "integer value (wrong field, no match)" ) << manager << defAndFieldNames.first << invalidField << true << QVariant(50) << es; |
| 750 | newMRow(tag: "integer value" , cm: manager) << manager << defAndFieldNames.first << defAndFieldNames.second << true << QVariant(10) << "a" ; |
| 751 | QTest::newRow(dataTag: "integer value (wrong field)" ) << manager << defAndFieldNames.first << invalidField << true << QVariant(10) << es; |
| 752 | QTest::newRow(dataTag: "integer value 2" ) << manager << defAndFieldNames.first << defAndFieldNames.second << true << QVariant(-20) << "c" ; |
| 753 | QTest::newRow(dataTag: "integer value 2 (wrong field)" ) << manager << defAndFieldNames.first << invalidField << true << QVariant(-20) << es; |
| 754 | } |
| 755 | |
| 756 | /* |
| 757 | * Date times |
| 758 | * A has QDateTime(QDate(2009, 06, 29), QTime(16, 52, 23, 0)) |
| 759 | * C has QDateTime(QDate(2009, 06, 29), QTime(16, 54, 17, 0)) |
| 760 | */ |
| 761 | const QDateTime adt(QDate(2009, 06, 29), QTime(16, 52, 23, 0)); |
| 762 | const QDateTime cdt(QDate(2009, 06, 29), QTime(16, 54, 17, 0)); |
| 763 | |
| 764 | defAndFieldNames = defAndFieldNamesForTypePerManager.value(akey: manager).value(akey: "DateTime" ); |
| 765 | if (validDetailField(pair: defAndFieldNames)) { |
| 766 | newMRow(tag: "datetime presence" , cm: manager) << manager << defAndFieldNames.first << -1 << false << ev << "ac" ; |
| 767 | QTest::newRow(dataTag: "datetime presence (inc field)" ) << manager << defAndFieldNames.first << defAndFieldNames.second << false << ev << "ac" ; |
| 768 | QTest::newRow(dataTag: "datetime presence (wrong field)" ) << manager << defAndFieldNames.first << invalidField << false << ev << es; |
| 769 | QTest::newRow(dataTag: "datetime value (no match)" ) << manager << defAndFieldNames.first << defAndFieldNames.second << true << QVariant(QDateTime(QDate(2100,5,13), QTime(5,5,5))) << es; |
| 770 | QTest::newRow(dataTag: "datetime value (wrong type)" ) << manager << defAndFieldNames.first << defAndFieldNames.second << true << QVariant(3.5) << es; |
| 771 | QTest::newRow(dataTag: "datetime value (wrong field, no match)" ) << manager << defAndFieldNames.first << invalidField << true << QVariant(QDateTime(QDate(2100,5,13), QTime(5,5,5))) << es; |
| 772 | newMRow(tag: "datetime value" , cm: manager) << manager << defAndFieldNames.first << defAndFieldNames.second << true << QVariant(adt) << "a" ; |
| 773 | QTest::newRow(dataTag: "datetime value (wrong field)" ) << manager << defAndFieldNames.first << invalidField << true << QVariant(adt) << es; |
| 774 | QTest::newRow(dataTag: "datetime value 2" ) << manager << defAndFieldNames.first << defAndFieldNames.second << true << QVariant(cdt)<< "c" ; |
| 775 | QTest::newRow(dataTag: "datetime value 2 (wrong field)" ) << manager << defAndFieldNames.first << invalidField << true << QVariant(cdt) << es; |
| 776 | } |
| 777 | |
| 778 | /* |
| 779 | * Dates |
| 780 | * A has QDate(1988, 1, 26) |
| 781 | * B has QDate(2492, 5, 5) |
| 782 | * D has QDate(2770, 10, 1) |
| 783 | */ |
| 784 | const QDate ad(1988, 1, 26); |
| 785 | const QDate bd(2492, 5, 5); |
| 786 | const QDate dd(2770, 10, 1); |
| 787 | |
| 788 | defAndFieldNames = defAndFieldNamesForTypePerManager.value(akey: manager).value(akey: "Date" ); |
| 789 | if (validDetailField(pair: defAndFieldNames)) { |
| 790 | newMRow(tag: "date presence" , cm: manager) << manager << defAndFieldNames.first << -1 << false << ev << "abd" ; |
| 791 | QTest::newRow(dataTag: "date presence (inc field)" ) << manager << defAndFieldNames.first << defAndFieldNames.second << false << ev << "abd" ; |
| 792 | QTest::newRow(dataTag: "date presence (wrong field)" ) << manager << defAndFieldNames.first << invalidField << false << ev << es; |
| 793 | QTest::newRow(dataTag: "date value (no match)" ) << manager << defAndFieldNames.first <<defAndFieldNames.second << true << QVariant(QDate(2100,5,13)) << es; |
| 794 | QTest::newRow(dataTag: "date value (wrong type)" ) << manager << defAndFieldNames.first << defAndFieldNames.second << true << QVariant(3.5) << es; |
| 795 | QTest::newRow(dataTag: "date value (wrong field, no match)" ) << manager << defAndFieldNames.first << invalidField << true << QVariant(QDate(2100,5,13)) << es; |
| 796 | newMRow(tag: "date value" , cm: manager) << manager << defAndFieldNames.first << defAndFieldNames.second << true << QVariant(ad) << "a" ; |
| 797 | QTest::newRow(dataTag: "date value (wrong field)" ) << manager << defAndFieldNames.first << invalidField << true << QVariant(ad) << es; |
| 798 | QTest::newRow(dataTag: "date value 2 (wrong field)" ) << manager << defAndFieldNames.first << invalidField << true << QVariant(bd) << es; |
| 799 | QTest::newRow(dataTag: "date value 3 (wrong field)" ) << manager << defAndFieldNames.first << invalidField << true << QVariant(dd) << es; |
| 800 | QTest::newRow(dataTag: "date value 2" ) << manager << defAndFieldNames.first << defAndFieldNames.second << true << QVariant(bd)<< "b" ; |
| 801 | QTest::newRow(dataTag: "date value 3" ) << manager << defAndFieldNames.first << defAndFieldNames.second << true << QVariant(dd)<< "d" ; |
| 802 | } |
| 803 | |
| 804 | /* |
| 805 | * Times |
| 806 | * A has QTime(16,52,23,0) |
| 807 | * B has QTime(15,52,23,0) |
| 808 | */ |
| 809 | const QTime at = QTime(16,52,23,0); |
| 810 | const QTime bt = QTime(15,52,23,0); |
| 811 | |
| 812 | defAndFieldNames = defAndFieldNamesForTypePerManager.value(akey: manager).value(akey: "Time" ); |
| 813 | if (validDetailField(pair: defAndFieldNames)) { |
| 814 | newMRow(tag: "time presence" , cm: manager) << manager << defAndFieldNames.first << -1 << false << ev << "ab" ; |
| 815 | QTest::newRow(dataTag: "time presence (inc field)" ) << manager << defAndFieldNames.first << defAndFieldNames.second << false << ev << "ab" ; |
| 816 | QTest::newRow(dataTag: "time presence (wrong field)" ) << manager << defAndFieldNames.first << invalidField << false << ev << es; |
| 817 | QTest::newRow(dataTag: "time value (no match)" ) << manager << defAndFieldNames.first << defAndFieldNames.second << true << QVariant(QTime(5,5,5)) << es; |
| 818 | QTest::newRow(dataTag: "time value (wrong type)" ) << manager << defAndFieldNames.first << defAndFieldNames.second << true << QVariant(3.5) << es; |
| 819 | QTest::newRow(dataTag: "time value (wrong field, no match)" ) << manager << defAndFieldNames.first << invalidField << true << QVariant(QTime(5,5,5)) << es; |
| 820 | newMRow(tag: "time value" , cm: manager) << manager << defAndFieldNames.first << defAndFieldNames.second << true << QVariant(at) << "a" ; |
| 821 | QTest::newRow(dataTag: "time value (wrong field)" ) << manager << defAndFieldNames.first << invalidField << true << QVariant(at) << es; |
| 822 | QTest::newRow(dataTag: "time value 2" ) << manager << defAndFieldNames.first << defAndFieldNames.second << true << QVariant(bt)<< "b" ; |
| 823 | QTest::newRow(dataTag: "time value 2 (wrong field)" ) << manager << defAndFieldNames.first << invalidField << true << QVariant(bt) << es; |
| 824 | } |
| 825 | |
| 826 | |
| 827 | /* |
| 828 | * Bool |
| 829 | * A has bool(true) |
| 830 | * B has bool(false) |
| 831 | * C has bool(false) |
| 832 | */ |
| 833 | defAndFieldNames = defAndFieldNamesForTypePerManager.value(akey: manager).value(akey: "Bool" ); |
| 834 | if (validDetailField(pair: defAndFieldNames)) { |
| 835 | newMRow(tag: "bool presence" , cm: manager) << manager << defAndFieldNames.first << -1 << false << ev << "abc" ; |
| 836 | QTest::newRow(dataTag: "bool presence (inc field)" ) << manager << defAndFieldNames.first << defAndFieldNames.second << false << ev << "abc" ; |
| 837 | QTest::newRow(dataTag: "bool presence (wrong field)" ) << manager << defAndFieldNames.first << invalidField << false << ev << es; |
| 838 | QTest::newRow(dataTag: "bool value (wrong type)" ) << manager << defAndFieldNames.first << defAndFieldNames.second << true << QVariant(4.0) << es; |
| 839 | newMRow(tag: "bool value" , cm: manager) << manager << defAndFieldNames.first << defAndFieldNames.second << true << QVariant(true) << "a" ; |
| 840 | QTest::newRow(dataTag: "bool value (wrong field)" ) << manager << defAndFieldNames.first << invalidField << true << QVariant(true) << es; |
| 841 | QTest::newRow(dataTag: "bool value 2" ) << manager << defAndFieldNames.first << defAndFieldNames.second << true << QVariant(false) << "bc" ; |
| 842 | QTest::newRow(dataTag: "bool value 2 (wrong field)" ) << manager << defAndFieldNames.first << invalidField << true << QVariant(false) << es; |
| 843 | } |
| 844 | |
| 845 | /* |
| 846 | * LongLong |
| 847 | * C has LongLong(8000000000LL) |
| 848 | * D has LongLong(-14000000000LL) |
| 849 | */ |
| 850 | defAndFieldNames = defAndFieldNamesForTypePerManager.value(akey: manager).value(akey: "LongLong" ); |
| 851 | if (validDetailField(pair: defAndFieldNames)) { |
| 852 | newMRow(tag: "longlong presence" , cm: manager) << manager << defAndFieldNames.first << -1 << false << ev << "cd" ; |
| 853 | QTest::newRow(dataTag: "longlong presence (inc field)" ) << manager << defAndFieldNames.first << defAndFieldNames.second << false << ev << "cd" ; |
| 854 | QTest::newRow(dataTag: "longlong presence (wrong field)" ) << manager << defAndFieldNames.first << invalidField << false << ev << es; |
| 855 | QTest::newRow(dataTag: "longlong value (no match)" ) << manager << defAndFieldNames.first << defAndFieldNames.second << true << QVariant(50000000000LL) << es; |
| 856 | QTest::newRow(dataTag: "longlong value (wrong type)" ) << manager << defAndFieldNames.first << defAndFieldNames.second << true << QVariant(3.5) << es; |
| 857 | QTest::newRow(dataTag: "longlong value (wrong field, no match)" ) << manager << defAndFieldNames.first<< invalidField << true << QVariant(50000000000LL) << es; |
| 858 | newMRow(tag: "longlong value" , cm: manager) << manager << defAndFieldNames.first << defAndFieldNames.second << true << QVariant(8000000000LL) << "c" ; |
| 859 | QTest::newRow(dataTag: "longlong value (wrong field)" ) << manager << defAndFieldNames.first << invalidField << true << QVariant(8000000000LL) << es; |
| 860 | QTest::newRow(dataTag: "longlong value 2" ) << manager << defAndFieldNames.first << defAndFieldNames.second << true << QVariant(-14000000000LL) << "d" ; |
| 861 | QTest::newRow(dataTag: "longlong value 2 (wrong field)" ) << manager << defAndFieldNames.first << invalidField << true << QVariant(-14000000000LL) << es; |
| 862 | } |
| 863 | |
| 864 | /* |
| 865 | * ULongLong |
| 866 | * A has ULongLong(120000000000ULL) |
| 867 | * B has ULongLong(80000000000ULL) |
| 868 | * C has ULongLong(80000000000ULL) |
| 869 | */ |
| 870 | defAndFieldNames = defAndFieldNamesForTypePerManager.value(akey: manager).value(akey: "ULongLong" ); |
| 871 | if (validDetailField(pair: defAndFieldNames)) { |
| 872 | newMRow(tag: "ulonglong presence" , cm: manager) << manager << defAndFieldNames.first << -1 << false << ev << "abc" ; |
| 873 | QTest::newRow(dataTag: "ulonglong presence (inc field)" ) << manager << defAndFieldNames.first << defAndFieldNames.second << false << ev << "abc" ; |
| 874 | QTest::newRow(dataTag: "ulonglong presence (wrong field)" ) << manager << defAndFieldNames.first << invalidField << false << ev << es; |
| 875 | QTest::newRow(dataTag: "ulonglong value (no match)" ) << manager << defAndFieldNames.first << defAndFieldNames.second << true << QVariant(50000000000ULL) << es; |
| 876 | QTest::newRow(dataTag: "ulonglong value (wrong type)" ) << manager << defAndFieldNames.first << defAndFieldNames.second << true << QVariant(3.5) << es; |
| 877 | QTest::newRow(dataTag: "ulonglong value (wrong field, no match)" ) << manager << defAndFieldNames.first << invalidField << true << QVariant(50000000000ULL) << es; |
| 878 | newMRow(tag: "ulonglong value" , cm: manager) << manager << defAndFieldNames.first << defAndFieldNames.second << true << QVariant(120000000000ULL) << "a" ; |
| 879 | QTest::newRow(dataTag: "ulonglong value (wrong field)" ) << manager << defAndFieldNames.first << invalidField << true << QVariant(120000000000ULL) << es; |
| 880 | QTest::newRow(dataTag: "ulonglong value 2" ) << manager << defAndFieldNames.first << defAndFieldNames.second << true << QVariant(80000000000ULL) << "bc" ; |
| 881 | QTest::newRow(dataTag: "ulonglong value 2 (wrong field)" ) << manager << defAndFieldNames.first << invalidField << true << QVariant(80000000000ULL) << es; |
| 882 | } |
| 883 | |
| 884 | /* |
| 885 | * UInt |
| 886 | * B has UInt(4000000000u) |
| 887 | * D has UInt(3000000000u) |
| 888 | */ |
| 889 | defAndFieldNames = defAndFieldNamesForTypePerManager.value(akey: manager).value(akey: "UInt" ); |
| 890 | if (validDetailField(pair: defAndFieldNames)) { |
| 891 | newMRow(tag: "unsigned integer presence" , cm: manager) << manager << defAndFieldNames.first << -1 << false << ev << "bd" ; |
| 892 | QTest::newRow(dataTag: "unsigned integer presence (inc field)" ) << manager << defAndFieldNames.first << defAndFieldNames.second << false << ev << "bd" ; |
| 893 | QTest::newRow(dataTag: "unsigned integer presence (wrong field)" ) << manager << defAndFieldNames.first << invalidField << false << ev << es; |
| 894 | QTest::newRow(dataTag: "unsigned integer value (no match)" ) << manager << defAndFieldNames.first << defAndFieldNames.second << true << QVariant(3500000000u) << es; |
| 895 | QTest::newRow(dataTag: "unsigned integer value (wrong type)" ) << manager << defAndFieldNames.first << defAndFieldNames.second << true << QVariant(3.5) << es; |
| 896 | QTest::newRow(dataTag: "unsigned integer value (wrong field, no match)" ) << manager << defAndFieldNames.first << invalidField << true << QVariant(3500000000u) << es; |
| 897 | newMRow(tag: "unsigned integer value" , cm: manager) << manager << defAndFieldNames.first << defAndFieldNames.second << true << QVariant(4000000000u) << "b" ; |
| 898 | QTest::newRow(dataTag: "unsigned integer value (wrong field)" ) << manager << defAndFieldNames.first << invalidField << true << QVariant(4000000000u) << es; |
| 899 | QTest::newRow(dataTag: "unsigned integer value 2" ) << manager << defAndFieldNames.first << defAndFieldNames.second << true << QVariant(3000000000u) << "d" ; |
| 900 | QTest::newRow(dataTag: "unsigned integer value 2 (wrong field)" ) << manager << defAndFieldNames.first << invalidField << true << QVariant(3000000000u) << es; |
| 901 | } |
| 902 | |
| 903 | /* |
| 904 | * Char |
| 905 | * B has QChar('b') |
| 906 | * C has QChar('c') |
| 907 | */ |
| 908 | const QChar bchar('b'); |
| 909 | const QChar cchar('c'); |
| 910 | defAndFieldNames = defAndFieldNamesForTypePerManager.value(akey: manager).value(akey: "Char" ); |
| 911 | if (validDetailField(pair: defAndFieldNames)) { |
| 912 | newMRow(tag: "char presence" , cm: manager) << manager << defAndFieldNames.first << -1 << false << ev << "bc" ; |
| 913 | QTest::newRow(dataTag: "char presence (inc field)" ) << manager << defAndFieldNames.first << defAndFieldNames.second << false << ev << "bc" ; |
| 914 | QTest::newRow(dataTag: "char presence (wrong field)" ) << manager << defAndFieldNames.first << invalidField << false << ev << es; |
| 915 | QTest::newRow(dataTag: "char value (no match)" ) << manager << defAndFieldNames.first << defAndFieldNames.second << true << QVariant(QChar('a')) << es; |
| 916 | QTest::newRow(dataTag: "char value (wrong type)" ) << manager << defAndFieldNames.first << defAndFieldNames.second << true << QVariant(3.5) << es; |
| 917 | QTest::newRow(dataTag: "char value (wrong field, no match)" ) << manager << defAndFieldNames.first << invalidField << true << QVariant(QChar('a')) << es; |
| 918 | newMRow(tag: "char value" , cm: manager) << manager << defAndFieldNames.first << defAndFieldNames.second << true << QVariant(bchar) << "b" ; |
| 919 | QTest::newRow(dataTag: "char value (wrong field)" ) << manager << defAndFieldNames.first << invalidField << true << QVariant(bchar) << es; |
| 920 | QTest::newRow(dataTag: "char value 2" ) << manager << defAndFieldNames.first << defAndFieldNames.second << true << QVariant(cchar)<< "c" ; |
| 921 | QTest::newRow(dataTag: "char value 2 (wrong field)" ) << manager << defAndFieldNames.first << invalidField << true << QVariant(cchar) << es; |
| 922 | } |
| 923 | } |
| 924 | } |
| 925 | |
| 926 | void tst_QContactManagerFiltering::detailVariantFiltering() |
| 927 | { |
| 928 | QFETCH(QContactManager*, cm); |
| 929 | QFETCH(QContactDetail::DetailType, detailType); |
| 930 | QFETCH(int, detailField); |
| 931 | QFETCH(bool, setValue); |
| 932 | QFETCH(QVariant, value); |
| 933 | QFETCH(QString, expected); |
| 934 | |
| 935 | QList<QContactId> contacts = contactsAddedToManagers.values(akey: cm); |
| 936 | QList<QContactId> ids; |
| 937 | |
| 938 | QContactDetailFilter df; |
| 939 | df.setDetailType(type: detailType, field: detailField); |
| 940 | if (setValue) |
| 941 | df.setValue(value); |
| 942 | |
| 943 | if (cm->managerName() == "memory" ) { |
| 944 | /* At this point, since we're using memory, assume the filter isn't really supported */ |
| 945 | QVERIFY(cm->isFilterSupported(df) == false); |
| 946 | } |
| 947 | |
| 948 | ids = cm->contactIds(filter: df); |
| 949 | |
| 950 | QString output = convertIds(allIds: contacts, ids, minimumContact: 'a', maximumContact: 'k'); // don't include the convenience filtering contacts |
| 951 | QCOMPARE_UNSORTED(output, expected); |
| 952 | } |
| 953 | |
| 954 | void tst_QContactManagerFiltering::rangeFiltering_data() |
| 955 | { |
| 956 | QTest::addColumn<QContactManager *>(name: "cm" ); |
| 957 | QTest::addColumn<QContactDetail::DetailType>(name: "detailType" ); |
| 958 | QTest::addColumn<int>(name: "detailField" ); |
| 959 | QTest::addColumn<QVariant>(name: "minrange" ); |
| 960 | QTest::addColumn<QVariant>(name: "maxrange" ); |
| 961 | QTest::addColumn<bool>(name: "setrfs" ); |
| 962 | QTest::addColumn<int>(name: "rangeflagsi" ); |
| 963 | QTest::addColumn<bool>(name: "setmfs" ); |
| 964 | QTest::addColumn<int>(name: "matchflagsi" ); |
| 965 | QTest::addColumn<QString>(name: "expected" ); |
| 966 | |
| 967 | QVariant ev; // empty variant |
| 968 | QString es; // empty string |
| 969 | const int invalidField(666); |
| 970 | |
| 971 | QContactDetail::DetailType nameType = QContactName::Type; |
| 972 | int firstname = QContactName::FieldFirstName; |
| 973 | |
| 974 | QContactDetail::DetailType phoneType = QContactPhoneNumber::Type; |
| 975 | int phonenum = QContactPhoneNumber::FieldNumber; |
| 976 | |
| 977 | int csflag = (int)QContactFilter::MatchCaseSensitive; |
| 978 | |
| 979 | for (int i = 0; i < managers.size(); i++) { |
| 980 | QContactManager *manager = managers.at(i); |
| 981 | |
| 982 | /* First, cover the "empty detailType / detailField / ranges" cases */ |
| 983 | newMRow(tag: "invalid detailType" , cm: manager) << manager << QContactDetail::TypeUndefined << firstname << QVariant("A" ) << QVariant("Bob" ) << false << 0 << true << 0 << es; |
| 984 | newMRow(tag: "defn presence test" , cm: manager) << manager << nameType << -1 << QVariant("A" ) << QVariant("Bob" ) << false << 0 << true << 0 << "abcdefghijk" ; |
| 985 | newMRow(tag: "field presence test" , cm: manager) << manager << phoneType << phonenum << QVariant() << QVariant() << false << 0 << true << 0 << "ab" ; |
| 986 | newMRow(tag: "good type, bad field" , cm: manager) << manager << nameType << invalidField << QVariant("A" ) << QVariant("Bob" ) << false << 0 << true << 0 << es; |
| 987 | newMRow(tag: "bad def" , cm: manager) << manager << static_cast<QContactDetail::DetailType>(-1) << -1 << QVariant("A" ) << QVariant("Bob" ) << false << 0 << true << 0 << es; |
| 988 | |
| 989 | /* Presence for fields that aren't there */ |
| 990 | newMRow(tag: "defn presence test negative" , cm: manager) << manager << QContactFamily::Type << -1 << ev << ev << false << 0 << false << 0 << es; |
| 991 | newMRow(tag: "field presence test negative" , cm: manager) << manager << QContactFamily::Type << invalidField << ev << ev << false << 0 << false << 0 << es; |
| 992 | newMRow(tag: "defn yes, field no presence test negative" , cm: manager) << manager << nameType << invalidField << ev << ev << false << 0 << false << 0 << es; |
| 993 | |
| 994 | newMRow(tag: "no max, all results" , cm: manager) << manager << nameType << firstname << QVariant("a" ) << QVariant() << false << 0 << true << 0 << "abcdefghijk" ; |
| 995 | newMRow(tag: "no max, some results" , cm: manager) << manager << nameType << firstname << QVariant("bob" ) << QVariant() << false << 0 << true << 0 << "bcdefghijk" ; |
| 996 | newMRow(tag: "no max, no results" , cm: manager) << manager << nameType << firstname << QVariant("ZamBeZI" ) << QVariant() << false << 0 << true << 0 << es; |
| 997 | newMRow(tag: "no min, all results" , cm: manager) << manager << nameType << firstname << QVariant() << QVariant("zambezi" ) << false << 0 << true << 0 << "abcdefghijk" ; |
| 998 | newMRow(tag: "no min, some results" , cm: manager) << manager << nameType << firstname << QVariant() << QVariant("bOb" ) << false << 0 << true << 0 << "a" ; |
| 999 | newMRow(tag: "no min, no results" , cm: manager) << manager << nameType << firstname << QVariant() << QVariant("aardvark" ) << false << 0 << true << 0 << es; |
| 1000 | |
| 1001 | /* now case sensitive */ |
| 1002 | newMRow(tag: "no max, cs, all results" , cm: manager) << manager << nameType << firstname << QVariant("A" ) << QVariant() << false << 0 << true << csflag << "abcdefghijk" ; |
| 1003 | newMRow(tag: "no max, cs, some results" , cm: manager) << manager << nameType << firstname << QVariant("Bob" ) << QVariant() << false << 0 << true << csflag << "bcdefghijk" ; |
| 1004 | newMRow(tag: "no max, cs, no results" , cm: manager) << manager << nameType << firstname << QVariant("Xambezi" ) << QVariant() << false << 0 << true << csflag << "hijk" ; |
| 1005 | newMRow(tag: "no min, cs, most results" , cm: manager) << manager << nameType << firstname << QVariant() << QVariant("Xambezi" ) << false << 0 << true << csflag << "abcdefg" ; |
| 1006 | newMRow(tag: "no min, cs, some results" , cm: manager) << manager << nameType << firstname << QVariant() << QVariant("Bob" ) << false << 0 << true << csflag << "a" ; |
| 1007 | newMRow(tag: "no min, cs, no results" , cm: manager) << manager << nameType << firstname << QVariant() << QVariant("Aardvark" ) << false << 0 << true << csflag << es; |
| 1008 | newMRow(tag: "no max, cs, badcase, all results" , cm: manager) << manager << nameType << firstname << QVariant("A" ) << QVariant() << false << 0 << true << csflag << "abcdefghijk" ; |
| 1009 | newMRow(tag: "no max, cs, badcase, some results" , cm: manager) << manager << nameType << firstname << QVariant("bob" ) << QVariant() << false << 0 << true << csflag << expectedSorting(m: manager, ufs: "hj" , lfs: "abcdefghijk" , iufs: "defghijk" , ilfs: "bcdefghijk" , fpiufs: "cdefghijk" , fpilfs: "bcdefghijk" ); |
| 1010 | newMRow(tag: "no max, cs, badcase, no results" , cm: manager) << manager << nameType << firstname << QVariant("XAMBEZI" ) << QVariant() << false << 0 << true << csflag << "hijk" ; |
| 1011 | newMRow(tag: "no min, cs, badcase, all results" , cm: manager) << manager << nameType << firstname << QVariant() << QVariant("XAMBEZI" ) << false << 0 << true << csflag << "abcdefg" ; |
| 1012 | newMRow(tag: "no min, cs, badcase, some results" , cm: manager) << manager << nameType << firstname << QVariant() << QVariant("BOB" ) << false << 0 << true << csflag << expectedSorting(m: manager, ufs: "a" , lfs: "abchj" , iufs: "a" , ilfs: "abc" , fpiufs: "a" , fpilfs: "ab" ); |
| 1013 | newMRow(tag: "no min, cs, badcase, no results" , cm: manager) << manager << nameType << firstname << QVariant() << QVariant("AARDVARK" ) << false << 0 << true << csflag << es; |
| 1014 | |
| 1015 | /* 'a' has phone number ("5551212") */ |
| 1016 | QTest::newRow(dataTag: "range1" ) << manager << phoneType << phonenum << QVariant("5551200" ) << QVariant("5551220" ) << false << 0 << false << 0 << "a" ; |
| 1017 | |
| 1018 | /* A(Aaron Aaronson), B(Bob Aaronsen), C(Boris Aaronsun), D(Dennis FitzMacyntire) */ |
| 1019 | // string range matching - no matchflags set. |
| 1020 | QTest::newRow(dataTag: "string range - no matchflags - 1" ) << manager << nameType << firstname << QVariant("A" ) << QVariant("Bob" ) << false << 0 << true << 0 << "a" ; |
| 1021 | QTest::newRow(dataTag: "string range - no matchflags - 2" ) << manager << nameType << firstname << QVariant("A" ) << QVariant("Bob" ) << true << (int)(QContactDetailRangeFilter::IncludeLower | QContactDetailRangeFilter::ExcludeUpper) << true << 0 << "a" ; |
| 1022 | QTest::newRow(dataTag: "string range - no matchflags - 3" ) << manager << nameType << firstname << QVariant("A" ) << QVariant("Bob" ) << true << (int)(QContactDetailRangeFilter::ExcludeLower | QContactDetailRangeFilter::ExcludeUpper) << true << 0 << "a" ; |
| 1023 | QTest::newRow(dataTag: "string range - no matchflags - 4" ) << manager << nameType << firstname << QVariant("A" ) << QVariant("Bob" ) << true << (int)(QContactDetailRangeFilter::IncludeLower | QContactDetailRangeFilter::IncludeUpper) << true << 0 << "ab" ; |
| 1024 | QTest::newRow(dataTag: "string range - no matchflags - 5" ) << manager << nameType << firstname << QVariant("A" ) << QVariant("Bob" ) << true << (int)(QContactDetailRangeFilter::ExcludeLower | QContactDetailRangeFilter::IncludeUpper) << true << 0 << "ab" ; |
| 1025 | QTest::newRow(dataTag: "string range - no matchflags - 6" ) << manager << nameType << firstname << QVariant("Bob" ) << QVariant("Boris" ) << true << (int)(QContactDetailRangeFilter::ExcludeLower | QContactDetailRangeFilter::IncludeUpper) << true << 0 << "c" ; |
| 1026 | QTest::newRow(dataTag: "string range - no matchflags - 7" ) << manager << nameType << firstname << QVariant("Bob" ) << QVariant("Boris" ) << true << (int)(QContactDetailRangeFilter::IncludeLower | QContactDetailRangeFilter::ExcludeUpper) << true << 0 << "b" ; |
| 1027 | QTest::newRow(dataTag: "string range - no matchflags - 8" ) << manager << nameType << firstname << QVariant("Bob" ) << QVariant("Boris" ) << true << (int)(QContactDetailRangeFilter::IncludeLower | QContactDetailRangeFilter::IncludeUpper) << true << 0 << "bc" ; |
| 1028 | QTest::newRow(dataTag: "string range - no matchflags - 9" ) << manager << nameType << firstname << QVariant("Bob" ) << QVariant("Boris" ) << true << (int)(QContactDetailRangeFilter::ExcludeLower | QContactDetailRangeFilter::ExcludeUpper) << true << 0 << "" ; |
| 1029 | QTest::newRow(dataTag: "string range - no matchflags - 10" ) << manager << nameType << firstname << QVariant("Barry" ) << QVariant("C" ) << true << (int)(QContactDetailRangeFilter::ExcludeLower | QContactDetailRangeFilter::ExcludeUpper) << true << 0 << "bc" ; |
| 1030 | |
| 1031 | // string range matching - QContactFilter::MatchStartsWith should produce the same results as without matchflags set. |
| 1032 | QTest::newRow(dataTag: "string range - startswith - 1" ) << manager << nameType << firstname << QVariant("A" ) << QVariant("Bo" ) << true << (int)(QContactDetailRangeFilter::IncludeLower | QContactDetailRangeFilter::ExcludeUpper) << true << (int)(QContactFilter::MatchStartsWith) << "a" ; |
| 1033 | QTest::newRow(dataTag: "string range - startswith - 2" ) << manager << nameType << firstname << QVariant("A" ) << QVariant("Bo" ) << true << (int)(QContactDetailRangeFilter::ExcludeLower | QContactDetailRangeFilter::ExcludeUpper) << true << (int)(QContactFilter::MatchStartsWith) << "a" ; |
| 1034 | QTest::newRow(dataTag: "string range - startswith - 3" ) << manager << nameType << firstname << QVariant("A" ) << QVariant("Bo" ) << true << (int)(QContactDetailRangeFilter::IncludeLower | QContactDetailRangeFilter::IncludeUpper) << true << (int)(QContactFilter::MatchStartsWith) << "ab" ; |
| 1035 | QTest::newRow(dataTag: "string range - startswith - 4" ) << manager << nameType << firstname << QVariant("A" ) << QVariant("Bo" ) << true << (int)(QContactDetailRangeFilter::ExcludeLower | QContactDetailRangeFilter::IncludeUpper) << true << (int)(QContactFilter::MatchStartsWith) << "ab" ; |
| 1036 | QTest::newRow(dataTag: "string range - startswith - 5" ) << manager << nameType << firstname << QVariant("Bo" ) << QVariant("C" ) << true << (int)(QContactDetailRangeFilter::ExcludeLower | QContactDetailRangeFilter::IncludeUpper) << true << (int)(QContactFilter::MatchStartsWith) << "c" ; |
| 1037 | QTest::newRow(dataTag: "string range - startswith - 6" ) << manager << nameType << firstname << QVariant("Bo" ) << QVariant("C" ) << true << (int)(QContactDetailRangeFilter::IncludeLower | QContactDetailRangeFilter::ExcludeUpper) << true << (int)(QContactFilter::MatchStartsWith) << "bc" ; |
| 1038 | QTest::newRow(dataTag: "string range - startswith - 7" ) << manager << nameType << firstname << QVariant("Bo" ) << QVariant("C" ) << true << (int)(QContactDetailRangeFilter::IncludeLower | QContactDetailRangeFilter::IncludeUpper) << true << (int)(QContactFilter::MatchStartsWith) << "bc" ; |
| 1039 | QTest::newRow(dataTag: "string range - startswith - 8" ) << manager << nameType << firstname << QVariant("Bo" ) << QVariant("C" ) << true << (int)(QContactDetailRangeFilter::ExcludeLower | QContactDetailRangeFilter::ExcludeUpper) << true << (int)(QContactFilter::MatchStartsWith) << "c" ; |
| 1040 | QTest::newRow(dataTag: "string range - startswith - 9" ) << manager << nameType << firstname << QVariant("Barry" ) << QVariant("C" ) << true << (int)(QContactDetailRangeFilter::ExcludeLower | QContactDetailRangeFilter::ExcludeUpper) << true << (int)(QContactFilter::MatchStartsWith) << "bc" ; |
| 1041 | |
| 1042 | // Open ended starts with |
| 1043 | QTest::newRow(dataTag: "string range - startswith open top - 1" ) << manager << nameType << firstname << QVariant("A" ) << ev << true << (int)(QContactDetailRangeFilter::IncludeLower) << true << (int)(QContactFilter::MatchStartsWith) << "abcdefghijk" ; |
| 1044 | QTest::newRow(dataTag: "string range - startswith open top - 2" ) << manager << nameType << firstname << QVariant("A" ) << ev << true << (int)(QContactDetailRangeFilter::ExcludeLower) << true << (int)(QContactFilter::MatchStartsWith) << "abcdefghijk" ; |
| 1045 | QTest::newRow(dataTag: "string range - startswith open top - 3" ) << manager << nameType << firstname << QVariant("Aaron" ) << ev << true << (int)(QContactDetailRangeFilter::IncludeLower) << true << (int)(QContactFilter::MatchStartsWith) << "abcdefghijk" ; |
| 1046 | QTest::newRow(dataTag: "string range - startswith open top - 4" ) << manager << nameType << firstname << QVariant("Aaron" ) << ev << true << (int)(QContactDetailRangeFilter::ExcludeLower) << true << (int)(QContactFilter::MatchStartsWith) << "bcdefghijk" ; |
| 1047 | QTest::newRow(dataTag: "string range - startswith open bottom - 1" ) << manager << nameType << firstname << ev << QVariant("Borit" ) << true << (int)(QContactDetailRangeFilter::IncludeUpper) << true << (int)(QContactFilter::MatchStartsWith) << "abc" ; |
| 1048 | QTest::newRow(dataTag: "string range - startswith open bottom - 2" ) << manager << nameType << firstname << ev << QVariant("Borit" ) << true << (int)(QContactDetailRangeFilter::ExcludeUpper) << true << (int)(QContactFilter::MatchStartsWith) << "abc" ; |
| 1049 | QTest::newRow(dataTag: "string range - startswith open bottom - 3" ) << manager << nameType << firstname << ev << QVariant("Boris" ) << true << (int)(QContactDetailRangeFilter::IncludeUpper) << true << (int)(QContactFilter::MatchStartsWith) << "abc" ; |
| 1050 | QTest::newRow(dataTag: "string range - startswith open bottom - 4" ) << manager << nameType << firstname << ev << QVariant("Boris" ) << true << (int)(QContactDetailRangeFilter::ExcludeUpper) << true << (int)(QContactFilter::MatchStartsWith) << "ab" ; |
| 1051 | |
| 1052 | /* A(10), B(20), C(-20) */ |
| 1053 | // Now integer range testing |
| 1054 | QPair<QContactDetail::DetailType, int> defAndFieldNames = defAndFieldNamesForTypePerManager.value(akey: manager).value(akey: "Integer" ); |
| 1055 | if (validDetailField(pair: defAndFieldNames)) { |
| 1056 | QTest::newRow(dataTag: "int range - no rangeflags - 1" ) << manager << defAndFieldNames.first << defAndFieldNames.second << QVariant(9) << QVariant(9) << false << 0 << false << 0 << es; |
| 1057 | QTest::newRow(dataTag: "int range - no rangeflags - 2" ) << manager << defAndFieldNames.first << defAndFieldNames.second << QVariant(9) << QVariant(10) << false << 0 << false << 0 << es; |
| 1058 | QTest::newRow(dataTag: "int range - no rangeflags - 3" ) << manager << defAndFieldNames.first << defAndFieldNames.second << QVariant(9) << QVariant(11) << false << 0 << false << 0 << "a" ; |
| 1059 | QTest::newRow(dataTag: "int range - no rangeflags - 4" ) << manager << defAndFieldNames.first << defAndFieldNames.second << QVariant(10) << QVariant(10) << false << 0 << false << 0 << es; |
| 1060 | QTest::newRow(dataTag: "int range - rangeflags - 1" ) << manager << defAndFieldNames.first << defAndFieldNames.second << QVariant(10) << QVariant(10) << true << (int)(QContactDetailRangeFilter::ExcludeLower | QContactDetailRangeFilter::ExcludeUpper) << false << 0 << es; |
| 1061 | QTest::newRow(dataTag: "int range - rangeflags - 2" ) << manager << defAndFieldNames.first << defAndFieldNames.second << QVariant(10) << QVariant(10) << true << (int)(QContactDetailRangeFilter::IncludeLower | QContactDetailRangeFilter::ExcludeUpper) << false << 0 << es; |
| 1062 | QTest::newRow(dataTag: "int range - rangeflags - 3" ) << manager << defAndFieldNames.first << defAndFieldNames.second << QVariant(10) << QVariant(10) << true << (int)(QContactDetailRangeFilter::ExcludeLower | QContactDetailRangeFilter::IncludeUpper) << false << 0 << es; |
| 1063 | QTest::newRow(dataTag: "int range - rangeflags - 4" ) << manager << defAndFieldNames.first << defAndFieldNames.second << QVariant(10) << QVariant(10) << true << (int)(QContactDetailRangeFilter::IncludeLower | QContactDetailRangeFilter::IncludeUpper) << false << 0 << "a" ; |
| 1064 | QTest::newRow(dataTag: "int range - rangeflags - 5" ) << manager << defAndFieldNames.first << defAndFieldNames.second << QVariant(10) << QVariant(11) << true << (int)(QContactDetailRangeFilter::IncludeLower | QContactDetailRangeFilter::IncludeUpper) << false << 0 << "a" ; |
| 1065 | QTest::newRow(dataTag: "int range - rangeflags - 6" ) << manager << defAndFieldNames.first << defAndFieldNames.second << QVariant(11) << QVariant(11) << true << (int)(QContactDetailRangeFilter::IncludeLower | QContactDetailRangeFilter::IncludeUpper) << false << 0 << es; |
| 1066 | QTest::newRow(dataTag: "int range - rangeflags - 7" ) << manager << defAndFieldNames.first << defAndFieldNames.second << QVariant(-30) << QVariant(-19) << true << (int)(QContactDetailRangeFilter::IncludeLower | QContactDetailRangeFilter::IncludeUpper) << false << 0 << "c" ; |
| 1067 | QTest::newRow(dataTag: "int range - rangeflags - 8" ) << manager << defAndFieldNames.first << defAndFieldNames.second << QVariant(-20) << QVariant(-30) << true << (int)(QContactDetailRangeFilter::IncludeLower | QContactDetailRangeFilter::IncludeUpper) << false << 0 << es; |
| 1068 | QTest::newRow(dataTag: "int range - rangeflags - variant - 1" ) << manager << defAndFieldNames.first << defAndFieldNames.second << QVariant(9) << QVariant() << true << (int)(QContactDetailRangeFilter::IncludeLower | QContactDetailRangeFilter::IncludeUpper) << false << 0 << "ab" ; |
| 1069 | QTest::newRow(dataTag: "int range - rangeflags - variant - 2" ) << manager << defAndFieldNames.first << defAndFieldNames.second << QVariant() << QVariant(11) << true << (int)(QContactDetailRangeFilter::IncludeLower | QContactDetailRangeFilter::IncludeUpper) << false << 0 << "ac" ; |
| 1070 | } |
| 1071 | } |
| 1072 | } |
| 1073 | |
| 1074 | void tst_QContactManagerFiltering::rangeFiltering() |
| 1075 | { |
| 1076 | QFETCH(QContactManager*, cm); |
| 1077 | QFETCH(QContactDetail::DetailType, detailType); |
| 1078 | QFETCH(int, detailField); |
| 1079 | QFETCH(QVariant, minrange); |
| 1080 | QFETCH(QVariant, maxrange); |
| 1081 | QFETCH(bool, setrfs); |
| 1082 | QFETCH(int, rangeflagsi); |
| 1083 | QFETCH(bool, setmfs); |
| 1084 | QFETCH(int, matchflagsi); |
| 1085 | QFETCH(QString, expected); |
| 1086 | |
| 1087 | QContactDetailRangeFilter::RangeFlags rangeflags = (QContactDetailRangeFilter::RangeFlags)rangeflagsi; |
| 1088 | QContactFilter::MatchFlags matchflags = (QContactFilter::MatchFlags) matchflagsi; |
| 1089 | |
| 1090 | QList<QContactId> contacts = contactsAddedToManagers.values(akey: cm); |
| 1091 | QList<QContactId> ids; |
| 1092 | |
| 1093 | /* Build the range filter */ |
| 1094 | QContactDetailRangeFilter drf; |
| 1095 | drf.setDetailType(type: detailType, field: detailField); |
| 1096 | if (setrfs) |
| 1097 | drf.setRange(min: minrange, max: maxrange, flags: rangeflags); |
| 1098 | else |
| 1099 | drf.setRange(min: minrange, max: maxrange); |
| 1100 | if (setmfs) |
| 1101 | drf.setMatchFlags(matchflags); |
| 1102 | |
| 1103 | if (cm->managerName() == "memory" ) { |
| 1104 | /* At this point, since we're using memory, assume the filter isn't really supported */ |
| 1105 | QVERIFY(cm->isFilterSupported(drf) == false); |
| 1106 | } |
| 1107 | ids = cm->contactIds(filter: drf); |
| 1108 | |
| 1109 | QString output = convertIds(allIds: contacts, ids, minimumContact: 'a', maximumContact: 'k'); // don't include the convenience filtering contacts |
| 1110 | QEXPECT_FAIL("string range - startswith - 3" , "No handling for startsWith exists in QContactDetailRangeFilter implementation" , Continue); |
| 1111 | QEXPECT_FAIL("string range - startswith - 4" , "No handling for startsWith exists in QContactDetailRangeFilter implementation" , Continue); |
| 1112 | QEXPECT_FAIL("string range - startswith - 5" , "No handling for startsWith exists in QContactDetailRangeFilter implementation" , Continue); |
| 1113 | QEXPECT_FAIL("string range - startswith - 8" , "No handling for startsWith exists in QContactDetailRangeFilter implementation" , Continue); |
| 1114 | QCOMPARE_UNSORTED(output, expected); |
| 1115 | } |
| 1116 | |
| 1117 | void tst_QContactManagerFiltering::intersectionFiltering_data() |
| 1118 | { |
| 1119 | QTest::addColumn<QContactManager *>(name: "cm" ); |
| 1120 | QTest::addColumn<bool>(name: "firstfilter" ); |
| 1121 | QTest::addColumn<int>(name: "fftype" ); // 1 = detail, 2 = detailrange, 3 = groupmembership, 4 = union, 5 = intersection |
| 1122 | QTest::addColumn<QContactDetail::DetailType>(name: "ffdetailtype" ); |
| 1123 | QTest::addColumn<int>(name: "ffdetailfield" ); |
| 1124 | QTest::addColumn<bool>(name: "ffsetvalue" ); |
| 1125 | QTest::addColumn<QVariant>(name: "ffvalue" ); |
| 1126 | QTest::addColumn<QVariant>(name: "ffminrange" ); |
| 1127 | QTest::addColumn<QVariant>(name: "ffmaxrange" ); |
| 1128 | QTest::addColumn<bool>(name: "secondfilter" ); |
| 1129 | QTest::addColumn<int>(name: "sftype" ); |
| 1130 | QTest::addColumn<QContactDetail::DetailType>(name: "sfdetailtype" ); |
| 1131 | QTest::addColumn<int>(name: "sfdetailfield" ); |
| 1132 | QTest::addColumn<bool>(name: "sfsetvalue" ); |
| 1133 | QTest::addColumn<QVariant>(name: "sfvalue" ); |
| 1134 | QTest::addColumn<QVariant>(name: "sfminrange" ); |
| 1135 | QTest::addColumn<QVariant>(name: "sfmaxrange" ); |
| 1136 | QTest::addColumn<QString>(name: "order" ); |
| 1137 | QTest::addColumn<QString>(name: "expected" ); |
| 1138 | |
| 1139 | QString es; // empty string. |
| 1140 | |
| 1141 | for (int i = 0; i < managers.size(); i++) { |
| 1142 | QContactManager *manager = managers.at(i); |
| 1143 | |
| 1144 | // for the following tests, terminology: |
| 1145 | // X will be an (empty) intersection filter created in the test |
| 1146 | // Y will be the first filter defined here |
| 1147 | // Z will be the second filter defined here |
| 1148 | |
| 1149 | // WITH Y AND Z AS DETAIL FILTERS (with no overlap between Y and Z results) |
| 1150 | // For these tests, Y matches "bc" and Z matches "a" |
| 1151 | // X && Y - X empty so es |
| 1152 | QPair<QContactDetail::DetailType, int> integerDefAndFieldNames = defAndFieldNamesForTypePerManager.value(akey: manager).value(akey: "Integer" ); |
| 1153 | QPair<QContactDetail::DetailType, int> booleanDefAndFieldNames = defAndFieldNamesForTypePerManager.value(akey: manager).value(akey: "Bool" ); |
| 1154 | if (validDetailField(pair: integerDefAndFieldNames) && validDetailField(pair: booleanDefAndFieldNames)) { |
| 1155 | QTest::newRow(dataTag: "A1" ) << manager |
| 1156 | << true << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1157 | << false << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(10) << QVariant() << QVariant() |
| 1158 | << "XY" << es; |
| 1159 | // Y && X - X empty so es |
| 1160 | QTest::newRow(dataTag: "A2" ) << manager |
| 1161 | << true << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1162 | << false << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(10) << QVariant() << QVariant() |
| 1163 | << "YX" << es; |
| 1164 | // Y && Z - matches "a" and "bc" - so intersected = es |
| 1165 | QTest::newRow(dataTag: "A3" ) << manager |
| 1166 | << true << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1167 | << true << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << true << QVariant(10) << QVariant() << QVariant() |
| 1168 | << "YZ" << es; |
| 1169 | // Z && Y - matches "bc" and "a" - so intersected = es |
| 1170 | QTest::newRow(dataTag: "A4" ) << manager |
| 1171 | << true << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1172 | << true << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << true << QVariant(10) << QVariant() << QVariant() |
| 1173 | << "ZY" << es; |
| 1174 | // X && Z - X empty so es |
| 1175 | QTest::newRow(dataTag: "A5" ) << manager |
| 1176 | << false << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1177 | << true << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << true << QVariant(10) << QVariant() << QVariant() |
| 1178 | << "XZ" << es; |
| 1179 | // Z && X - X empty so es |
| 1180 | QTest::newRow(dataTag: "A6" ) << manager |
| 1181 | << false << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1182 | << true << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << true << QVariant(10) << QVariant() << QVariant() |
| 1183 | << "ZX" << es; |
| 1184 | // X && Y && Z - X empty so es |
| 1185 | QTest::newRow(dataTag: "A7" ) << manager |
| 1186 | << true << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1187 | << true << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << true << QVariant(10) << QVariant() << QVariant() |
| 1188 | << "XYZ" << es; |
| 1189 | // X && Z && Y - X empty so es |
| 1190 | QTest::newRow(dataTag: "A8" ) << manager |
| 1191 | << true << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1192 | << true << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << true << QVariant(10) << QVariant() << QVariant() |
| 1193 | << "XZY" << es; |
| 1194 | // Y && X && Z - X empty so es |
| 1195 | QTest::newRow(dataTag: "A9" ) << manager |
| 1196 | << true << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1197 | << true << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << true << QVariant(10) << QVariant() << QVariant() |
| 1198 | << "YXZ" << es; |
| 1199 | // Z && X && Y - X empty so es |
| 1200 | QTest::newRow(dataTag: "A10" ) << manager |
| 1201 | << true << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1202 | << true << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << true << QVariant(10) << QVariant() << QVariant() |
| 1203 | << "ZXY" << es; |
| 1204 | // Y && Z && X - X empty so es |
| 1205 | QTest::newRow(dataTag: "A11" ) << manager |
| 1206 | << true << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1207 | << true << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << true << QVariant(10) << QVariant() << QVariant() |
| 1208 | << "YZX" << es; |
| 1209 | // Z && Y && X - X empty so es |
| 1210 | QTest::newRow(dataTag: "A12" ) << manager |
| 1211 | << true << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1212 | << true << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << true << QVariant(10) << QVariant() << QVariant() |
| 1213 | << "ZYX" << es; |
| 1214 | |
| 1215 | // WITH Y AND Z AS DETAIL FILTERS (with some overlap between Y and Z results) |
| 1216 | // For these tests, Y matches "bc", Z matches "b" |
| 1217 | // X && Y - X empty so es |
| 1218 | QTest::newRow(dataTag: "B1" ) << manager |
| 1219 | << true << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1220 | << false << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(20) << QVariant() << QVariant() |
| 1221 | << "XY" << es; |
| 1222 | // Y && X - X empty so es |
| 1223 | QTest::newRow(dataTag: "B2" ) << manager |
| 1224 | << true << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1225 | << false << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(20) << QVariant() << QVariant() |
| 1226 | << "YX" << es; |
| 1227 | // Y && Z - matches "b" and "bc" - so intersected = "b" |
| 1228 | QTest::newRow(dataTag: "B3" ) << manager |
| 1229 | << true << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1230 | << true << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << true << QVariant(20) << QVariant() << QVariant() |
| 1231 | << "YZ" << "b" ; |
| 1232 | // Z && Y - matches "bc" and "b" - so intersected = "b" |
| 1233 | QTest::newRow(dataTag: "B4" ) << manager |
| 1234 | << true << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1235 | << true << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << true << QVariant(20) << QVariant() << QVariant() |
| 1236 | << "ZY" << "b" ; |
| 1237 | // X && Z - X empty so es |
| 1238 | QTest::newRow(dataTag: "B5" ) << manager |
| 1239 | << false << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1240 | << true << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << true << QVariant(20) << QVariant() << QVariant() |
| 1241 | << "XZ" << es; |
| 1242 | // Z && X - X empty so es |
| 1243 | QTest::newRow(dataTag: "B6" ) << manager |
| 1244 | << false << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1245 | << true << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << true << QVariant(20) << QVariant() << QVariant() |
| 1246 | << "ZX" << es; |
| 1247 | // X && Y && Z - X empty so es |
| 1248 | QTest::newRow(dataTag: "B7" ) << manager |
| 1249 | << true << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1250 | << true << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << true << QVariant(20) << QVariant() << QVariant() |
| 1251 | << "XYZ" << es; |
| 1252 | // X && Z && Y - X empty so es |
| 1253 | QTest::newRow(dataTag: "B8" ) << manager |
| 1254 | << true << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1255 | << true << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << true << QVariant(20) << QVariant() << QVariant() |
| 1256 | << "XZY" << es; |
| 1257 | // Y && X && Z - X empty so es |
| 1258 | QTest::newRow(dataTag: "B9" ) << manager |
| 1259 | << true << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1260 | << true << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << true << QVariant(20) << QVariant() << QVariant() |
| 1261 | << "YXZ" << es; |
| 1262 | // Z && X && Y - X empty so es |
| 1263 | QTest::newRow(dataTag: "B10" ) << manager |
| 1264 | << true << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1265 | << true << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << true << QVariant(20) << QVariant() << QVariant() |
| 1266 | << "ZXY" << es; |
| 1267 | // Y && Z && X - X empty so es |
| 1268 | QTest::newRow(dataTag: "B11" ) << manager |
| 1269 | << true << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1270 | << true << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << true << QVariant(20) << QVariant() << QVariant() |
| 1271 | << "YZX" << es; |
| 1272 | // Z && Y && X - X empty so es |
| 1273 | QTest::newRow(dataTag: "B12" ) << manager |
| 1274 | << true << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1275 | << true << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << true << QVariant(20) << QVariant() << QVariant() |
| 1276 | << "ZYX" << es; |
| 1277 | } |
| 1278 | |
| 1279 | //--------------------------- |
| 1280 | |
| 1281 | // WITH Y AND Z AS RANGE FILTERS (with no overlap between Y and Z results) |
| 1282 | // For these tests, Y matches "a", Z matches "b" |
| 1283 | // X && Y - X empty so es |
| 1284 | if (validDetailField(pair: integerDefAndFieldNames)) { |
| 1285 | QTest::newRow(dataTag: "C1" ) << manager |
| 1286 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(15) |
| 1287 | << false << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1288 | << "XY" << es; |
| 1289 | // Y && X - X empty so es |
| 1290 | QTest::newRow(dataTag: "C2" ) << manager |
| 1291 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(15) |
| 1292 | << false << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1293 | << "YX" << es; |
| 1294 | // Y && Z - no overlap so es |
| 1295 | QTest::newRow(dataTag: "C3" ) << manager |
| 1296 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(15) |
| 1297 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1298 | << "YZ" << es; |
| 1299 | // Z && Y - no overlap so es |
| 1300 | QTest::newRow(dataTag: "C4" ) << manager |
| 1301 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(15) |
| 1302 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1303 | << "ZY" << es; |
| 1304 | // X && Z - X empty so es |
| 1305 | QTest::newRow(dataTag: "C5" ) << manager |
| 1306 | << false << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(15) |
| 1307 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1308 | << "XZ" << es; |
| 1309 | // Z && X - X empty so es |
| 1310 | QTest::newRow(dataTag: "C6" ) << manager |
| 1311 | << false << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(15) |
| 1312 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1313 | << "ZX" << es; |
| 1314 | // X && Y && Z - X empty so es |
| 1315 | QTest::newRow(dataTag: "C7" ) << manager |
| 1316 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(15) |
| 1317 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1318 | << "XYZ" << es; |
| 1319 | // X && Z && Y - X empty so es |
| 1320 | QTest::newRow(dataTag: "C8" ) << manager |
| 1321 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(15) |
| 1322 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1323 | << "XZY" << es; |
| 1324 | // Y && X && Z - X empty so es |
| 1325 | QTest::newRow(dataTag: "C9" ) << manager |
| 1326 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(15) |
| 1327 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1328 | << "YXZ" << es; |
| 1329 | // Z && X && Y - X empty so es |
| 1330 | QTest::newRow(dataTag: "C10" ) << manager |
| 1331 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(15) |
| 1332 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1333 | << "ZXY" << es; |
| 1334 | // Y && Z && X - X empty so es |
| 1335 | QTest::newRow(dataTag: "C11" ) << manager |
| 1336 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(15) |
| 1337 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1338 | << "YZX" << es; |
| 1339 | // Z && Y && X - X empty so es |
| 1340 | QTest::newRow(dataTag: "C12" ) << manager |
| 1341 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(15) |
| 1342 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1343 | << "ZYX" << es; |
| 1344 | |
| 1345 | // WITH Y AND Z AS RANGE FILTERS (with some overlap between Y and Z results) |
| 1346 | // For these tests, Y matches "ab", Z matches "b" |
| 1347 | // X && Y - X empty so es |
| 1348 | QTest::newRow(dataTag: "D1" ) << manager |
| 1349 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(25) |
| 1350 | << false << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1351 | << "XY" << es; |
| 1352 | // Y && X - X empty so es |
| 1353 | QTest::newRow(dataTag: "D2" ) << manager |
| 1354 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(25) |
| 1355 | << false << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1356 | << "YX" << es; |
| 1357 | // Y && Z - Y matches "ab", Z matches "b", intersection = "b" |
| 1358 | QTest::newRow(dataTag: "D3" ) << manager |
| 1359 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(25) |
| 1360 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1361 | << "YZ" << "b" ; |
| 1362 | // Z && Y - Y matches "ab", Z matches "b", intersection = "b" |
| 1363 | QTest::newRow(dataTag: "D4" ) << manager |
| 1364 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(25) |
| 1365 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1366 | << "ZY" << "b" ; |
| 1367 | // X && Z - X empty so es |
| 1368 | QTest::newRow(dataTag: "D5" ) << manager |
| 1369 | << false << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(25) |
| 1370 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1371 | << "XZ" << es; |
| 1372 | // Z && X - X empty so es |
| 1373 | QTest::newRow(dataTag: "D6" ) << manager |
| 1374 | << false << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(25) |
| 1375 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1376 | << "ZX" << es; |
| 1377 | // X && Y && Z - X empty so es |
| 1378 | QTest::newRow(dataTag: "D7" ) << manager |
| 1379 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(25) |
| 1380 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1381 | << "XYZ" << es; |
| 1382 | // X && Z && Y - X empty so es |
| 1383 | QTest::newRow(dataTag: "D8" ) << manager |
| 1384 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(25) |
| 1385 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1386 | << "XZY" << es; |
| 1387 | // Y && X && Z - X empty so es |
| 1388 | QTest::newRow(dataTag: "D9" ) << manager |
| 1389 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(25) |
| 1390 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1391 | << "YXZ" << es; |
| 1392 | // Z && X && Y - X empty so es |
| 1393 | QTest::newRow(dataTag: "D10" ) << manager |
| 1394 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(25) |
| 1395 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1396 | << "ZXY" << es; |
| 1397 | // Y && Z && X - X empty so es |
| 1398 | QTest::newRow(dataTag: "D11" ) << manager |
| 1399 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(25) |
| 1400 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1401 | << "YZX" << es; |
| 1402 | // Z && Y && X - X empty so es |
| 1403 | QTest::newRow(dataTag: "D12" ) << manager |
| 1404 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(25) |
| 1405 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1406 | << "ZYX" << es; |
| 1407 | } |
| 1408 | } |
| 1409 | } |
| 1410 | |
| 1411 | void tst_QContactManagerFiltering::intersectionFiltering() |
| 1412 | { |
| 1413 | QFETCH(QContactManager*, cm); |
| 1414 | QFETCH(bool, firstfilter); |
| 1415 | QFETCH(int, fftype); // 1 = detail, 2 = detailrange, 3 = groupmembership, 4 = union, 5 = intersection |
| 1416 | QFETCH(QContactDetail::DetailType, ffdetailtype); |
| 1417 | QFETCH(int, ffdetailfield); |
| 1418 | QFETCH(bool, ffsetvalue); |
| 1419 | QFETCH(QVariant, ffvalue); |
| 1420 | QFETCH(QVariant, ffminrange); |
| 1421 | QFETCH(QVariant, ffmaxrange); |
| 1422 | QFETCH(bool, secondfilter); |
| 1423 | QFETCH(int, sftype); |
| 1424 | QFETCH(QContactDetail::DetailType, sfdetailtype); |
| 1425 | QFETCH(int, sfdetailfield); |
| 1426 | QFETCH(bool, sfsetvalue); |
| 1427 | QFETCH(QVariant, sfvalue); |
| 1428 | QFETCH(QVariant, sfminrange); |
| 1429 | QFETCH(QVariant, sfmaxrange); |
| 1430 | QFETCH(QString, order); |
| 1431 | QFETCH(QString, expected); |
| 1432 | |
| 1433 | QContactFilter *x = new QContactIntersectionFilter(); |
| 1434 | QContactFilter *y = 0, *z = 0; |
| 1435 | |
| 1436 | if (firstfilter) { |
| 1437 | switch (fftype) { |
| 1438 | case 1: // detail filter |
| 1439 | y = new QContactDetailFilter(); |
| 1440 | static_cast<QContactDetailFilter*>(y)->setDetailType(type: ffdetailtype, field: ffdetailfield); |
| 1441 | if (ffsetvalue) |
| 1442 | static_cast<QContactDetailFilter*>(y)->setValue(ffvalue); |
| 1443 | break; |
| 1444 | case 2: // range filter |
| 1445 | y = new QContactDetailRangeFilter(); |
| 1446 | static_cast<QContactDetailRangeFilter*>(y)->setDetailType(type: ffdetailtype, field: ffdetailfield); |
| 1447 | static_cast<QContactDetailRangeFilter*>(y)->setRange(min: ffminrange, max: ffmaxrange); |
| 1448 | break; |
| 1449 | case 3: // group membership filter |
| 1450 | case 4: // union filter |
| 1451 | case 5: // intersection filter |
| 1452 | break; |
| 1453 | |
| 1454 | default: |
| 1455 | QVERIFY(false); // force fail. |
| 1456 | break; |
| 1457 | } |
| 1458 | } |
| 1459 | |
| 1460 | if (secondfilter) { |
| 1461 | switch (sftype) { |
| 1462 | case 1: // detail filter |
| 1463 | z = new QContactDetailFilter(); |
| 1464 | static_cast<QContactDetailFilter*>(z)->setDetailType(type: sfdetailtype, field: sfdetailfield); |
| 1465 | if (sfsetvalue) |
| 1466 | static_cast<QContactDetailFilter*>(z)->setValue(sfvalue); |
| 1467 | break; |
| 1468 | case 2: // range filter |
| 1469 | z = new QContactDetailRangeFilter(); |
| 1470 | static_cast<QContactDetailRangeFilter*>(z)->setDetailType(type: sfdetailtype, field: sfdetailfield); |
| 1471 | static_cast<QContactDetailRangeFilter*>(z)->setRange(min: sfminrange, max: sfmaxrange); |
| 1472 | break; |
| 1473 | case 3: // group membership filter |
| 1474 | case 4: // union filter |
| 1475 | case 5: // intersection filter |
| 1476 | break; |
| 1477 | |
| 1478 | default: |
| 1479 | QVERIFY(false); // force fail. |
| 1480 | break; |
| 1481 | } |
| 1482 | } |
| 1483 | |
| 1484 | // control variables - order: starts, ends, mids |
| 1485 | bool sX = false; |
| 1486 | bool sY = false; |
| 1487 | bool sZ = false; |
| 1488 | bool eX = false; |
| 1489 | bool eY = false; |
| 1490 | bool eZ = false; |
| 1491 | bool mX = false; |
| 1492 | bool mY = false; |
| 1493 | bool mZ = false; |
| 1494 | |
| 1495 | if (order.startsWith(s: "X" )) |
| 1496 | sX = true; |
| 1497 | if (order.startsWith(s: "Y" )) |
| 1498 | sY = true; |
| 1499 | if (order.startsWith(s: "Z" )) |
| 1500 | sZ = true; |
| 1501 | if (order.endsWith(s: "X" )) |
| 1502 | eX = true; |
| 1503 | if (order.endsWith(s: "Y" )) |
| 1504 | eY = true; |
| 1505 | if (order.endsWith(s: "Z" )) |
| 1506 | eZ = true; |
| 1507 | if (order.size() > 2) { |
| 1508 | if (order.at(i: 1) == 'X') |
| 1509 | mX = true; |
| 1510 | if (order.at(i: 1) == 'Y') |
| 1511 | mY = true; |
| 1512 | if (order.at(i: 1) == 'Z') |
| 1513 | mZ = true; |
| 1514 | } |
| 1515 | |
| 1516 | // now perform the filtering. |
| 1517 | QContactIntersectionFilter resultFilter; |
| 1518 | if (sX) { |
| 1519 | if (mY && eZ) |
| 1520 | resultFilter = *x & *y & *z; |
| 1521 | else if (mZ && eY) |
| 1522 | resultFilter = *x & *z & *y; |
| 1523 | else if (eY) |
| 1524 | resultFilter = *x & *y; |
| 1525 | else if (eZ) |
| 1526 | resultFilter = *x & *z; |
| 1527 | } else if (sY) { |
| 1528 | if (mX && eZ) |
| 1529 | resultFilter = *y & *x & *z; |
| 1530 | else if (mZ && eX) |
| 1531 | resultFilter = *y & *z & *x; |
| 1532 | else if (eX) |
| 1533 | resultFilter = *y & *x; |
| 1534 | else if (eZ) |
| 1535 | resultFilter = *y & *z; |
| 1536 | } else if (sZ) { |
| 1537 | if (mX && eY) |
| 1538 | resultFilter = *z & *x & *y; |
| 1539 | else if (mY && eX) |
| 1540 | resultFilter = *z & *y & *x; |
| 1541 | else if (eX) |
| 1542 | resultFilter = *z & *x; |
| 1543 | else if (eY) |
| 1544 | resultFilter = *z & *y; |
| 1545 | } |
| 1546 | |
| 1547 | QList<QContactId> contacts = contactsAddedToManagers.values(akey: cm); |
| 1548 | QList<QContactId> ids; |
| 1549 | |
| 1550 | ids = cm->contactIds(filter: resultFilter); |
| 1551 | |
| 1552 | QString output = convertIds(allIds: contacts, ids, minimumContact: 'a', maximumContact: 'k'); // don't include the convenience filtering contacts |
| 1553 | QCOMPARE_UNSORTED(output, expected); |
| 1554 | |
| 1555 | delete x; |
| 1556 | if (y) delete y; |
| 1557 | if (z) delete z; |
| 1558 | } |
| 1559 | |
| 1560 | void tst_QContactManagerFiltering::unionFiltering_data() |
| 1561 | { |
| 1562 | QTest::addColumn<QContactManager *>(name: "cm" ); |
| 1563 | QTest::addColumn<bool>(name: "firstfilter" ); |
| 1564 | QTest::addColumn<int>(name: "fftype" ); // 1 = detail, 2 = detailrange, 3 = groupmembership, 4 = union, 5 = intersection |
| 1565 | QTest::addColumn<QContactDetail::DetailType>(name: "ffdetailtype" ); |
| 1566 | QTest::addColumn<int>(name: "ffdetailfield" ); |
| 1567 | QTest::addColumn<bool>(name: "ffsetvalue" ); |
| 1568 | QTest::addColumn<QVariant>(name: "ffvalue" ); |
| 1569 | QTest::addColumn<QVariant>(name: "ffminrange" ); |
| 1570 | QTest::addColumn<QVariant>(name: "ffmaxrange" ); |
| 1571 | QTest::addColumn<bool>(name: "secondfilter" ); |
| 1572 | QTest::addColumn<int>(name: "sftype" ); |
| 1573 | QTest::addColumn<QContactDetail::DetailType>(name: "sfdetailtype" ); |
| 1574 | QTest::addColumn<int>(name: "sfdetailfield" ); |
| 1575 | QTest::addColumn<bool>(name: "sfsetvalue" ); |
| 1576 | QTest::addColumn<QVariant>(name: "sfvalue" ); |
| 1577 | QTest::addColumn<QVariant>(name: "sfminrange" ); |
| 1578 | QTest::addColumn<QVariant>(name: "sfmaxrange" ); |
| 1579 | QTest::addColumn<QString>(name: "order" ); |
| 1580 | QTest::addColumn<QString>(name: "expected" ); |
| 1581 | |
| 1582 | QString es; // empty string. |
| 1583 | |
| 1584 | for (int i = 0; i < managers.size(); i++) { |
| 1585 | QContactManager *manager = managers.at(i); |
| 1586 | |
| 1587 | // for the following tests, terminology: |
| 1588 | // X will be an (empty) union filter created in the test |
| 1589 | // Y will be the first filter defined here |
| 1590 | // Z will be the second filter defined here |
| 1591 | |
| 1592 | // WITH Y AND Z AS DETAIL FILTERS (with no overlap between Y and Z results) |
| 1593 | // For these tests, Y matches "bc" and Z matches "a" |
| 1594 | // X || Y - X empty, Y matches "bc" so union = "bc" |
| 1595 | QPair<QContactDetail::DetailType, int> integerDefAndFieldNames = defAndFieldNamesForTypePerManager.value(akey: manager).value(akey: "Integer" ); |
| 1596 | QPair<QContactDetail::DetailType, int> booleanDefAndFieldNames = defAndFieldNamesForTypePerManager.value(akey: manager).value(akey: "Bool" ); |
| 1597 | if (validDetailField(pair: integerDefAndFieldNames) && validDetailField(pair: booleanDefAndFieldNames)) { |
| 1598 | QTest::newRow(dataTag: "A1" ) << manager |
| 1599 | << true << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1600 | << false << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(10) << QVariant() << QVariant() |
| 1601 | << "XY" << "bc" ; |
| 1602 | // Y || X - Y matches "bc", X empty so union = "bc" |
| 1603 | QTest::newRow(dataTag: "A2" ) << manager |
| 1604 | << true << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1605 | << false << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(10) << QVariant() << QVariant() |
| 1606 | << "YX" << "bc" ; |
| 1607 | // Y || Z - Y matches "bc" and Z matches "a" - so union = "abc" |
| 1608 | QTest::newRow(dataTag: "A3" ) << manager |
| 1609 | << true << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1610 | << true << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << true << QVariant(10) << QVariant() << QVariant() |
| 1611 | << "YZ" << "abc" ; |
| 1612 | // Z || Y - Y matches "bc" and Z matches "a" - so union = "abc" |
| 1613 | QTest::newRow(dataTag: "A4" ) << manager |
| 1614 | << true << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1615 | << true << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << true << QVariant(10) << QVariant() << QVariant() |
| 1616 | << "ZY" << "abc" ; |
| 1617 | // X || Z - X empty, Z matches "a" so "a" |
| 1618 | QTest::newRow(dataTag: "A5" ) << manager |
| 1619 | << false << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << false << QVariant(false) << QVariant() << QVariant() |
| 1620 | << true << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << true << QVariant(10) << QVariant() << QVariant() |
| 1621 | << "XZ" << "a" ; |
| 1622 | // Z || X - X empty, Z matches "a" so "a" |
| 1623 | QTest::newRow(dataTag: "A6" ) << manager |
| 1624 | << false << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << false << QVariant(false) << QVariant() << QVariant() |
| 1625 | << true << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << true << QVariant(10) << QVariant() << QVariant() |
| 1626 | << "ZX" << "a" ; |
| 1627 | // X || Y || Z - X empty, Y matches "bc", Z matches "a" so "abc" |
| 1628 | QTest::newRow(dataTag: "A7" ) << manager |
| 1629 | << true << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1630 | << true << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << true << QVariant(10) << QVariant() << QVariant() |
| 1631 | << "XYZ" << "abc" ; |
| 1632 | // X || Z || Y - X empty, Y matches "bc", Z matches "a" so "abc" |
| 1633 | QTest::newRow(dataTag: "A8" ) << manager |
| 1634 | << true << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1635 | << true << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << true << QVariant(10) << QVariant() << QVariant() |
| 1636 | << "XZY" << "abc" ; |
| 1637 | // Y || X || Z - X empty, Y matches "bc", Z matches "a" so "abc" |
| 1638 | QTest::newRow(dataTag: "A9" ) << manager |
| 1639 | << true << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1640 | << true << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << true << QVariant(10) << QVariant() << QVariant() |
| 1641 | << "YXZ" << "abc" ; |
| 1642 | // Z || X || Y - X empty, Y matches "bc", Z matches "a" so "abc" |
| 1643 | QTest::newRow(dataTag: "A10" ) << manager |
| 1644 | << true << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1645 | << true << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << true << QVariant(10) << QVariant() << QVariant() |
| 1646 | << "ZXY" << "abc" ; |
| 1647 | // Y || Z || X - X empty, Y matches "bc", Z matches "a" so "abc" |
| 1648 | QTest::newRow(dataTag: "A11" ) << manager |
| 1649 | << true << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1650 | << true << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << true << QVariant(10) << QVariant() << QVariant() |
| 1651 | << "YZX" << "abc" ; |
| 1652 | // Z || Y || X - X empty, Y matches "bc", Z matches "a" so "abc" |
| 1653 | QTest::newRow(dataTag: "A12" ) << manager |
| 1654 | << true << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1655 | << true << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << true << QVariant(10) << QVariant() << QVariant() |
| 1656 | << "ZYX" << "abc" ; |
| 1657 | |
| 1658 | // WITH Y AND Z AS DETAIL FILTERS (with some overlap between Y and Z results) |
| 1659 | // For these tests, Y matches "bc", Z matches "b" |
| 1660 | // X || Y - X empty, Y matches "b", so "bc" |
| 1661 | QTest::newRow(dataTag: "B1" ) << manager |
| 1662 | << true << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1663 | << false << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(20) << QVariant() << QVariant() |
| 1664 | << "XY" << "bc" ; |
| 1665 | // Y || X - X empty, Y matches "bc", so "bc" |
| 1666 | QTest::newRow(dataTag: "B2" ) << manager |
| 1667 | << true << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1668 | << false << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(20) << QVariant() << QVariant() |
| 1669 | << "YX" << "bc" ; |
| 1670 | // Y || Z - X empty, Y matches "bc", Z matches "b" so "bc" |
| 1671 | QTest::newRow(dataTag: "B3" ) << manager |
| 1672 | << true << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1673 | << true << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << true << QVariant(20) << QVariant() << QVariant() |
| 1674 | << "YZ" << "bc" ; |
| 1675 | // Z || Y - X empty, Y matches "bc", Z matches "b" so "bc" |
| 1676 | QTest::newRow(dataTag: "B4" ) << manager |
| 1677 | << true << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1678 | << true << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << true << QVariant(20) << QVariant() << QVariant() |
| 1679 | << "ZY" << "bc" ; |
| 1680 | // X || Z - X empty, Z matches "b" so "b" |
| 1681 | QTest::newRow(dataTag: "B5" ) << manager |
| 1682 | << false << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1683 | << true << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << true << QVariant(20) << QVariant() << QVariant() |
| 1684 | << "XZ" << "b" ; |
| 1685 | // Z || X - X empty, Z matches "b" so "b" |
| 1686 | QTest::newRow(dataTag: "B6" ) << manager |
| 1687 | << false << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1688 | << true << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << true << QVariant(20) << QVariant() << QVariant() |
| 1689 | << "ZX" << "b" ; |
| 1690 | // X || Y || Z - X empty, Y matches "bc", Z matches "b" so "bc" |
| 1691 | QTest::newRow(dataTag: "B7" ) << manager |
| 1692 | << true << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1693 | << true << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << true << QVariant(20) << QVariant() << QVariant() |
| 1694 | << "XYZ" << "bc" ; |
| 1695 | // X || Z || Y - X empty, Y matches "bc", Z matches "b" so "bc" |
| 1696 | QTest::newRow(dataTag: "B8" ) << manager |
| 1697 | << true << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1698 | << true << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << true << QVariant(20) << QVariant() << QVariant() |
| 1699 | << "XZY" << "bc" ; |
| 1700 | // Y || X || Z - X empty, Y matches "bc", Z matches "b" so "bc" |
| 1701 | QTest::newRow(dataTag: "B9" ) << manager |
| 1702 | << true << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1703 | << true << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << true << QVariant(20) << QVariant() << QVariant() |
| 1704 | << "YXZ" << "bc" ; |
| 1705 | // Z || X || Y - X empty, Y matches "bc", Z matches "b" so "bc" |
| 1706 | QTest::newRow(dataTag: "B10" ) << manager |
| 1707 | << true << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1708 | << true << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << true << QVariant(20) << QVariant() << QVariant() |
| 1709 | << "ZXY" << "bc" ; |
| 1710 | // Y || Z || X - X empty, Y matches "bc", Z matches "b" so "bc" |
| 1711 | QTest::newRow(dataTag: "B11" ) << manager |
| 1712 | << true << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1713 | << true << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << true << QVariant(20) << QVariant() << QVariant() |
| 1714 | << "YZX" << "bc" ; |
| 1715 | // Z || Y || X - X empty, Y matches "bc", Z matches "b" so "bc" |
| 1716 | QTest::newRow(dataTag: "B12" ) << manager |
| 1717 | << true << 1 << booleanDefAndFieldNames.first << booleanDefAndFieldNames.second << true << QVariant(false) << QVariant() << QVariant() |
| 1718 | << true << 1 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << true << QVariant(20) << QVariant() << QVariant() |
| 1719 | << "ZYX" << "bc" ; |
| 1720 | } |
| 1721 | |
| 1722 | //--------------------------- |
| 1723 | |
| 1724 | // WITH Y AND Z AS RANGE FILTERS (with no overlap between Y and Z results) |
| 1725 | // For these tests, Y matches "a", Z matches "b" |
| 1726 | // X || Y - X empty, Y matches "a" so "a" |
| 1727 | if (validDetailField(pair: integerDefAndFieldNames)) { |
| 1728 | QTest::newRow(dataTag: "C1" ) << manager |
| 1729 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(15) |
| 1730 | << false << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1731 | << "XY" << "a" ; |
| 1732 | // Y || X - X empty, Y matches "a" so "a" |
| 1733 | QTest::newRow(dataTag: "C2" ) << manager |
| 1734 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(15) |
| 1735 | << false << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1736 | << "YX" << "a" ; |
| 1737 | // Y || Z - Y matches "a", Z matches "b" so "ab" |
| 1738 | QTest::newRow(dataTag: "C3" ) << manager |
| 1739 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(15) |
| 1740 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1741 | << "YZ" << "ab" ; |
| 1742 | // Z || Y - Y matches "a", Z matches "b" so "ab" |
| 1743 | QTest::newRow(dataTag: "C4" ) << manager |
| 1744 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(15) |
| 1745 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1746 | << "ZY" << "ab" ; |
| 1747 | // X || Z - X empty, Z matches "b" so "b" |
| 1748 | QTest::newRow(dataTag: "C5" ) << manager |
| 1749 | << false << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(15) |
| 1750 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1751 | << "XZ" << "b" ; |
| 1752 | // Z || X - X empty, Z matches "b" so "b" |
| 1753 | QTest::newRow(dataTag: "C6" ) << manager |
| 1754 | << false << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(15) |
| 1755 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1756 | << "ZX" << "b" ; |
| 1757 | // X || Y || Z - X empty, Y matches "a", Z matches "b" so "ab" |
| 1758 | QTest::newRow(dataTag: "C7" ) << manager |
| 1759 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(15) |
| 1760 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1761 | << "XYZ" << "ab" ; |
| 1762 | // X || Z || Y - X empty, Y matches "a", Z matches "b" so "ab" |
| 1763 | QTest::newRow(dataTag: "C8" ) << manager |
| 1764 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(15) |
| 1765 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1766 | << "XZY" << "ab" ; |
| 1767 | // Y || X || Z - X empty, Y matches "a", Z matches "b" so "ab" |
| 1768 | QTest::newRow(dataTag: "C9" ) << manager |
| 1769 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(15) |
| 1770 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1771 | << "YXZ" << "ab" ; |
| 1772 | // Z || X || Y - X empty, Y matches "a", Z matches "b" so "ab" |
| 1773 | QTest::newRow(dataTag: "C10" ) << manager |
| 1774 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(15) |
| 1775 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1776 | << "ZXY" << "ab" ; |
| 1777 | // Y || Z || X - X empty, Y matches "a", Z matches "b" so "ab" |
| 1778 | QTest::newRow(dataTag: "C11" ) << manager |
| 1779 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(15) |
| 1780 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1781 | << "YZX" << "ab" ; |
| 1782 | // Z || Y || X - X empty, Y matches "a", Z matches "b" so "ab" |
| 1783 | QTest::newRow(dataTag: "C12" ) << manager |
| 1784 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(15) |
| 1785 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1786 | << "ZYX" << "ab" ; |
| 1787 | |
| 1788 | // WITH Y AND Z AS RANGE FILTERS (with some overlap between Y and Z results) |
| 1789 | // For these tests, Y matches "ab", Z matches "b" |
| 1790 | // X || Y - X empty, Y matches "ab" so "ab" |
| 1791 | QTest::newRow(dataTag: "D1" ) << manager |
| 1792 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(25) |
| 1793 | << false << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1794 | << "XY" << "ab" ; |
| 1795 | // Y || X - X empty, Y matches "ab" so "ab" |
| 1796 | QTest::newRow(dataTag: "D2" ) << manager |
| 1797 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(25) |
| 1798 | << false << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1799 | << "YX" << "ab" ; |
| 1800 | // Y || Z - Y matches "ab", Z matches "b", union = "ab" |
| 1801 | QTest::newRow(dataTag: "D3" ) << manager |
| 1802 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(25) |
| 1803 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1804 | << "YZ" << "ab" ; |
| 1805 | // Z || Y - Y matches "ab", Z matches "b", union = "ab" |
| 1806 | QTest::newRow(dataTag: "D4" ) << manager |
| 1807 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(25) |
| 1808 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1809 | << "ZY" << "ab" ; |
| 1810 | // X || Z - X empty, Z matches "b" so "b" |
| 1811 | QTest::newRow(dataTag: "D5" ) << manager |
| 1812 | << false << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(25) |
| 1813 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1814 | << "XZ" << "b" ; |
| 1815 | // Z || X - X empty, Z matches "b" so "b" |
| 1816 | QTest::newRow(dataTag: "D6" ) << manager |
| 1817 | << false << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(25) |
| 1818 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1819 | << "ZX" << "b" ; |
| 1820 | // X || Y || Z - X empty, Y matches "ab", Z matches "b" so "ab" |
| 1821 | QTest::newRow(dataTag: "D7" ) << manager |
| 1822 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(25) |
| 1823 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1824 | << "XYZ" << "ab" ; |
| 1825 | // X || Z || Y - X empty, Y matches "ab", Z matches "b" so "ab" |
| 1826 | QTest::newRow(dataTag: "D8" ) << manager |
| 1827 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(25) |
| 1828 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1829 | << "XZY" << "ab" ; |
| 1830 | // Y || X || Z - X empty, Y matches "ab", Z matches "b" so "ab" |
| 1831 | QTest::newRow(dataTag: "D9" ) << manager |
| 1832 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(25) |
| 1833 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1834 | << "YXZ" << "ab" ; |
| 1835 | // Z || X || Y - X empty, Y matches "ab", Z matches "b" so "ab" |
| 1836 | QTest::newRow(dataTag: "D10" ) << manager |
| 1837 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(25) |
| 1838 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1839 | << "ZXY" << "ab" ; |
| 1840 | // Y || Z || X - X empty, Y matches "ab", Z matches "b" so "ab" |
| 1841 | QTest::newRow(dataTag: "D11" ) << manager |
| 1842 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(25) |
| 1843 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1844 | << "YZX" << "ab" ; |
| 1845 | // Z || Y || X - X empty, Y matches "ab", Z matches "b" so "ab" |
| 1846 | QTest::newRow(dataTag: "D12" ) << manager |
| 1847 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(5) << QVariant(25) |
| 1848 | << true << 2 << integerDefAndFieldNames.first << integerDefAndFieldNames.second << false << QVariant(0) << QVariant(15) << QVariant(25) |
| 1849 | << "ZYX" << "ab" ; |
| 1850 | } |
| 1851 | } |
| 1852 | } |
| 1853 | |
| 1854 | void tst_QContactManagerFiltering::unionFiltering() |
| 1855 | { |
| 1856 | QFETCH(QContactManager*, cm); |
| 1857 | QFETCH(bool, firstfilter); |
| 1858 | QFETCH(int, fftype); // 1 = detail, 2 = detailrange, 3 = groupmembership, 4 = union, 5 = intersection |
| 1859 | QFETCH(QContactDetail::DetailType, ffdetailtype); |
| 1860 | QFETCH(int, ffdetailfield); |
| 1861 | QFETCH(bool, ffsetvalue); |
| 1862 | QFETCH(QVariant, ffvalue); |
| 1863 | QFETCH(QVariant, ffminrange); |
| 1864 | QFETCH(QVariant, ffmaxrange); |
| 1865 | QFETCH(bool, secondfilter); |
| 1866 | QFETCH(int, sftype); |
| 1867 | QFETCH(QContactDetail::DetailType, sfdetailtype); |
| 1868 | QFETCH(int, sfdetailfield); |
| 1869 | QFETCH(bool, sfsetvalue); |
| 1870 | QFETCH(QVariant, sfvalue); |
| 1871 | QFETCH(QVariant, sfminrange); |
| 1872 | QFETCH(QVariant, sfmaxrange); |
| 1873 | QFETCH(QString, order); |
| 1874 | QFETCH(QString, expected); |
| 1875 | |
| 1876 | QContactFilter *x = new QContactUnionFilter(); |
| 1877 | QContactFilter *y = 0, *z = 0; |
| 1878 | |
| 1879 | if (firstfilter) { |
| 1880 | switch (fftype) { |
| 1881 | case 1: // detail filter |
| 1882 | y = new QContactDetailFilter(); |
| 1883 | static_cast<QContactDetailFilter*>(y)->setDetailType(type: ffdetailtype, field: ffdetailfield); |
| 1884 | if (ffsetvalue) |
| 1885 | static_cast<QContactDetailFilter*>(y)->setValue(ffvalue); |
| 1886 | break; |
| 1887 | case 2: // range filter |
| 1888 | y = new QContactDetailRangeFilter(); |
| 1889 | static_cast<QContactDetailRangeFilter*>(y)->setDetailType(type: ffdetailtype, field: ffdetailfield); |
| 1890 | static_cast<QContactDetailRangeFilter*>(y)->setRange(min: ffminrange, max: ffmaxrange); |
| 1891 | break; |
| 1892 | case 3: // group membership filter |
| 1893 | case 4: // union filter |
| 1894 | case 5: // intersection filter |
| 1895 | break; |
| 1896 | |
| 1897 | default: |
| 1898 | QVERIFY(false); // force fail. |
| 1899 | break; |
| 1900 | } |
| 1901 | } |
| 1902 | |
| 1903 | if (secondfilter) { |
| 1904 | switch (sftype) { |
| 1905 | case 1: // detail filter |
| 1906 | z = new QContactDetailFilter(); |
| 1907 | static_cast<QContactDetailFilter*>(z)->setDetailType(type: sfdetailtype, field: sfdetailfield); |
| 1908 | if (sfsetvalue) |
| 1909 | static_cast<QContactDetailFilter*>(z)->setValue(sfvalue); |
| 1910 | break; |
| 1911 | case 2: // range filter |
| 1912 | z = new QContactDetailRangeFilter(); |
| 1913 | static_cast<QContactDetailRangeFilter*>(z)->setDetailType(type: sfdetailtype, field: sfdetailfield); |
| 1914 | static_cast<QContactDetailRangeFilter*>(z)->setRange(min: sfminrange, max: sfmaxrange); |
| 1915 | break; |
| 1916 | case 3: // group membership filter |
| 1917 | case 4: // union filter |
| 1918 | case 5: // intersection filter |
| 1919 | break; |
| 1920 | |
| 1921 | default: |
| 1922 | QVERIFY(false); // force fail. |
| 1923 | break; |
| 1924 | } |
| 1925 | } |
| 1926 | |
| 1927 | // control variables - order: starts, ends, mids |
| 1928 | bool sX = false; |
| 1929 | bool sY = false; |
| 1930 | bool sZ = false; |
| 1931 | bool eX = false; |
| 1932 | bool eY = false; |
| 1933 | bool eZ = false; |
| 1934 | bool mX = false; |
| 1935 | bool mY = false; |
| 1936 | bool mZ = false; |
| 1937 | |
| 1938 | if (order.startsWith(s: "X" )) |
| 1939 | sX = true; |
| 1940 | if (order.startsWith(s: "Y" )) |
| 1941 | sY = true; |
| 1942 | if (order.startsWith(s: "Z" )) |
| 1943 | sZ = true; |
| 1944 | if (order.endsWith(s: "X" )) |
| 1945 | eX = true; |
| 1946 | if (order.endsWith(s: "Y" )) |
| 1947 | eY = true; |
| 1948 | if (order.endsWith(s: "Z" )) |
| 1949 | eZ = true; |
| 1950 | if (order.size() > 2) { |
| 1951 | if (order.at(i: 1) == 'X') |
| 1952 | mX = true; |
| 1953 | if (order.at(i: 1) == 'Y') |
| 1954 | mY = true; |
| 1955 | if (order.at(i: 1) == 'Z') |
| 1956 | mZ = true; |
| 1957 | } |
| 1958 | |
| 1959 | // now perform the filtering. |
| 1960 | QContactUnionFilter resultFilter; |
| 1961 | if (sX) { |
| 1962 | if (mY && eZ) |
| 1963 | resultFilter = *x | *y | *z; |
| 1964 | else if (mZ && eY) |
| 1965 | resultFilter = *x | *z | *y; |
| 1966 | else if (eY) |
| 1967 | resultFilter = *x | *y; |
| 1968 | else if (eZ) |
| 1969 | resultFilter = *x | *z; |
| 1970 | } else if (sY) { |
| 1971 | if (mX && eZ) |
| 1972 | resultFilter = *y | *x | *z; |
| 1973 | else if (mZ && eX) |
| 1974 | resultFilter = *y | *z | *x; |
| 1975 | else if (eX) |
| 1976 | resultFilter = *y | *x; |
| 1977 | else if (eZ) |
| 1978 | resultFilter = *y | *z; |
| 1979 | } else if (sZ) { |
| 1980 | if (mX && eY) |
| 1981 | resultFilter = *z | *x | *y; |
| 1982 | else if (mY && eX) |
| 1983 | resultFilter = *z | *y | *x; |
| 1984 | else if (eX) |
| 1985 | resultFilter = *z | *x; |
| 1986 | else if (eY) |
| 1987 | resultFilter = *z | *y; |
| 1988 | } |
| 1989 | |
| 1990 | QList<QContactId> contacts = contactsAddedToManagers.values(akey: cm); |
| 1991 | QList<QContactId> ids; |
| 1992 | |
| 1993 | ids = cm->contactIds(filter: resultFilter); |
| 1994 | |
| 1995 | QString output = convertIds(allIds: contacts, ids, minimumContact: 'a', maximumContact: 'k'); // don't include the convenience filtering contacts |
| 1996 | QCOMPARE_UNSORTED(output, expected); |
| 1997 | |
| 1998 | delete x; |
| 1999 | if (y) delete y; |
| 2000 | if (z) delete z; |
| 2001 | } |
| 2002 | |
| 2003 | void tst_QContactManagerFiltering::relationshipFiltering_data() |
| 2004 | { |
| 2005 | QTest::addColumn<QContactManager *>(name: "cm" ); |
| 2006 | QTest::addColumn<int>(name: "relatedContactRole" ); |
| 2007 | QTest::addColumn<QString>(name: "relationshipType" ); |
| 2008 | QTest::addColumn<char>(name: "relatedContact" ); |
| 2009 | QTest::addColumn<QString>(name: "expected" ); |
| 2010 | |
| 2011 | const int firstRole(static_cast<int>(QContactRelationship::First)); |
| 2012 | const int secondRole(static_cast<int>(QContactRelationship::Second)); |
| 2013 | const int eitherRole(static_cast<int>(QContactRelationship::Either)); |
| 2014 | |
| 2015 | for (int i = 0; i < managers.size(); i++) { |
| 2016 | QContactManager *manager = managers.at(i); |
| 2017 | |
| 2018 | // HasMember |
| 2019 | QTest::newRow(dataTag: "RF-1" ) << manager << secondRole << QContactRelationship::HasMember() << '\0' << "a" ; |
| 2020 | QTest::newRow(dataTag: "RF-2" ) << manager << firstRole << QContactRelationship::HasMember() << '\0' << "b" ; |
| 2021 | QTest::newRow(dataTag: "RF-3" ) << manager << eitherRole << QContactRelationship::HasMember() << '\0' << "ab" ; |
| 2022 | |
| 2023 | // match any contact that has an assistant |
| 2024 | QTest::newRow(dataTag: "RF-4" ) << manager << secondRole << QContactRelationship::HasAssistant() << '\0' << "a" ; |
| 2025 | // match any contact that is an assistant |
| 2026 | QTest::newRow(dataTag: "RF-5" ) << manager << firstRole << QContactRelationship::HasAssistant() << '\0' << "b" ; |
| 2027 | // match any contact that has an assistant or is an assistant |
| 2028 | QTest::newRow(dataTag: "RF-6" ) << manager << eitherRole << QContactRelationship::HasAssistant() << '\0' << "ab" ; |
| 2029 | |
| 2030 | // IsSameAs |
| 2031 | QTest::newRow(dataTag: "RF-7" ) << manager << secondRole << QContactRelationship::IsSameAs() << '\0' << "a" ; |
| 2032 | QTest::newRow(dataTag: "RF-8" ) << manager << firstRole << QContactRelationship::IsSameAs() << '\0' << "b" ; |
| 2033 | QTest::newRow(dataTag: "RF-9" ) << manager << eitherRole << QContactRelationship::IsSameAs() << '\0' << "ab" ; |
| 2034 | |
| 2035 | // Aggregates |
| 2036 | QTest::newRow(dataTag: "RF-10" ) << manager << secondRole << QContactRelationship::Aggregates() << '\0' << "a" ; |
| 2037 | QTest::newRow(dataTag: "RF-11" ) << manager << firstRole << QContactRelationship::Aggregates() << '\0' << "b" ; |
| 2038 | QTest::newRow(dataTag: "RF-12" ) << manager << eitherRole << QContactRelationship::Aggregates() << '\0' << "ab" ; |
| 2039 | |
| 2040 | // HasManager |
| 2041 | QTest::newRow(dataTag: "RF-13" ) << manager << secondRole << QContactRelationship::HasManager() << '\0' << "a" ; |
| 2042 | QTest::newRow(dataTag: "RF-14" ) << manager << firstRole << QContactRelationship::HasManager() << '\0' << "b" ; |
| 2043 | QTest::newRow(dataTag: "RF-15" ) << manager << eitherRole << QContactRelationship::HasManager() << '\0' << "ab" ; |
| 2044 | |
| 2045 | // HasSpouse |
| 2046 | QTest::newRow(dataTag: "RF-16" ) << manager << secondRole << QContactRelationship::HasSpouse() << '\0' << "a" ; |
| 2047 | QTest::newRow(dataTag: "RF-17" ) << manager << firstRole << QContactRelationship::HasSpouse() << '\0' << "b" ; |
| 2048 | QTest::newRow(dataTag: "RF-18" ) << manager << eitherRole << QContactRelationship::HasSpouse() << '\0' << "ab" ; |
| 2049 | |
| 2050 | // Unknown relationship |
| 2051 | QTest::newRow(dataTag: "RF-19" ) << manager << secondRole << QStringLiteral("UnknownRelationship" ) << '\0' << "a" ; |
| 2052 | QTest::newRow(dataTag: "RF-20" ) << manager << firstRole << QStringLiteral("UnknownRelationship" ) << '\0' << "b" ; |
| 2053 | QTest::newRow(dataTag: "RF-21" ) << manager << eitherRole << QStringLiteral("UnknownRelationship" ) << '\0' << "ab" ; |
| 2054 | |
| 2055 | // match any contact that is the related contact in a relationship with contact-A |
| 2056 | QTest::newRow(dataTag: "RF-22" ) << manager << secondRole << QString() << 'a' << "" ; |
| 2057 | // match any contact has contact-A as the related contact |
| 2058 | QTest::newRow(dataTag: "RF-23" ) << manager << firstRole << QString() << 'a' << "b" ; |
| 2059 | // match any contact that has any relationship with contact-A |
| 2060 | QTest::newRow(dataTag: "RF-24" ) << manager << eitherRole << QString() << 'a' << "b" ; |
| 2061 | |
| 2062 | // match any contact that is the related contact in a relationship with contact-B |
| 2063 | QTest::newRow(dataTag: "RF-25" ) << manager << secondRole << QString() << 'b' << "a" ; |
| 2064 | // match any contact has contact-B as the related contact |
| 2065 | QTest::newRow(dataTag: "RF-26" ) << manager << firstRole << QString() << 'b' << "" ; |
| 2066 | // match any contact that has any relationship with contact-B |
| 2067 | QTest::newRow(dataTag: "RF-27" ) << manager << eitherRole << QString() << 'b' << "a" ; |
| 2068 | } |
| 2069 | } |
| 2070 | |
| 2071 | QContact tst_QContactManagerFiltering::createContact(QContactManager* cm, QContactType::TypeValues type, const QString &name) |
| 2072 | { |
| 2073 | QContact contact; |
| 2074 | contact.setType(type); |
| 2075 | QContactName contactName; |
| 2076 | for (int i = QContactName::FieldPrefix; i <= QContactName::FieldSuffix; ++i) { |
| 2077 | contactName.setValue(field: i, value: name); |
| 2078 | } |
| 2079 | contact.saveDetail(detail: &contactName); |
| 2080 | cm->saveContact(contact: &contact); |
| 2081 | return contact; |
| 2082 | } |
| 2083 | |
| 2084 | void tst_QContactManagerFiltering::relationshipFiltering() |
| 2085 | { |
| 2086 | QFETCH(QContactManager*, cm); |
| 2087 | QFETCH(int, relatedContactRole); |
| 2088 | QFETCH(QString, relationshipType); |
| 2089 | QFETCH(char, relatedContact); |
| 2090 | QFETCH(QString, expected); |
| 2091 | |
| 2092 | // TODO: A little re-factoring could be used to make the test case more readable |
| 2093 | |
| 2094 | // 1. Create contacts to be used in relationship testing |
| 2095 | QContact contactA; |
| 2096 | if(relationshipType == QContactRelationship::HasMember()) { |
| 2097 | // Change contact type to group as this is required at least by symbian backend |
| 2098 | // TODO: should it be possible to query this constraint from the backend? |
| 2099 | contactA = createContact(cm, type: QContactType::TypeGroup, name: "ContactA" ); |
| 2100 | } else { |
| 2101 | contactA = createContact(cm, type: QContactType::TypeContact, name: "ContactA" ); |
| 2102 | } |
| 2103 | QContact contactB = createContact(cm, type: QContactType::TypeContact, name: "ContactB" ); |
| 2104 | |
| 2105 | // 2. Create the relationship between the contacts |
| 2106 | QContact first; |
| 2107 | first.setId(contactA.id()); |
| 2108 | QContact second; |
| 2109 | second.setId(contactB.id()); |
| 2110 | |
| 2111 | QContactRelationship h2i; |
| 2112 | h2i.setFirst(first.id()); |
| 2113 | h2i.setSecond(second.id()); |
| 2114 | h2i.setRelationshipType(relationshipType); |
| 2115 | // save and check error code |
| 2116 | bool succeeded = false; |
| 2117 | if(cm->isRelationshipTypeSupported(relationshipType, contactType: contactA.type()) |
| 2118 | && cm->isRelationshipTypeSupported(relationshipType, contactType: contactB.type())) { |
| 2119 | succeeded = true; |
| 2120 | QVERIFY(cm->saveRelationship(&h2i)); |
| 2121 | QCOMPARE(cm->error(), QContactManager::NoError); |
| 2122 | } else { |
| 2123 | QVERIFY(!cm->saveRelationship(&h2i)); |
| 2124 | QCOMPARE(cm->error(), QContactManager::NotSupportedError); |
| 2125 | } |
| 2126 | |
| 2127 | // 3. Construct the filter |
| 2128 | QContactRelationshipFilter crf; |
| 2129 | crf.setRelatedContactRole(static_cast<QContactRelationship::Role>(relatedContactRole)); |
| 2130 | crf.setRelationshipType(relationshipType); |
| 2131 | if (relatedContact == 'a') { |
| 2132 | crf.setRelatedContactId(first.id()); |
| 2133 | } else if (relatedContact == 'b') { |
| 2134 | crf.setRelatedContactId(second.id()); |
| 2135 | } |
| 2136 | |
| 2137 | // 4. Grab the filtering results |
| 2138 | QList<QContactId> contacts; |
| 2139 | contacts.append(t: contactA.id()); |
| 2140 | contacts.append(t: contactB.id()); |
| 2141 | QList<QContactId> ids = cm->contactIds(filter: crf); |
| 2142 | QString output = convertIds(allIds: contacts, ids, minimumContact: 'a', maximumContact: 'k'); // don't include the convenience filtering contacts |
| 2143 | |
| 2144 | // Check that a different relationship type does not match |
| 2145 | crf.setRelationshipType(QStringLiteral("Some other type" )); |
| 2146 | QList<QContactId> ids2 = cm->contactIds(filter: crf); |
| 2147 | |
| 2148 | // 5. Remove the created relationship and contacts |
| 2149 | if(succeeded) { |
| 2150 | // Check that an existing relationship can be removed |
| 2151 | QVERIFY(cm->removeRelationship(h2i)); |
| 2152 | QCOMPARE(cm->error(), QContactManager::NoError); |
| 2153 | } else { |
| 2154 | // Check that non-existing relationship cannot be removed |
| 2155 | QVERIFY(!cm->removeRelationship(h2i)); |
| 2156 | //TODO: what is the expected error code? |
| 2157 | //QCOMPARE(cm->error(), QContactManager::DoesNotExistError); |
| 2158 | } |
| 2159 | foreach (const QContactId& cid, contacts) { |
| 2160 | cm->removeContact(contactId: cid); |
| 2161 | } |
| 2162 | |
| 2163 | // 6. Verify the filtering result |
| 2164 | if(succeeded) { |
| 2165 | QCOMPARE_UNSORTED(output, expected); |
| 2166 | QCOMPARE(ids2, QList<QContactId>()); |
| 2167 | } else { |
| 2168 | QString msg = "Manager does not support relationship type " + relationshipType + " between " + contactA.type() + " and " + contactB.type() + " type contacts." ; |
| 2169 | QSKIP(msg.toLatin1()); |
| 2170 | } |
| 2171 | } |
| 2172 | |
| 2173 | void tst_QContactManagerFiltering::sorting_data() |
| 2174 | { |
| 2175 | QTest::addColumn<QContactManager *>(name: "cm" ); |
| 2176 | QTest::addColumn<QContactDetail::DetailType>(name: "detailType" ); |
| 2177 | QTest::addColumn<int>(name: "detailField" ); |
| 2178 | QTest::addColumn<int>(name: "directioni" ); |
| 2179 | QTest::addColumn<bool>(name: "setbp" ); |
| 2180 | QTest::addColumn<int>(name: "blankpolicyi" ); |
| 2181 | QTest::addColumn<int>(name: "casesensitivityi" ); |
| 2182 | QTest::addColumn<QString>(name: "expected" ); |
| 2183 | QTest::addColumn<QString>(name: "unstable" ); |
| 2184 | |
| 2185 | int firstname = QContactName::FieldFirstName; |
| 2186 | int lastname = QContactName::FieldLastName; |
| 2187 | QContactDetail::DetailType nameType = QContactName::Type; |
| 2188 | QContactDetail::DetailType dlType = QContactDisplayLabel::Type; |
| 2189 | int dlfld = QContactDisplayLabel::FieldLabel; |
| 2190 | |
| 2191 | int asc = Qt::AscendingOrder; |
| 2192 | int desc = Qt::DescendingOrder; |
| 2193 | int bll = QContactSortOrder::BlanksLast; |
| 2194 | int blf = QContactSortOrder::BlanksFirst; |
| 2195 | int cs = Qt::CaseSensitive; |
| 2196 | int ci = Qt::CaseInsensitive; |
| 2197 | |
| 2198 | for (int i = 0; i < managers.size(); i++) { |
| 2199 | QContactManager *manager = managers.at(i); |
| 2200 | |
| 2201 | QPair<QContactDetail::DetailType, int> integerDefAndFieldNames = defAndFieldNamesForTypePerManager.value(akey: manager).value(akey: "Integer" ); |
| 2202 | QPair<QContactDetail::DetailType, int> stringDefAndFieldNames = defAndFieldNamesForTypePerManager.value(akey: manager).value(akey: "String" ); |
| 2203 | |
| 2204 | newMRow(tag: "first ascending" , cm: manager) << manager << nameType << firstname << asc << false << 0 << cs << expectedSorting(m: manager, ufs: "abcdefgikhj" , lfs: "hjabcdefgik" , iufs: "abcdefgihkj" , ilfs: "abcdefghijk" , fpiufs: "abcdefgihkj" , fpilfs: "abcdefghijk" ) << "efg" ; // efg have the same first name |
| 2205 | newMRow(tag: "first descending" , cm: manager) << manager << nameType << firstname << desc << false << 0 << cs << expectedSorting(m: manager, ufs: "jhkigfedcba" , lfs: "kigfedcbajh" , iufs: "jkhigfedcba" , ilfs: "kjihgfedcba" , fpiufs: "jkhigfedcba" , fpilfs: "kjihgfedcba" ) << "efg" ;// efg have the same first name |
| 2206 | newMRow(tag: "last ascending" , cm: manager) << manager << nameType << lastname << asc << false << 0 << cs << "bacdefghijk" << "hijk" ; // all have a well defined, sortable last name except hijk |
| 2207 | newMRow(tag: "last descending" , cm: manager) << manager << nameType << lastname << desc << false << 0 << cs << "gfedcabhijk" << "hijk" ; // all have a well defined, sortable last name except hijk |
| 2208 | if (validDetailField(pair: integerDefAndFieldNames)) { |
| 2209 | newMRow(tag: "integer ascending, blanks last" , cm: manager) << manager << integerDefAndFieldNames.first << integerDefAndFieldNames.second << asc << true << bll << cs << "cabgfedhijk" << "gfedhijk" ; // gfedhijk have no integer |
| 2210 | newMRow(tag: "integer descending, blanks last" , cm: manager) << manager << integerDefAndFieldNames.first << integerDefAndFieldNames.second << desc << true << bll << cs << "bacgfedhijk" << "gfedhijk" ; // gfedhijk have no integer |
| 2211 | newMRow(tag: "integer ascending, blanks first" , cm: manager) << manager << integerDefAndFieldNames.first << integerDefAndFieldNames.second << asc << true << blf << cs << "hijkdefgcab" << "gfedhijk" ; // gfedhijk have no integer |
| 2212 | newMRow(tag: "integer descending, blanks first" , cm: manager) << manager << integerDefAndFieldNames.first << integerDefAndFieldNames.second << desc << true << blf << cs << "hijkdefgbac" << "gfedhijk" ; // gfedhijk have no integer |
| 2213 | } |
| 2214 | if (validDetailField(pair: stringDefAndFieldNames)) { |
| 2215 | QTest::newRow(dataTag: "string ascending (null value), blanks first" ) << manager << stringDefAndFieldNames.first << stringDefAndFieldNames.second << asc << true << blf << cs << "feabcdg" << "fehijk" ; // f and e have blank string |
| 2216 | QTest::newRow(dataTag: "string ascending (null value), blanks last" ) << manager << stringDefAndFieldNames.first << stringDefAndFieldNames.second << asc << true << bll << cs << "abcdgef" << "efhijk" ; // f and e have blank string |
| 2217 | } |
| 2218 | |
| 2219 | newMRow(tag: "display label insensitive" , cm: manager) << manager << dlType << dlfld << asc << false << 0 << ci << "abcdefghjik" << "efghji" ; |
| 2220 | newMRow(tag: "display label sensitive" , cm: manager) << manager << dlType << dlfld << asc << false << 0 << cs << "abcdefghjik" << "efg" ; |
| 2221 | } |
| 2222 | } |
| 2223 | |
| 2224 | void tst_QContactManagerFiltering::sorting() |
| 2225 | { |
| 2226 | QFETCH(QContactManager*, cm); |
| 2227 | QFETCH(QContactDetail::DetailType, detailType); |
| 2228 | QFETCH(int, detailField); |
| 2229 | QFETCH(int, directioni); |
| 2230 | QFETCH(bool, setbp); |
| 2231 | QFETCH(int, blankpolicyi); |
| 2232 | QFETCH(int, casesensitivityi); |
| 2233 | QFETCH(QString, expected); |
| 2234 | QFETCH(QString, unstable); |
| 2235 | |
| 2236 | Qt::SortOrder direction = (Qt::SortOrder)directioni; |
| 2237 | QContactSortOrder::BlankPolicy blankpolicy = (QContactSortOrder::BlankPolicy) blankpolicyi; |
| 2238 | Qt::CaseSensitivity casesensitivity = (Qt::CaseSensitivity) casesensitivityi; |
| 2239 | |
| 2240 | QList<QContactId> contacts = contactsAddedToManagers.values(akey: cm); |
| 2241 | QList<QContactId> ids; |
| 2242 | |
| 2243 | /* Build the sort order */ |
| 2244 | QContactSortOrder s; |
| 2245 | s.setDetailType(type: detailType, field: detailField); |
| 2246 | s.setDirection(direction); |
| 2247 | if (setbp) |
| 2248 | s.setBlankPolicy(blankpolicy); |
| 2249 | s.setCaseSensitivity(casesensitivity); |
| 2250 | |
| 2251 | ids = cm->contactIds(sortOrders: s); |
| 2252 | QString output = convertIds(allIds: contacts, ids, minimumContact: 'a', maximumContact: 'k'); // don't include the convenience filtering contacts |
| 2253 | |
| 2254 | // It's possible to get some contacts back in an arbitrary order (since we single sort) |
| 2255 | if (unstable.length() > 1) { |
| 2256 | // ensure that the maximum distance between unstable elements in the output is the size of the unstable string. |
| 2257 | int firstIndex = -1; |
| 2258 | int lastIndex = -1; |
| 2259 | |
| 2260 | for (int i = 0; i < output.size(); i++) { |
| 2261 | if (unstable.contains(c: output.at(i))) { |
| 2262 | firstIndex = i; |
| 2263 | break; |
| 2264 | } |
| 2265 | } |
| 2266 | |
| 2267 | for (int i = output.size() - 1; i >= 0; i--) { |
| 2268 | if (unstable.contains(c: output.at(i))) { |
| 2269 | lastIndex = i; |
| 2270 | break; |
| 2271 | } |
| 2272 | } |
| 2273 | |
| 2274 | if (firstIndex == -1 || lastIndex == -1) { |
| 2275 | bool containsAllUnstableElements = false; |
| 2276 | QVERIFY(containsAllUnstableElements); |
| 2277 | } |
| 2278 | |
| 2279 | bool unstableElementsAreGrouped = ((lastIndex - firstIndex) == (unstable.length() - 1)); |
| 2280 | QVERIFY(unstableElementsAreGrouped); |
| 2281 | |
| 2282 | // now remove all unstable elements from the output |
| 2283 | for (int i = 1; i < unstable.length(); i++) { |
| 2284 | output.remove(c: unstable.at(i)); |
| 2285 | expected.remove(c: unstable.at(i)); |
| 2286 | } |
| 2287 | } |
| 2288 | |
| 2289 | // These tests pass only due to the un-sorted order matching the tested order: |
| 2290 | //QEXPECT_FAIL("display label insensitive[memory]", "memory backend does not add QContactDisplayLabel details", Continue); |
| 2291 | //QEXPECT_FAIL("display label insensitive[memory[params]]", "memory backend does not add QContactDisplayLabel details", Continue); |
| 2292 | QEXPECT_FAIL("display label sensitive[memory]" , "memory backend does not add QContactDisplayLabel details" , Continue); |
| 2293 | QEXPECT_FAIL("display label sensitive[memory[params]]" , "memory backend does not add QContactDisplayLabel details" , Continue); |
| 2294 | QCOMPARE(output, expected); |
| 2295 | |
| 2296 | /* Now do a check with a filter involved; the filter should not affect the sort order */ |
| 2297 | QContactDetailFilter presenceName; |
| 2298 | presenceName.setDetailType(type: QContactName::Type); |
| 2299 | |
| 2300 | ids = cm->contactIds(filter: presenceName, sortOrders: s); |
| 2301 | |
| 2302 | output = convertIds(allIds: contacts, ids, minimumContact: 'a', maximumContact: 'k'); // don't include the convenience filtering contacts |
| 2303 | |
| 2304 | // It's possible to get some contacts back in an arbitrary order (since we single sort) |
| 2305 | if (unstable.length() > 1) { |
| 2306 | // ensure that the maximum distance between unstable elements in the output is the size of the unstable string. |
| 2307 | int firstIndex = -1; |
| 2308 | int lastIndex = -1; |
| 2309 | |
| 2310 | for (int i = 0; i < output.size(); i++) { |
| 2311 | if (unstable.contains(c: output.at(i))) { |
| 2312 | firstIndex = i; |
| 2313 | break; |
| 2314 | } |
| 2315 | } |
| 2316 | |
| 2317 | for (int i = output.size() - 1; i >= 0; i--) { |
| 2318 | if (unstable.contains(c: output.at(i))) { |
| 2319 | lastIndex = i; |
| 2320 | break; |
| 2321 | } |
| 2322 | } |
| 2323 | |
| 2324 | if (firstIndex == -1 || lastIndex == -1) { |
| 2325 | bool containsAllUnstableElements = false; |
| 2326 | QVERIFY(containsAllUnstableElements); |
| 2327 | } |
| 2328 | |
| 2329 | bool unstableElementsAreGrouped = ((lastIndex - firstIndex) == (unstable.length() - 1)); |
| 2330 | QVERIFY(unstableElementsAreGrouped); |
| 2331 | |
| 2332 | // now remove all unstable elements from the output |
| 2333 | for (int i = 1; i < unstable.length(); i++) { |
| 2334 | output.remove(c: unstable.at(i)); |
| 2335 | expected.remove(c: unstable.at(i)); |
| 2336 | } |
| 2337 | } |
| 2338 | |
| 2339 | //QEXPECT_FAIL("display label insensitive[memory]", "memory backend does not add QContactDisplayLabel details", Continue); |
| 2340 | //QEXPECT_FAIL("display label insensitive[memory[params]]", "memory backend does not add QContactDisplayLabel details", Continue); |
| 2341 | QEXPECT_FAIL("display label sensitive[memory]" , "memory backend does not add QContactDisplayLabel details" , Continue); |
| 2342 | QEXPECT_FAIL("display label sensitive[memory[params]]" , "memory backend does not add QContactDisplayLabel details" , Continue); |
| 2343 | QCOMPARE(output, expected); |
| 2344 | } |
| 2345 | |
| 2346 | void tst_QContactManagerFiltering::multiSorting_data() |
| 2347 | { |
| 2348 | QTest::addColumn<QContactManager *>(name: "cm" ); |
| 2349 | |
| 2350 | QTest::addColumn<bool>(name: "firstsort" ); |
| 2351 | QTest::addColumn<QContactDetail::DetailType>(name: "fsdetailtype" ); |
| 2352 | QTest::addColumn<int>(name: "fsdetailfield" ); |
| 2353 | QTest::addColumn<int>(name: "fsdirectioni" ); |
| 2354 | |
| 2355 | QTest::addColumn<bool>(name: "secondsort" ); |
| 2356 | QTest::addColumn<QContactDetail::DetailType>(name: "ssdetailtype" ); |
| 2357 | QTest::addColumn<int>(name: "ssdetailfield" ); |
| 2358 | QTest::addColumn<int>(name: "ssdirectioni" ); |
| 2359 | |
| 2360 | QTest::addColumn<QString>(name: "expected" ); |
| 2361 | QTest::addColumn<bool>(name: "efgunstable" ); |
| 2362 | |
| 2363 | |
| 2364 | QString es; |
| 2365 | |
| 2366 | int firstname = QContactName::FieldFirstName; |
| 2367 | int lastname = QContactName::FieldLastName; |
| 2368 | QContactDetail::DetailType nameType = QContactName::Type; |
| 2369 | QContactDetail::DetailType phoneType = QContactPhoneNumber::Type; |
| 2370 | int numberfield = QContactPhoneNumber::FieldNumber; |
| 2371 | |
| 2372 | int asc = Qt::AscendingOrder; |
| 2373 | int desc = Qt::DescendingOrder; |
| 2374 | |
| 2375 | for (int i = 0; i < managers.size(); i++) { |
| 2376 | QContactManager *manager = managers.at(i); |
| 2377 | QPair<QContactDetail::DetailType, int> stringDefAndFieldNames = defAndFieldNamesForTypePerManager.value(akey: manager).value(akey: "String" ); |
| 2378 | |
| 2379 | QTest::newRow(dataTag: "1" ) << manager |
| 2380 | << true << nameType << firstname << asc |
| 2381 | << true << nameType << lastname << asc |
| 2382 | << "abcdefg" << false; |
| 2383 | QTest::newRow(dataTag: "2" ) << manager |
| 2384 | << true << nameType << firstname << asc |
| 2385 | << true << nameType << lastname << desc |
| 2386 | << "abcdgfe" << false; |
| 2387 | QTest::newRow(dataTag: "3" ) << manager |
| 2388 | << true << nameType << firstname << desc |
| 2389 | << true << nameType << lastname << asc |
| 2390 | << "efgdcba" << false; |
| 2391 | QTest::newRow(dataTag: "4" ) << manager |
| 2392 | << true << nameType << firstname << desc |
| 2393 | << true << nameType << lastname << desc |
| 2394 | << "gfedcba" << false; |
| 2395 | |
| 2396 | QTest::newRow(dataTag: "5" ) << manager |
| 2397 | << true << nameType << firstname << asc |
| 2398 | << false << nameType << lastname << asc |
| 2399 | << "abcdefg" << true; |
| 2400 | |
| 2401 | QTest::newRow(dataTag: "5b" ) << manager |
| 2402 | << true << nameType << firstname << asc |
| 2403 | << true << static_cast<QContactDetail::DetailType>(-1) << -1 << asc |
| 2404 | << "abcdefg" << true; |
| 2405 | |
| 2406 | QTest::newRow(dataTag: "6" ) << manager |
| 2407 | << false << nameType << firstname << asc |
| 2408 | << true << nameType << lastname << asc |
| 2409 | << "bacdefg" << false; |
| 2410 | |
| 2411 | // This test is completely unstable; no sort criteria means dependent upon internal sort order of manager. |
| 2412 | //QTest::newRow("7") << manager |
| 2413 | // << false << nameType << firstname << asc |
| 2414 | // << false << nameType << lastname << asc |
| 2415 | // << "abcdefg" << false; // XXX Isn't this totally unstable? |
| 2416 | |
| 2417 | if (validDetailField(pair: stringDefAndFieldNames)) { |
| 2418 | QTest::newRow(dataTag: "8" ) << manager |
| 2419 | << true << stringDefAndFieldNames.first << stringDefAndFieldNames.second << asc |
| 2420 | << false << stringDefAndFieldNames.first << stringDefAndFieldNames.second << desc |
| 2421 | << "abcdgef" << false; // default policy = blanks last, and ef have no value (e is empty, f is null) |
| 2422 | |
| 2423 | QTest::newRow(dataTag: "8b" ) << manager |
| 2424 | << true << stringDefAndFieldNames.first << stringDefAndFieldNames.second << asc |
| 2425 | << false << static_cast<QContactDetail::DetailType>(-1) << -1 << desc |
| 2426 | << "abcdgef" << false; // default policy = blanks last, and ef have no value (e is empty, f is null) |
| 2427 | } |
| 2428 | |
| 2429 | QTest::newRow(dataTag: "9" ) << manager |
| 2430 | << true << phoneType << numberfield << asc |
| 2431 | << true << nameType << lastname << desc |
| 2432 | << "abgfedc" << false; |
| 2433 | |
| 2434 | QTest::newRow(dataTag: "10" ) << manager |
| 2435 | << true << nameType << firstname << asc |
| 2436 | << true << nameType << firstname << desc |
| 2437 | << "abcdefg" << true; |
| 2438 | |
| 2439 | } |
| 2440 | } |
| 2441 | |
| 2442 | void tst_QContactManagerFiltering::multiSorting() |
| 2443 | { |
| 2444 | QFETCH(QContactManager*, cm); |
| 2445 | QFETCH(bool, firstsort); |
| 2446 | QFETCH(QContactDetail::DetailType, fsdetailtype); |
| 2447 | QFETCH(int, fsdetailfield); |
| 2448 | QFETCH(int, fsdirectioni); |
| 2449 | QFETCH(bool, secondsort); |
| 2450 | QFETCH(QContactDetail::DetailType, ssdetailtype); |
| 2451 | QFETCH(int, ssdetailfield); |
| 2452 | QFETCH(int, ssdirectioni); |
| 2453 | QFETCH(QString, expected); |
| 2454 | QFETCH(bool, efgunstable); |
| 2455 | |
| 2456 | Qt::SortOrder fsdirection = (Qt::SortOrder)fsdirectioni; |
| 2457 | Qt::SortOrder ssdirection = (Qt::SortOrder)ssdirectioni; |
| 2458 | |
| 2459 | QList<QContactId> contacts = contactsAddedToManagers.values(akey: cm); |
| 2460 | |
| 2461 | /* Build the sort orders */ |
| 2462 | QContactSortOrder fs; |
| 2463 | fs.setDetailType(type: fsdetailtype, field: fsdetailfield); |
| 2464 | fs.setDirection(fsdirection); |
| 2465 | QContactSortOrder ss; |
| 2466 | ss.setDetailType(type: ssdetailtype, field: ssdetailfield); |
| 2467 | ss.setDirection(ssdirection); |
| 2468 | QList<QContactSortOrder> sortOrders; |
| 2469 | if (firstsort) |
| 2470 | sortOrders.append(t: fs); |
| 2471 | if (secondsort) |
| 2472 | sortOrders.append(t: ss); |
| 2473 | |
| 2474 | QList<QContactId> ids = cm->contactIds(sortOrders); |
| 2475 | QString output = convertIds(allIds: contacts, ids, minimumContact: 'a', maximumContact: 'k'); // don't include the convenience filtering contacts |
| 2476 | |
| 2477 | // Remove the display label tests |
| 2478 | output.remove(c: 'h'); |
| 2479 | output.remove(c: 'i'); |
| 2480 | output.remove(c: 'j'); |
| 2481 | output.remove(c: 'k'); |
| 2482 | |
| 2483 | // Just like the single sort test, we might get some contacts back in indeterminate order |
| 2484 | // (but their relative position with other contacts should not change) |
| 2485 | if (efgunstable) { |
| 2486 | QVERIFY(output.count('e') == 1); |
| 2487 | QVERIFY(output.count('f') == 1); |
| 2488 | QVERIFY(output.count('g') == 1); |
| 2489 | output.remove(c: 'f'); |
| 2490 | output.remove(c: 'g'); |
| 2491 | expected.remove(c: 'f'); |
| 2492 | expected.remove(c: 'g'); |
| 2493 | } |
| 2494 | |
| 2495 | QCOMPARE(output, expected); |
| 2496 | } |
| 2497 | |
| 2498 | #ifdef INCLUDE_TESTACTIONS |
| 2499 | void tst_QContactManagerFiltering::actionPlugins() |
| 2500 | { |
| 2501 | QStringList actions = QContactAction::availableActions(); |
| 2502 | QVERIFY(actions.contains("Boolean" )); |
| 2503 | QVERIFY(actions.contains("Number" )); |
| 2504 | |
| 2505 | /* Ignore the version if the vendor is not set */ |
| 2506 | actions = QContactAction::availableActions(QString()); |
| 2507 | QVERIFY(actions.contains("Boolean" )); |
| 2508 | QVERIFY(actions.contains("Number" )); |
| 2509 | |
| 2510 | actions = QContactAction::availableActions("NumberCo" ); |
| 2511 | QVERIFY(actions.contains("Number" )); |
| 2512 | QVERIFY(!actions.contains("Boolean" )); |
| 2513 | |
| 2514 | actions = QContactAction::availableActions("IntegerCo" ); |
| 2515 | QVERIFY(actions.contains("Number" )); |
| 2516 | QVERIFY(!actions.contains("Boolean" )); |
| 2517 | |
| 2518 | actions = QContactAction::availableActions("BooleanCo" ); |
| 2519 | QVERIFY(!actions.contains("Number" )); |
| 2520 | QVERIFY(actions.contains("Boolean" )); |
| 2521 | |
| 2522 | actions = QContactAction::availableActions("IntegerCo" ); |
| 2523 | QVERIFY(actions.contains("Number" )); |
| 2524 | QVERIFY(!actions.contains("Boolean" )); |
| 2525 | |
| 2526 | actions = QContactAction::availableActions("BooleanCo" ); |
| 2527 | QVERIFY(!actions.contains("Number" )); |
| 2528 | QVERIFY(actions.contains("Boolean" )); |
| 2529 | } |
| 2530 | |
| 2531 | void tst_QContactManagerFiltering::actionFiltering_data() |
| 2532 | { |
| 2533 | QTest::addColumn<QContactManager *>("cm" ); |
| 2534 | QTest::addColumn<QString>("actionName" ); |
| 2535 | QTest::addColumn<QString>("expected" ); |
| 2536 | |
| 2537 | QString es; |
| 2538 | |
| 2539 | for (int i = 0; i < managers.size(); i++) { |
| 2540 | QContactManager *manager = managers.at(i); |
| 2541 | QPair<QContactDetail::DetailType, int> booleanDefAndFieldNames = defAndFieldNamesForTypePerManager.value(manager).value("Bool" ); |
| 2542 | QPair<QContactDetail::DetailType, int> integerDefAndFieldNames = defAndFieldNamesForTypePerManager.value(manager).value("Integer" ); |
| 2543 | QPair<QContactDetail::DetailType, int> dateDefAndFieldNames = defAndFieldNamesForTypePerManager.value(manager).value("Date" ); |
| 2544 | |
| 2545 | newMRow("bad actionname" , manager) << manager << "No such action" << "" ; |
| 2546 | |
| 2547 | QString expected; |
| 2548 | if (validDetailField(integerDefAndFieldNames) || validDetailField(booleanDefAndFieldNames)) { |
| 2549 | expected = "abcd" ; |
| 2550 | } else if (validDetailField(dateDefAndFieldNames)) { |
| 2551 | expected = "abd" ; |
| 2552 | } else { |
| 2553 | /* contact a,b have phone number, so at least phone number action can match them */ |
| 2554 | expected = "ab" ; |
| 2555 | } |
| 2556 | |
| 2557 | QTest::newRow("empty (any action matches)" ) << manager << es << expected; |
| 2558 | |
| 2559 | if (validDetailField(integerDefAndFieldNames)) { |
| 2560 | newMRow("Number" , manager) << manager << "NumberAction" << "abcd" ; |
| 2561 | QTest::newRow("Number (NumberCo)" ) << manager << "NumberAction" << "abcd" ; |
| 2562 | } |
| 2563 | |
| 2564 | if (validDetailField(booleanDefAndFieldNames)) { |
| 2565 | /* Boolean testing */ |
| 2566 | newMRow("Boolean action" , manager) << manager << "BooleanAction" << "a" ; |
| 2567 | newMRow("BooleanCo" , manager) << manager << es << "a" ; |
| 2568 | } |
| 2569 | |
| 2570 | if (validDetailField(booleanDefAndFieldNames)) { |
| 2571 | newMRow("Boolean action matching true" , manager) << manager << es << "a" ; |
| 2572 | newMRow("Boolean action matching false" , manager) << manager << es << es; |
| 2573 | } |
| 2574 | |
| 2575 | /* Recursive filtering */ |
| 2576 | QTest::newRow("Recursive action 1" ) << manager << "IntersectionRecursive" << es; |
| 2577 | QTest::newRow("Recursive action 2" ) << manager << "UnionRecursive" << es; |
| 2578 | QTest::newRow("Recursive action 3" ) << manager << "PairRecursive" << es; |
| 2579 | QTest::newRow("Recursive action 4" ) << manager << "AnotherPairRecursive" << es; |
| 2580 | QTest::newRow("Recursive action 5" ) << manager << "Recursive" << es; |
| 2581 | } |
| 2582 | } |
| 2583 | |
| 2584 | void tst_QContactManagerFiltering::actionFiltering() |
| 2585 | { |
| 2586 | QFETCH(QContactManager*, cm); |
| 2587 | QFETCH(QString, actionName); |
| 2588 | QFETCH(QString, expected); |
| 2589 | |
| 2590 | // only test the memory engine - action filtering + service framework plugin loading |
| 2591 | // codepaths are tested fully this way since the codepath for other engines is that of |
| 2592 | // the memory engine, and only the memory engine has the required definitions and fields. |
| 2593 | if (cm->managerName() != QString(QLatin1String("memory" ))) |
| 2594 | return; |
| 2595 | |
| 2596 | /* Load the definition and field names for the various variant types for the current manager */ |
| 2597 | defAndFieldNamesForTypeForActions = defAndFieldNamesForTypePerManager.value(cm); |
| 2598 | if (!defAndFieldNamesForTypeForActions.isEmpty()) { |
| 2599 | QContactActionFilter af; |
| 2600 | af.setActionName(actionName); |
| 2601 | |
| 2602 | QList<QContactId> ids = cm->contactIds(af); |
| 2603 | QList<QContactId> contacts = contactsAddedToManagers.values(cm); |
| 2604 | |
| 2605 | qDebug() << " actionName =" << actionName; |
| 2606 | |
| 2607 | QString output = convertIds(contacts, ids, 'a', 'k'); // don't include the convenience filtering contacts |
| 2608 | QCOMPARE_UNSORTED(output, expected); |
| 2609 | } |
| 2610 | } |
| 2611 | #endif |
| 2612 | |
| 2613 | void tst_QContactManagerFiltering::idListFiltering_data() |
| 2614 | { |
| 2615 | QTest::addColumn<QContactManager *>(name: "cm" ); |
| 2616 | QTest::addColumn<QString>(name: "input" ); |
| 2617 | QTest::addColumn<QString>(name: "expected" ); |
| 2618 | |
| 2619 | QString es; |
| 2620 | |
| 2621 | for (int i = 0; i < managers.size(); i++) { |
| 2622 | QContactManager *manager = managers.at(i); |
| 2623 | newMRow(tag: "empty" , cm: manager) << manager << es << es; |
| 2624 | newMRow(tag: "a" , cm: manager) << manager << "a" << "a" ; |
| 2625 | newMRow(tag: "ab" , cm: manager) << manager << "ab" << "ab" ; |
| 2626 | newMRow(tag: "aa" , cm: manager) << manager << "aa" << "a" ; |
| 2627 | newMRow(tag: "ba" , cm: manager) << manager << "ba" << "ab" ; |
| 2628 | newMRow(tag: "abcd" , cm: manager) << manager << "abcd" << "abcd" ; |
| 2629 | newMRow(tag: "abcde" , cm: manager) << manager << "abcde" << "abcd" ; |
| 2630 | } |
| 2631 | } |
| 2632 | |
| 2633 | void tst_QContactManagerFiltering::idListFiltering() |
| 2634 | { |
| 2635 | QFETCH(QContactManager*, cm); |
| 2636 | QFETCH(QString, input); |
| 2637 | QFETCH(QString, expected); |
| 2638 | |
| 2639 | QList<QContactId> contacts = contactsAddedToManagers.values(akey: cm); |
| 2640 | QList<QContactId> ids; |
| 2641 | |
| 2642 | // extra id that won't exist |
| 2643 | QContactId e; |
| 2644 | |
| 2645 | /* Convert the input to a list of ids */ |
| 2646 | foreach(QChar c, input) { |
| 2647 | if (c == 'a') |
| 2648 | ids << contacts.at(i: 0); |
| 2649 | else if (c == 'b') |
| 2650 | ids << contacts.at(i: 1); |
| 2651 | else if (c == 'c') |
| 2652 | ids << contacts.at(i: 2); |
| 2653 | else if (c == 'd') |
| 2654 | ids << contacts.at(i: 3); |
| 2655 | else if (c == 'e') |
| 2656 | ids << e; |
| 2657 | } |
| 2658 | |
| 2659 | /* And do the search */ |
| 2660 | QContactIdFilter idf; |
| 2661 | idf.setIds(ids); |
| 2662 | |
| 2663 | /* Retrieve contacts matching the filter, and compare (unsorted) output */ |
| 2664 | ids = cm->contactIds(filter: idf); |
| 2665 | QString output = convertIds(allIds: contacts, ids, minimumContact: 'a', maximumContact: 'k'); // don't include the convenience filtering contacts |
| 2666 | QCOMPARE_UNSORTED(output, expected); |
| 2667 | } |
| 2668 | |
| 2669 | void tst_QContactManagerFiltering::convenienceFiltering_data() |
| 2670 | { |
| 2671 | QTest::addColumn<QContactManager *>(name: "cm" ); |
| 2672 | QTest::addColumn<QString>(name: "addressSubString" ); |
| 2673 | QTest::addColumn<bool>(name: "addressEnabled" ); |
| 2674 | QTest::addColumn<QString>(name: "emailAddressSubString" ); |
| 2675 | QTest::addColumn<bool>(name: "emailEnabled" ); |
| 2676 | QTest::addColumn<QString>(name: "phoneSubString" ); |
| 2677 | QTest::addColumn<bool>(name: "phoneEnabled" ); |
| 2678 | QTest::addColumn<QString>(name: "displayLabelSubString" ); |
| 2679 | QTest::addColumn<bool>(name: "displayLabelEnabled" ); |
| 2680 | QTest::addColumn<QString>(name: "nameSubString" ); |
| 2681 | QTest::addColumn<bool>(name: "nameEnabled" ); |
| 2682 | QTest::addColumn<bool>(name: "favoriteEnabled" ); |
| 2683 | QTest::addColumn<QString>(name: "tagSubString" ); |
| 2684 | QTest::addColumn<bool>(name: "tagEnabled" ); |
| 2685 | QTest::addColumn<QString>(name: "expected" ); |
| 2686 | |
| 2687 | QString es; // empty string |
| 2688 | |
| 2689 | foreach (QContactManager *manager, managers) { |
| 2690 | const QList<QContactDetail::DetailType> supportedTypes(manager->supportedContactDetailTypes()); |
| 2691 | if (supportedTypes.contains(t: QContactAddress::Type)) { |
| 2692 | newMRow(tag: "address matching only" , cm: manager) << manager |
| 2693 | << "streetstring" << true |
| 2694 | << es << false |
| 2695 | << es << false |
| 2696 | << es << false |
| 2697 | << es << false |
| 2698 | << false // Favorite has no substring associated. |
| 2699 | << es << false |
| 2700 | << "l" ; |
| 2701 | } |
| 2702 | if (supportedTypes.contains(t: QContactEmailAddress::Type)) { |
| 2703 | newMRow(tag: "emailAddress matching only" , cm: manager) << manager |
| 2704 | << es << false |
| 2705 | << "@test.com" << true |
| 2706 | << es << false |
| 2707 | << es << false |
| 2708 | << es << false |
| 2709 | << false |
| 2710 | << es << false |
| 2711 | << "m" ; |
| 2712 | } |
| 2713 | if (supportedTypes.contains(t: QContactPhoneNumber::Type)) { |
| 2714 | newMRow(tag: "phone matching only" , cm: manager) << manager |
| 2715 | << es << false |
| 2716 | << es << false |
| 2717 | << "12345" << true |
| 2718 | << es << false |
| 2719 | << es << false |
| 2720 | << false |
| 2721 | << es << false |
| 2722 | << "n" ; |
| 2723 | } |
| 2724 | if (supportedTypes.contains(t: QContactDisplayLabel::Type)) { |
| 2725 | newMRow(tag: "displayLabel matching only" , cm: manager) << manager |
| 2726 | << es << false |
| 2727 | << es << false |
| 2728 | << es << false |
| 2729 | << "Freddy" << true |
| 2730 | << es << false |
| 2731 | << false |
| 2732 | << es << false |
| 2733 | << "o" ; |
| 2734 | } |
| 2735 | if (supportedTypes.contains(t: QContactName::Type)) { |
| 2736 | newMRow(tag: "name matching only" , cm: manager) << manager |
| 2737 | << es << false |
| 2738 | << es << false |
| 2739 | << es << false |
| 2740 | << es << false |
| 2741 | << "Frederic" << true |
| 2742 | << false |
| 2743 | << es << false |
| 2744 | << "p" ; |
| 2745 | } |
| 2746 | if (supportedTypes.contains(t: QContactFavorite::Type)) { |
| 2747 | newMRow(tag: "favorite matching only" , cm: manager) << manager |
| 2748 | << es << false |
| 2749 | << es << false |
| 2750 | << es << false |
| 2751 | << es << false |
| 2752 | << es << false |
| 2753 | << true |
| 2754 | << es << false |
| 2755 | << "q" ; |
| 2756 | } |
| 2757 | if (supportedTypes.contains(t: QContactTag::Type)) { |
| 2758 | newMRow(tag: "tag matching only" , cm: manager) << manager |
| 2759 | << es << false |
| 2760 | << es << false |
| 2761 | << es << false |
| 2762 | << es << false |
| 2763 | << es << false |
| 2764 | << false |
| 2765 | << "Football" << true |
| 2766 | << "r" ; |
| 2767 | } |
| 2768 | if (supportedTypes.contains(t: QContactAddress::Type) && |
| 2769 | supportedTypes.contains(t: QContactPhoneNumber::Type)) { |
| 2770 | newMRow(tag: "address or phone matching" , cm: manager) << manager |
| 2771 | << "streetstring" << true |
| 2772 | << es << false |
| 2773 | << "12345" << true |
| 2774 | << es << false |
| 2775 | << es << false |
| 2776 | << false |
| 2777 | << es << false |
| 2778 | << "ln" ; |
| 2779 | } |
| 2780 | if (supportedTypes.contains(t: QContactFavorite::Type) && |
| 2781 | supportedTypes.contains(t: QContactTag::Type)) { |
| 2782 | newMRow(tag: "favorite or tag matching" , cm: manager) << manager |
| 2783 | << es << false |
| 2784 | << es << false |
| 2785 | << es << false |
| 2786 | << es << false |
| 2787 | << es << false |
| 2788 | << true |
| 2789 | << "Football" << true |
| 2790 | << "qr" ; |
| 2791 | } |
| 2792 | } |
| 2793 | } |
| 2794 | |
| 2795 | void tst_QContactManagerFiltering::convenienceFiltering() |
| 2796 | { |
| 2797 | QFETCH(QContactManager*, cm); |
| 2798 | QFETCH(QString, addressSubString); |
| 2799 | QFETCH(bool, addressEnabled); |
| 2800 | QFETCH(QString, emailAddressSubString); |
| 2801 | QFETCH(bool, emailEnabled); |
| 2802 | QFETCH(QString, phoneSubString); |
| 2803 | QFETCH(bool, phoneEnabled); |
| 2804 | QFETCH(QString, displayLabelSubString); |
| 2805 | QFETCH(bool, displayLabelEnabled); |
| 2806 | QFETCH(QString, nameSubString); |
| 2807 | QFETCH(bool, nameEnabled); |
| 2808 | QFETCH(bool, favoriteEnabled); |
| 2809 | QFETCH(QString, tagSubString); |
| 2810 | QFETCH(bool, tagEnabled); |
| 2811 | QFETCH(QString, expected); |
| 2812 | |
| 2813 | QContactFilter af = QContactAddress::match(subString: addressSubString); |
| 2814 | QContactFilter ef = QContactEmailAddress::match(emailAddress: emailAddressSubString); |
| 2815 | QContactFilter pf = QContactPhoneNumber::match(number: phoneSubString); |
| 2816 | QContactFilter df = QContactDisplayLabel::match(label: displayLabelSubString); |
| 2817 | QContactFilter nf = QContactName::match(name: nameSubString); |
| 2818 | QContactFilter ff = QContactFavorite::match(); |
| 2819 | QContactFilter tf = QContactTag::match(subString: tagSubString); |
| 2820 | |
| 2821 | QList<QContactFilter> convenienceFilters; |
| 2822 | if (addressEnabled) convenienceFilters << af; |
| 2823 | if (emailEnabled) convenienceFilters << ef; |
| 2824 | if (phoneEnabled) convenienceFilters << pf; |
| 2825 | if (displayLabelEnabled) convenienceFilters << df; |
| 2826 | if (nameEnabled) convenienceFilters << nf; |
| 2827 | if (favoriteEnabled) convenienceFilters << ff; |
| 2828 | if (tagEnabled) convenienceFilters << tf; |
| 2829 | |
| 2830 | QContactFilter finalFilter; |
| 2831 | finalFilter = convenienceFilters.at(i: 0); |
| 2832 | if (convenienceFilters.size() > 1) { |
| 2833 | for (int i = 1; i < convenienceFilters.size(); ++i) { |
| 2834 | // if more than one filter, we union them. |
| 2835 | finalFilter = (finalFilter | convenienceFilters.at(i)); |
| 2836 | } |
| 2837 | } |
| 2838 | |
| 2839 | /* Retrieve contacts matching the filter, and ensure that the results are expected */ |
| 2840 | QList<QContactId> ids = cm->contactIds(filter: finalFilter); |
| 2841 | |
| 2842 | // build a string containing letters corresponding to the ids we retrieved. |
| 2843 | QList<QContactId> contacts = contactsAddedToManagers.values(akey: cm); |
| 2844 | QString resultString = convertIds(allIds: contacts, ids, minimumContact: 'l', maximumContact: 'r'); // just the convenience filtering contacts (L->R) |
| 2845 | QEXPECT_FAIL("displayLabel matching only[memory]" , "memory backend does not add QContactDisplayLabel details" , Continue); |
| 2846 | QEXPECT_FAIL("displayLabel matching only[memory[params]]" , "memory backend does not add QContactDisplayLabel details" , Continue); |
| 2847 | QCOMPARE(resultString, expected); |
| 2848 | } |
| 2849 | |
| 2850 | void tst_QContactManagerFiltering::invalidFiltering_data() |
| 2851 | { |
| 2852 | QTest::addColumn<QContactManager*>(name: "cm" ); |
| 2853 | |
| 2854 | for (int i = 0; i < managers.size(); i++) { |
| 2855 | QContactManager *manager = managers.at(i); |
| 2856 | QTest::newRow(dataTag: manager->managerName().toLatin1().constData()) << manager; |
| 2857 | } |
| 2858 | } |
| 2859 | |
| 2860 | void tst_QContactManagerFiltering::invalidFiltering() |
| 2861 | { |
| 2862 | QFETCH(QContactManager*, cm); |
| 2863 | |
| 2864 | QList<QContactId> contacts = contactsAddedToManagers.values(akey: cm); |
| 2865 | QContactInvalidFilter f; // invalid |
| 2866 | QList<QContactId> ids = cm->contactIds(filter: f); |
| 2867 | QVERIFY(ids.count() == 0); |
| 2868 | |
| 2869 | // Try unions/intersections of invalids too |
| 2870 | ids = cm->contactIds(filter: f | f); |
| 2871 | QVERIFY(ids.count() == 0); |
| 2872 | |
| 2873 | ids = cm->contactIds(filter: f & f); |
| 2874 | QVERIFY(ids.count() == 0); |
| 2875 | } |
| 2876 | |
| 2877 | void tst_QContactManagerFiltering::allFiltering_data() |
| 2878 | { |
| 2879 | QTest::addColumn<QContactManager*>(name: "cm" ); |
| 2880 | |
| 2881 | for (int i = 0; i < managers.size(); i++) { |
| 2882 | QContactManager *manager = managers.at(i); |
| 2883 | QTest::newRow(dataTag: manager->managerName().toLatin1().constData()) << manager; |
| 2884 | } |
| 2885 | } |
| 2886 | |
| 2887 | void tst_QContactManagerFiltering::allFiltering() |
| 2888 | { |
| 2889 | QFETCH(QContactManager*, cm); |
| 2890 | |
| 2891 | QList<QContactId> contacts = contactsAddedToManagers.values(akey: cm); |
| 2892 | QContactFilter f; // default = permissive |
| 2893 | QList<QContactId> ids = cm->contactIds(filter: f); |
| 2894 | QVERIFY(ids.count() == contacts.size()); |
| 2895 | QString output = convertIds(allIds: contacts, ids, minimumContact: 'a', maximumContact: 'k'); // don't include the convenience filtering contacts |
| 2896 | QString expected = convertIds(allIds: contacts, ids: contacts, minimumContact: 'a', maximumContact: 'k'); // :) |
| 2897 | QCOMPARE_UNSORTED(output, expected); |
| 2898 | |
| 2899 | // Try unions/intersections of defaults |
| 2900 | ids = cm->contactIds(filter: f | f); |
| 2901 | output = convertIds(allIds: contacts, ids, minimumContact: 'a', maximumContact: 'k'); // don't include the convenience filtering contacts |
| 2902 | QCOMPARE_UNSORTED(output, expected); |
| 2903 | |
| 2904 | ids = cm->contactIds(filter: f & f); |
| 2905 | output = convertIds(allIds: contacts, ids, minimumContact: 'a', maximumContact: 'k'); // don't include the convenience filtering contacts |
| 2906 | QCOMPARE_UNSORTED(output, expected); |
| 2907 | } |
| 2908 | |
| 2909 | void tst_QContactManagerFiltering::fetchHint_data() |
| 2910 | { |
| 2911 | QTest::addColumn<QContactManager*>(name: "cm" ); |
| 2912 | |
| 2913 | for (int i = 0; i < managers.size(); i++) { |
| 2914 | QContactManager *manager = managers.at(i); |
| 2915 | QTest::newRow(dataTag: manager->managerName().toLatin1().constData()) << manager; |
| 2916 | } |
| 2917 | } |
| 2918 | |
| 2919 | void tst_QContactManagerFiltering::fetchHint() |
| 2920 | { |
| 2921 | QFETCH(QContactManager*, cm); |
| 2922 | |
| 2923 | // if no fetch hint is provided, the manager should return all data |
| 2924 | // if a fetch hint is provided, it should have a clearly defined effect, |
| 2925 | // unless it is ignored by the manager, in which case the result should |
| 2926 | // be equivalent to not providing a fetch hint. |
| 2927 | |
| 2928 | // we use a defined sort order for the retrieval of contacts to make comparison simple. |
| 2929 | // We sort on name, because we include name details in the fetch hint. |
| 2930 | QList<QContactSortOrder> nameSort; |
| 2931 | QContactSortOrder firstNameSort, middleNameSort, lastNameSort; |
| 2932 | firstNameSort.setDetailType(type: QContactName::Type, field: QContactName::FieldFirstName); |
| 2933 | middleNameSort.setDetailType(type: QContactName::Type, field: QContactName::FieldMiddleName); |
| 2934 | lastNameSort.setDetailType(type: QContactName::Type, field: QContactName::FieldLastName); |
| 2935 | nameSort << lastNameSort << middleNameSort << firstNameSort; |
| 2936 | |
| 2937 | // fetch all contacts from the manager. |
| 2938 | QList<QContact> allContacts = cm->contacts(sortOrders: nameSort); |
| 2939 | |
| 2940 | // define some maximum count limit, and some list of detail definitions to retrieve. |
| 2941 | int countLimit = (allContacts.size() / 2) + 1; |
| 2942 | QList<QContactDetail::DetailType> defs; |
| 2943 | defs << QContactName::Type |
| 2944 | << QContactPhoneNumber::Type; |
| 2945 | |
| 2946 | // test that the manager doesn't incorrectly implement fetch hints. |
| 2947 | // we test max count limit, and detail definition limits. |
| 2948 | // XXX TODO: other hints! |
| 2949 | QContactFetchHint mclh; // max count limited hint |
| 2950 | QContactFetchHint ddh; // detail definitions hint |
| 2951 | mclh.setMaxCountHint(countLimit); |
| 2952 | ddh.setDetailTypesHint(defs); |
| 2953 | |
| 2954 | // the next part of the test requires some contacts to be saved in the manager. |
| 2955 | if (allContacts.size() == 0) { |
| 2956 | QSKIP("No contacts in manager; skipping fetch hint limit test." ); |
| 2957 | } |
| 2958 | |
| 2959 | // test with a hint which sets a maximum count limit for retrieved contacts. |
| 2960 | QList<QContact> mclhContacts = cm->contacts(sortOrders: nameSort, fetchHint: mclh); |
| 2961 | QVERIFY(allContacts.size() >= mclhContacts.size()); |
| 2962 | if (allContacts.size() > mclh.maxCountHint()) { |
| 2963 | // shouldn't return an arbitrarily smaller amount of contacts. |
| 2964 | QVERIFY(mclhContacts.size() == mclh.maxCountHint() |
| 2965 | || mclhContacts.size() == allContacts.size()); |
| 2966 | } |
| 2967 | for (int i = 0; i < mclhContacts.size(); ++i) { |
| 2968 | // the sort order should still be defined. |
| 2969 | QVERIFY(mclhContacts.at(i) == allContacts.at(i)); |
| 2970 | } |
| 2971 | |
| 2972 | // now test with a hint which describes which details the client is interested in. |
| 2973 | QList<QContact> ddhContacts = cm->contacts(sortOrders: nameSort, fetchHint: ddh); |
| 2974 | QCOMPARE(ddhContacts.size(), allContacts.size()); |
| 2975 | for (int i = 0; i < allContacts.size(); ++i) { |
| 2976 | QContact a = allContacts.at(i); |
| 2977 | QContact b = ddhContacts.at(i); |
| 2978 | |
| 2979 | // since we're sorting on a detail which should exist (since it was included in the hint) |
| 2980 | // the order of the contacts returned shouldn't have changed. |
| 2981 | QVERIFY(a.id() == b.id()); |
| 2982 | |
| 2983 | // check that the hint didn't remove names or phones. |
| 2984 | QCOMPARE(a.details(QContactName::Type).size(), |
| 2985 | b.details(QContactName::Type).size()); |
| 2986 | QCOMPARE(a.details(QContactPhoneNumber::Type).size(), |
| 2987 | b.details(QContactPhoneNumber::Type).size()); |
| 2988 | |
| 2989 | // other details are not necessarily returned. |
| 2990 | QVERIFY(a.details().size() >= b.details().size()); |
| 2991 | } |
| 2992 | } |
| 2993 | |
| 2994 | |
| 2995 | void tst_QContactManagerFiltering::changelogFiltering_data() |
| 2996 | { |
| 2997 | QTest::addColumn<QContactManager *>(name: "cm" ); |
| 2998 | QTest::addColumn<QList<QContactId> >(name: "contacts" ); |
| 2999 | QTest::addColumn<int>(name: "eventType" ); |
| 3000 | QTest::addColumn<QDateTime>(name: "since" ); |
| 3001 | QTest::addColumn<QString>(name: "expected" ); |
| 3002 | |
| 3003 | int added = (int)QContactChangeLogFilter::EventAdded; |
| 3004 | int changed = (int)QContactChangeLogFilter::EventChanged; |
| 3005 | int removed = (int)QContactChangeLogFilter::EventRemoved; |
| 3006 | |
| 3007 | for (int i = 0; i < managers.size(); i++) { |
| 3008 | QContactManager *manager = managers.at(i); |
| 3009 | |
| 3010 | QList<QContactId> contacts = contactsAddedToManagers.values(akey: manager); |
| 3011 | QContact a,b,c,d; |
| 3012 | a = manager->contact(contactId: contacts.at(i: 0)); |
| 3013 | b = manager->contact(contactId: contacts.at(i: 1)); |
| 3014 | c = manager->contact(contactId: contacts.at(i: 2)); |
| 3015 | d = manager->contact(contactId: contacts.at(i: 3)); |
| 3016 | |
| 3017 | QDateTime ac = a.detail<QContactTimestamp>().created(); |
| 3018 | QDateTime bc = b.detail<QContactTimestamp>().created(); |
| 3019 | QDateTime cc = c.detail<QContactTimestamp>().created(); |
| 3020 | QDateTime dc = d.detail<QContactTimestamp>().created(); |
| 3021 | |
| 3022 | QDateTime am = a.detail<QContactTimestamp>().lastModified(); |
| 3023 | QDateTime bm = b.detail<QContactTimestamp>().lastModified(); |
| 3024 | QDateTime cm = c.detail<QContactTimestamp>().lastModified(); |
| 3025 | QDateTime dm = d.detail<QContactTimestamp>().lastModified(); |
| 3026 | |
| 3027 | newMRow(tag: "Added since before start" , cm: manager) << manager << contacts << added << ac.addSecs(secs: -1) << "abcdefg" ; |
| 3028 | newMRow(tag: "Added since first" , cm: manager) << manager << contacts << added << ac << "abcdefg" ; |
| 3029 | newMRow(tag: "Added since second" , cm: manager) << manager << contacts << added << bc << "bcdefg" ; |
| 3030 | newMRow(tag: "Added since third" , cm: manager) << manager << contacts << added << cc << "cdefg" ; |
| 3031 | newMRow(tag: "Added since fourth" , cm: manager) << manager << contacts << added << dc << "defg" ; |
| 3032 | newMRow(tag: "Added since after fourth" , cm: manager) << manager << contacts << added << dc.addSecs(secs: 1) << "efg" ; |
| 3033 | newMRow(tag: "Added since first changed" , cm: manager) << manager << contacts << added << am << "" ; |
| 3034 | newMRow(tag: "Added since second changed" , cm: manager) << manager << contacts << added << bm << "" ; |
| 3035 | newMRow(tag: "Added since third changed" , cm: manager) << manager << contacts << added << cm << "" ; |
| 3036 | newMRow(tag: "Added since fourth changed" , cm: manager) << manager << contacts << added << cm << "" ; |
| 3037 | |
| 3038 | newMRow(tag: "Changed since before start" , cm: manager) << manager << contacts << changed << ac.addSecs(secs: -1) << "abcdefg" ; |
| 3039 | newMRow(tag: "Changed since first" , cm: manager) << manager << contacts << changed << ac << "abcdefg" ; |
| 3040 | newMRow(tag: "Changed since second" , cm: manager) << manager << contacts << changed << bc << "abcdefg" ; |
| 3041 | newMRow(tag: "Changed since third" , cm: manager) << manager << contacts << changed << cc << "abcdefg" ; |
| 3042 | newMRow(tag: "Changed since fourth" , cm: manager) << manager << contacts << changed << dc << "abcdefg" ; |
| 3043 | newMRow(tag: "Changed since after fourth" , cm: manager) << manager << contacts << changed << dc.addSecs(secs: 1) << "abcefg" ; |
| 3044 | newMRow(tag: "Changed since first changed" , cm: manager) << manager << contacts << changed << am << "a" ; |
| 3045 | newMRow(tag: "Changed since second changed" , cm: manager) << manager << contacts << changed << bm << "ab" ; |
| 3046 | newMRow(tag: "Changed since third changed" , cm: manager) << manager << contacts << changed << cm << "abc" ; |
| 3047 | newMRow(tag: "Changed since fourth changed" , cm: manager) << manager << contacts << changed << dm << "abcdefg" ; |
| 3048 | |
| 3049 | // These are currently useless.. |
| 3050 | newMRow(tag: "Removed since before start" , cm: manager) << manager << contacts << removed << ac.addSecs(secs: -1) << "" ; |
| 3051 | newMRow(tag: "Removed since first" , cm: manager) << manager << contacts << removed << ac << "" ; |
| 3052 | newMRow(tag: "Removed since second" , cm: manager) << manager << contacts << removed << bc << "" ; |
| 3053 | newMRow(tag: "Removed since third" , cm: manager) << manager << contacts << removed << cc << "" ; |
| 3054 | newMRow(tag: "Removed since fourth" , cm: manager) << manager << contacts << removed << dc << "" ; |
| 3055 | newMRow(tag: "Removed since after fourth" , cm: manager) << manager << contacts << removed << dc.addSecs(secs: 1) << "" ; |
| 3056 | } |
| 3057 | } |
| 3058 | |
| 3059 | void tst_QContactManagerFiltering::changelogFiltering() |
| 3060 | { |
| 3061 | QFETCH(int, eventType); |
| 3062 | QFETCH(QDateTime, since); |
| 3063 | QFETCH(QString, expected); |
| 3064 | QFETCH(QContactManager*, cm); |
| 3065 | QFETCH(QList<QContactId>, contacts); |
| 3066 | |
| 3067 | QList<QContactId> ids; |
| 3068 | |
| 3069 | QContactChangeLogFilter clf((QContactChangeLogFilter::EventType)eventType); |
| 3070 | clf.setSince(since); |
| 3071 | |
| 3072 | ids = cm->contactIds(filter: clf); |
| 3073 | |
| 3074 | QString output = convertIds(allIds: contacts, ids, minimumContact: 'a', maximumContact: 'g'); // don't include the convenience filtering contacts |
| 3075 | QCOMPARE(output, expected); // unsorted? or sorted? |
| 3076 | } |
| 3077 | |
| 3078 | QList<QContactId> tst_QContactManagerFiltering::prepareModel(QContactManager *cm) |
| 3079 | { |
| 3080 | // Sleep between contact additions to allow change log filtering to differentiate contacts by timestamp |
| 3081 | // Assume 1-second resolution or better |
| 3082 | const int napTime = 1000; |
| 3083 | |
| 3084 | QMap<QString, QPair<QContactDetail::DetailType, int> > definitionDetails; |
| 3085 | definitionDetails.insert(akey: "String" , avalue: qMakePair(x: QContactGuid::Type, y: static_cast<int>(QContactGuid::FieldGuid))); |
| 3086 | definitionDetails.insert(akey: "Integer" , avalue: qMakePair(x: QContactPresence::Type, y: static_cast<int>(QContactPresence::FieldPresenceState))); |
| 3087 | definitionDetails.insert(akey: "DateTime" , avalue: qMakePair(x: QContactAnniversary::Type, y: static_cast<int>(QContactAnniversary::FieldOriginalDate))); |
| 3088 | definitionDetails.insert(akey: "Date" , avalue: qMakePair(x: QContactBirthday::Type, y: static_cast<int>(QContactBirthday::FieldBirthday))); |
| 3089 | definitionDetails.insert(akey: "Bool" , avalue: qMakePair(x: QContactFavorite::Type, y: static_cast<int>(QContactFavorite::FieldFavorite))); |
| 3090 | definitionDetails.insert(akey: "Double" , avalue: qMakePair(x: QContactDetail::TypeGeoLocation, y: static_cast<int>(QContactGeoLocation::FieldLatitude))); |
| 3091 | // Currently unused: |
| 3092 | definitionDetails.insert(akey: "LongLong" , avalue: qMakePair(x: QContactDetail::TypeUndefined, y: -1)); |
| 3093 | definitionDetails.insert(akey: "ULongLong" , avalue: qMakePair(x: QContactDetail::TypeUndefined, y: -1)); |
| 3094 | definitionDetails.insert(akey: "Time" , avalue: qMakePair(x: QContactDetail::TypeUndefined, y: -1)); |
| 3095 | definitionDetails.insert(akey: "UInt" , avalue: qMakePair(x: QContactDetail::TypeUndefined, y: -1)); |
| 3096 | definitionDetails.insert(akey: "Char" , avalue: qMakePair(x: QContactDetail::TypeUndefined, y: -1)); |
| 3097 | |
| 3098 | defAndFieldNamesForTypePerManager.insert(akey: cm, avalue: definitionDetails); |
| 3099 | |
| 3100 | /* Add some contacts */ |
| 3101 | QContact contactA, contactB, contactC, contactD; |
| 3102 | QContactName name; |
| 3103 | QContactPhoneNumber number; |
| 3104 | |
| 3105 | // Create details for each relevant value type |
| 3106 | QContactDetail stringDetail(definitionDetails.value(akey: "String" ).first); |
| 3107 | QContactDetail integerDetail(definitionDetails.value(akey: "Integer" ).first); |
| 3108 | QContactDetail datetimeDetail(definitionDetails.value(akey: "DateTime" ).first); |
| 3109 | QContactDetail doubleDetail(definitionDetails.value(akey: "Double" ).first); |
| 3110 | QContactDetail boolDetail(definitionDetails.value(akey: "Bool" ).first); |
| 3111 | QContactDetail longlongDetail(definitionDetails.value(akey: "LongLong" ).first); |
| 3112 | QContactDetail ulonglongDetail(definitionDetails.value(akey: "ULongLong" ).first); |
| 3113 | QContactDetail dateDetail(definitionDetails.value(akey: "Date" ).first); |
| 3114 | QContactDetail timeDetail(definitionDetails.value(akey: "Time" ).first); |
| 3115 | QContactDetail uintDetail(definitionDetails.value(akey: "UInt" ).first); |
| 3116 | QContactDetail charDetail(definitionDetails.value(akey: "Char" ).first); |
| 3117 | |
| 3118 | name.setFirstName("Aaron" ); |
| 3119 | name.setLastName("Aaronson" ); |
| 3120 | name.setMiddleName("Arne" ); |
| 3121 | name.setPrefix("Sir" ); |
| 3122 | name.setSuffix("Dr." ); |
| 3123 | QContactNickname nick; |
| 3124 | nick.setNickname("Sir Aaron" ); |
| 3125 | QContactEmailAddress emailAddr; |
| 3126 | emailAddr.setEmailAddress("Aaron@Aaronson.com" ); |
| 3127 | number.setNumber("5551212" ); |
| 3128 | stringDetail.setValue(field: definitionDetails.value(akey: "String" ).second, value: "Aaron Aaronson" ); |
| 3129 | integerDetail.setValue(field: definitionDetails.value(akey: "Integer" ).second, value: 10); |
| 3130 | datetimeDetail.setValue(field: definitionDetails.value(akey: "DateTime" ).second, value: QDateTime(QDate(2009, 06, 29), QTime(16, 52, 23, 0))); |
| 3131 | boolDetail.setValue(field: definitionDetails.value(akey: "Bool" ).second, value: true); |
| 3132 | ulonglongDetail.setValue(field: definitionDetails.value(akey: "ULongLong" ).second, value: (qulonglong)120000000000LL); // 120B |
| 3133 | dateDetail.setValue(field: definitionDetails.value(akey: "Date" ).second, value: QDate(1988, 1, 26)); |
| 3134 | timeDetail.setValue(field: definitionDetails.value(akey: "Time" ).second, value: QTime(16,52,23,0)); |
| 3135 | |
| 3136 | contactA.saveDetail(detail: &name); |
| 3137 | contactA.saveDetail(detail: &nick); |
| 3138 | contactA.saveDetail(detail: &emailAddr); |
| 3139 | contactA.saveDetail(detail: &number); |
| 3140 | if (validDetailField(pair: definitionDetails.value(akey: "String" ))) |
| 3141 | contactA.saveDetail(detail: &stringDetail); |
| 3142 | if (validDetailField(pair: definitionDetails.value(akey: "Integer" ))) |
| 3143 | contactA.saveDetail(detail: &integerDetail); |
| 3144 | if (validDetailField(pair: definitionDetails.value(akey: "DateTime" ))) |
| 3145 | contactA.saveDetail(detail: &datetimeDetail); |
| 3146 | if (validDetailField(pair: definitionDetails.value(akey: "Bool" ))) |
| 3147 | contactA.saveDetail(detail: &boolDetail); |
| 3148 | if (validDetailField(pair: definitionDetails.value(akey: "ULongLong" ))) |
| 3149 | contactA.saveDetail(detail: &ulonglongDetail); |
| 3150 | if (validDetailField(pair: definitionDetails.value(akey: "Date" ))) |
| 3151 | contactA.saveDetail(detail: &dateDetail); |
| 3152 | if (validDetailField(pair: definitionDetails.value(akey: "Time" ))) |
| 3153 | contactA.saveDetail(detail: &timeDetail); |
| 3154 | |
| 3155 | name = QContactName(); |
| 3156 | name.setFirstName("Bob" ); |
| 3157 | name.setLastName("Aaronsen" ); |
| 3158 | nick.setNickname("Sir Bob" ); |
| 3159 | number.setNumber("5553456" ); |
| 3160 | stringDetail.setValue(field: definitionDetails.value(akey: "String" ).second, value: "Bob Aaronsen" ); |
| 3161 | integerDetail.setValue(field: definitionDetails.value(akey: "Integer" ).second, value: 20); |
| 3162 | doubleDetail.setValue(field: definitionDetails.value(akey: "Double" ).second, value: 4.0); |
| 3163 | boolDetail.setValue(field: definitionDetails.value(akey: "Bool" ).second, value: false); |
| 3164 | ulonglongDetail.setValue(field: definitionDetails.value(akey: "ULongLong" ).second, value: (qulonglong) 80000000000LL); // 80B |
| 3165 | uintDetail.setValue(field: definitionDetails.value(akey: "UInt" ).second, value: 4000000000u); // 4B |
| 3166 | dateDetail.setValue(field: definitionDetails.value(akey: "Date" ).second, value: QDate(2492, 5, 5)); |
| 3167 | timeDetail.setValue(field: definitionDetails.value(akey: "Time" ).second, value: QTime(15,52,23,0)); |
| 3168 | charDetail.setValue(field: definitionDetails.value(akey: "Char" ).second, value: QVariant(QChar('b'))); |
| 3169 | |
| 3170 | contactB.saveDetail(detail: &name); |
| 3171 | contactB.saveDetail(detail: &nick); |
| 3172 | contactB.saveDetail(detail: &number); |
| 3173 | if (validDetailField(pair: definitionDetails.value(akey: "String" ))) |
| 3174 | contactB.saveDetail(detail: &stringDetail); |
| 3175 | if (validDetailField(pair: definitionDetails.value(akey: "Integer" ))) |
| 3176 | contactB.saveDetail(detail: &integerDetail); |
| 3177 | if (validDetailField(pair: definitionDetails.value(akey: "Double" ))) |
| 3178 | contactB.saveDetail(detail: &doubleDetail); |
| 3179 | if (validDetailField(pair: definitionDetails.value(akey: "Bool" ))) |
| 3180 | contactB.saveDetail(detail: &boolDetail); |
| 3181 | if (validDetailField(pair: definitionDetails.value(akey: "ULongLong" ))) |
| 3182 | contactB.saveDetail(detail: &ulonglongDetail); |
| 3183 | if (validDetailField(pair: definitionDetails.value(akey: "UInt" ))) |
| 3184 | contactB.saveDetail(detail: &uintDetail); |
| 3185 | if (validDetailField(pair: definitionDetails.value(akey: "Date" ))) |
| 3186 | contactB.saveDetail(detail: &dateDetail); |
| 3187 | if (validDetailField(pair: definitionDetails.value(akey: "Time" ))) |
| 3188 | contactB.saveDetail(detail: &timeDetail); |
| 3189 | if (validDetailField(pair: definitionDetails.value(akey: "Char" ))) |
| 3190 | contactB.saveDetail(detail: &charDetail); |
| 3191 | |
| 3192 | name.setFirstName("Boris" ); |
| 3193 | name.setLastName("Aaronsun" ); |
| 3194 | stringDetail.setValue(field: definitionDetails.value(akey: "String" ).second, value: "Boris Aaronsun" ); |
| 3195 | integerDetail.setValue(field: definitionDetails.value(akey: "Integer" ).second, value: -20); |
| 3196 | datetimeDetail.setValue(field: definitionDetails.value(akey: "DateTime" ).second, value: QDateTime(QDate(2009, 06, 29), QTime(16, 54, 17, 0))); |
| 3197 | longlongDetail.setValue(field: definitionDetails.value(akey: "LongLong" ).second, value: (qlonglong)8000000000LL); // 8B |
| 3198 | charDetail.setValue(field: definitionDetails.value(akey: "Char" ).second, value: QVariant(QChar('c'))); |
| 3199 | |
| 3200 | contactC.saveDetail(detail: &name); |
| 3201 | if (validDetailField(pair: definitionDetails.value(akey: "String" ))) |
| 3202 | contactC.saveDetail(detail: &stringDetail); |
| 3203 | if (validDetailField(pair: definitionDetails.value(akey: "Integer" ))) |
| 3204 | contactC.saveDetail(detail: &integerDetail); |
| 3205 | if (validDetailField(pair: definitionDetails.value(akey: "DateTime" ))) |
| 3206 | contactC.saveDetail(detail: &datetimeDetail); |
| 3207 | if (validDetailField(pair: definitionDetails.value(akey: "Double" ))) |
| 3208 | contactC.saveDetail(detail: &doubleDetail); |
| 3209 | if (validDetailField(pair: definitionDetails.value(akey: "Bool" ))) |
| 3210 | contactC.saveDetail(detail: &boolDetail); |
| 3211 | if (validDetailField(pair: definitionDetails.value(akey: "LongLong" ))) |
| 3212 | contactC.saveDetail(detail: &longlongDetail); |
| 3213 | if (validDetailField(pair: definitionDetails.value(akey: "ULongLong" ))) |
| 3214 | contactC.saveDetail(detail: &ulonglongDetail); |
| 3215 | if (validDetailField(pair: definitionDetails.value(akey: "Char" ))) |
| 3216 | contactC.saveDetail(detail: &charDetail); |
| 3217 | |
| 3218 | name.setFirstName("Dennis" ); |
| 3219 | name.setLastName("FitzMacintyre" ); |
| 3220 | stringDetail.setValue(field: definitionDetails.value(akey: "String" ).second, value: "Dennis FitzMacintyre" ); |
| 3221 | doubleDetail.setValue(field: definitionDetails.value(akey: "Double" ).second, value: -128.0); |
| 3222 | longlongDetail.setValue(field: definitionDetails.value(akey: "LongLong" ).second, value: (qlonglong)-14000000000LL); |
| 3223 | uintDetail.setValue(field: definitionDetails.value(akey: "UInt" ).second, value: 3000000000u); // 3B |
| 3224 | dateDetail.setValue(field: definitionDetails.value(akey: "Date" ).second, value: QDate(2770, 10, 1)); |
| 3225 | |
| 3226 | contactD.saveDetail(detail: &name); |
| 3227 | if (validDetailField(pair: definitionDetails.value(akey: "String" ))) |
| 3228 | contactD.saveDetail(detail: &stringDetail); |
| 3229 | if (validDetailField(pair: definitionDetails.value(akey: "Double" ))) |
| 3230 | contactD.saveDetail(detail: &doubleDetail); |
| 3231 | if (validDetailField(pair: definitionDetails.value(akey: "LongLong" ))) |
| 3232 | contactD.saveDetail(detail: &longlongDetail); |
| 3233 | if (validDetailField(pair: definitionDetails.value(akey: "UInt" ))) |
| 3234 | contactD.saveDetail(detail: &uintDetail); |
| 3235 | if (validDetailField(pair: definitionDetails.value(akey: "Date" ))) |
| 3236 | contactD.saveDetail(detail: &dateDetail); |
| 3237 | |
| 3238 | qDebug() << "Generating contacts with different timestamps, please wait.." ; |
| 3239 | int originalContactCount = cm->contactIds().count(); |
| 3240 | bool successfulSave = cm->saveContact(contact: &contactA); |
| 3241 | Q_FATAL_VERIFY(successfulSave); |
| 3242 | QTest::qSleep(ms: napTime); |
| 3243 | successfulSave = cm->saveContact(contact: &contactB); |
| 3244 | Q_FATAL_VERIFY(successfulSave); |
| 3245 | QTest::qSleep(ms: napTime); |
| 3246 | successfulSave = cm->saveContact(contact: &contactC); |
| 3247 | Q_FATAL_VERIFY(successfulSave); |
| 3248 | QTest::qSleep(ms: napTime); |
| 3249 | successfulSave = cm->saveContact(contact: &contactD); |
| 3250 | Q_FATAL_VERIFY(successfulSave); |
| 3251 | QTest::qSleep(ms: napTime); |
| 3252 | |
| 3253 | /* Now add some contacts specifically for multisorting */ |
| 3254 | QContact contactE,contactF,contactG; |
| 3255 | QContactName n; |
| 3256 | n.setFirstName("John" ); |
| 3257 | n.setLastName("Smithee" ); |
| 3258 | stringDetail.setValue(field: definitionDetails.value(akey: "String" ).second, value: "" ); |
| 3259 | if (validDetailField(pair: definitionDetails.value(akey: "String" ))) |
| 3260 | contactE.saveDetail(detail: &stringDetail); |
| 3261 | contactE.saveDetail(detail: &n); |
| 3262 | n = QContactName(); |
| 3263 | n.setFirstName("John" ); |
| 3264 | n.setLastName("Smithey" ); |
| 3265 | contactF.saveDetail(detail: &n); |
| 3266 | n = QContactName(); |
| 3267 | n.setFirstName("John" ); |
| 3268 | n.setLastName("Smithy" ); |
| 3269 | stringDetail.setValue(field: definitionDetails.value(akey: "String" ).second, value: "zzz" ); |
| 3270 | if (validDetailField(pair: definitionDetails.value(akey: "String" ))) |
| 3271 | contactG.saveDetail(detail: &stringDetail); |
| 3272 | contactG.saveDetail(detail: &n); |
| 3273 | successfulSave = cm->saveContact(contact: &contactE); |
| 3274 | Q_FATAL_VERIFY(successfulSave); |
| 3275 | successfulSave = cm->saveContact(contact: &contactF); |
| 3276 | Q_FATAL_VERIFY(successfulSave); |
| 3277 | successfulSave = cm->saveContact(contact: &contactG); |
| 3278 | Q_FATAL_VERIFY(successfulSave); |
| 3279 | originalContactCount += 7; |
| 3280 | Q_FATAL_VERIFY(cm->contactIds().count() == originalContactCount); |
| 3281 | |
| 3282 | /* Now some for the locale aware sorting */ |
| 3283 | /* In the C locale, all lowercase chars sort after uppercase */ |
| 3284 | QContact contactH, contactI, contactJ, contactK; |
| 3285 | QContactName n2; |
| 3286 | n2.setFirstName("xander" ); |
| 3287 | contactH.saveDetail(detail: &n2); |
| 3288 | n2.setFirstName("Xander" ); |
| 3289 | contactI.saveDetail(detail: &n2); |
| 3290 | n2.setFirstName("yarrow" ); |
| 3291 | contactJ.saveDetail(detail: &n2); |
| 3292 | n2.setFirstName("Yarrow" ); |
| 3293 | contactK.saveDetail(detail: &n2); |
| 3294 | |
| 3295 | Q_FATAL_VERIFY(cm->saveContact(&contactH)); |
| 3296 | Q_FATAL_VERIFY(cm->saveContact(&contactI)); |
| 3297 | Q_FATAL_VERIFY(cm->saveContact(&contactJ)); |
| 3298 | Q_FATAL_VERIFY(cm->saveContact(&contactK)); |
| 3299 | |
| 3300 | /* Ensure the last modified times are different */ |
| 3301 | QTest::qSleep(ms: napTime); |
| 3302 | QContactName modifiedName = contactC.detail(type: QContactName::Type); |
| 3303 | contactC.saveDetail(detail: &modifiedName); |
| 3304 | cm->saveContact(contact: &contactC); |
| 3305 | QTest::qSleep(ms: napTime); |
| 3306 | modifiedName = contactB.detail(type: QContactName::Type); |
| 3307 | contactB.saveDetail(detail: &modifiedName); |
| 3308 | cm->saveContact(contact: &contactB); |
| 3309 | QTest::qSleep(ms: napTime); |
| 3310 | modifiedName = contactA.detail(type: QContactName::Type); |
| 3311 | contactA.saveDetail(detail: &modifiedName); |
| 3312 | cm->saveContact(contact: &contactA); |
| 3313 | QTest::qSleep(ms: napTime); |
| 3314 | |
| 3315 | /* Now some for convenience filtering */ |
| 3316 | QList<QContactDetail::DetailType> allTypes = cm->supportedContactDetailTypes(); |
| 3317 | // Contact L ---------------------------------------- |
| 3318 | QContact contactL; |
| 3319 | if (allTypes.contains(t: QContactAddress::Type)) { |
| 3320 | QContactAddress ladr; |
| 3321 | ladr.setStreet("streetstring road" ); // Contact L matches streetstring. |
| 3322 | ladr.setLocality("testplace" ); |
| 3323 | ladr.setRegion("somewhere" ); |
| 3324 | contactL.saveDetail(detail: &ladr); |
| 3325 | } |
| 3326 | if (allTypes.contains(t: QContactEmailAddress::Type)) { |
| 3327 | QContactEmailAddress led; |
| 3328 | led.setEmailAddress("frad@test.domain" ); |
| 3329 | contactL.saveDetail(detail: &led); |
| 3330 | } |
| 3331 | if (allTypes.contains(t: QContactPhoneNumber::Type)) { |
| 3332 | QContactPhoneNumber lp; |
| 3333 | lp.setNumber("11111" ); |
| 3334 | contactL.saveDetail(detail: &lp); |
| 3335 | } |
| 3336 | if (allTypes.contains(t: QContactName::Type)) { |
| 3337 | QContactName ln; |
| 3338 | ln.setFirstName("Fradarick" ); |
| 3339 | ln.setLastName("Gumboots" ); |
| 3340 | contactL.saveDetail(detail: &ln); |
| 3341 | } |
| 3342 | if (allTypes.contains(t: QContactTag::Type)) { |
| 3343 | QContactTag lt; |
| 3344 | lt.setTag("Soccer" ); |
| 3345 | contactL.saveDetail(detail: <); |
| 3346 | } |
| 3347 | // Contact M ---------------------------------------- |
| 3348 | QContact contactM; |
| 3349 | if (allTypes.contains(t: QContactAddress::Type)) { |
| 3350 | QContactAddress madr; |
| 3351 | madr.setStreet("some road" ); |
| 3352 | madr.setLocality("testplace" ); |
| 3353 | madr.setRegion("somewhere" ); |
| 3354 | contactM.saveDetail(detail: &madr); |
| 3355 | } |
| 3356 | if (allTypes.contains(t: QContactEmailAddress::Type)) { |
| 3357 | QContactEmailAddress med; |
| 3358 | med.setEmailAddress("frbd@test.com" ); // Contact M matches @test.com |
| 3359 | contactM.saveDetail(detail: &med); |
| 3360 | } |
| 3361 | if (allTypes.contains(t: QContactPhoneNumber::Type)) { |
| 3362 | QContactPhoneNumber mp; |
| 3363 | mp.setNumber("22222" ); |
| 3364 | contactM.saveDetail(detail: &mp); |
| 3365 | } |
| 3366 | if (allTypes.contains(t: QContactName::Type)) { |
| 3367 | QContactName mn; |
| 3368 | mn.setFirstName("Frbdbrick" ); |
| 3369 | mn.setLastName("Gumboots" ); |
| 3370 | contactM.saveDetail(detail: &mn); |
| 3371 | } |
| 3372 | if (allTypes.contains(t: QContactTag::Type)) { |
| 3373 | QContactTag mt; |
| 3374 | mt.setTag("Soccer" ); |
| 3375 | contactM.saveDetail(detail: &mt); |
| 3376 | } |
| 3377 | // Contact N ---------------------------------------- |
| 3378 | QContact contactN; |
| 3379 | if (allTypes.contains(t: QContactAddress::Type)) { |
| 3380 | QContactAddress nadr; |
| 3381 | nadr.setStreet("some road" ); |
| 3382 | nadr.setLocality("testplace" ); |
| 3383 | nadr.setRegion("somewhere" ); |
| 3384 | contactN.saveDetail(detail: &nadr); |
| 3385 | } |
| 3386 | if (allTypes.contains(t: QContactEmailAddress::Type)) { |
| 3387 | QContactEmailAddress ned; |
| 3388 | ned.setEmailAddress("frcd@test.domain" ); |
| 3389 | contactN.saveDetail(detail: &ned); |
| 3390 | } |
| 3391 | if (allTypes.contains(t: QContactPhoneNumber::Type)) { |
| 3392 | QContactPhoneNumber np; |
| 3393 | np.setNumber("12345" ); // Contact N matches 12345 |
| 3394 | contactN.saveDetail(detail: &np); |
| 3395 | } |
| 3396 | if (allTypes.contains(t: QContactName::Type)) { |
| 3397 | QContactName nn; |
| 3398 | nn.setFirstName("Frcdcrick" ); |
| 3399 | nn.setLastName("Gumboots" ); |
| 3400 | contactN.saveDetail(detail: &nn); |
| 3401 | } |
| 3402 | if (allTypes.contains(t: QContactTag::Type)) { |
| 3403 | QContactTag nt; |
| 3404 | nt.setTag("Soccer" ); |
| 3405 | contactN.saveDetail(detail: &nt); |
| 3406 | } |
| 3407 | // Contact O ---------------------------------------- |
| 3408 | QContact contactO; |
| 3409 | if (allTypes.contains(t: QContactAddress::Type)) { |
| 3410 | QContactAddress oadr; |
| 3411 | oadr.setStreet("some road" ); |
| 3412 | oadr.setLocality("testplace" ); |
| 3413 | oadr.setRegion("somewhere" ); |
| 3414 | contactO.saveDetail(detail: &oadr); |
| 3415 | } |
| 3416 | if (allTypes.contains(t: QContactEmailAddress::Type)) { |
| 3417 | QContactEmailAddress oed; |
| 3418 | oed.setEmailAddress("frdd@test.domain" ); |
| 3419 | contactO.saveDetail(detail: &oed); |
| 3420 | } |
| 3421 | if (allTypes.contains(t: QContactPhoneNumber::Type)) { |
| 3422 | QContactPhoneNumber op; |
| 3423 | op.setNumber("44444" ); |
| 3424 | contactO.saveDetail(detail: &op); |
| 3425 | } |
| 3426 | if (allTypes.contains(t: QContactName::Type)) { |
| 3427 | QContactName on; |
| 3428 | on.setFirstName("Freddy" ); // Contact O matches Freddy |
| 3429 | on.setLastName("Gumboots" ); |
| 3430 | contactO.saveDetail(detail: &on); |
| 3431 | } |
| 3432 | if (allTypes.contains(t: QContactTag::Type)) { |
| 3433 | QContactTag ot; |
| 3434 | ot.setTag("Soccer" ); |
| 3435 | contactO.saveDetail(detail: &ot); |
| 3436 | } |
| 3437 | // Contact P ---------------------------------------- |
| 3438 | QContact contactP; |
| 3439 | if (allTypes.contains(t: QContactAddress::Type)) { |
| 3440 | QContactAddress padr; |
| 3441 | padr.setStreet("some road" ); |
| 3442 | padr.setLocality("testplace" ); |
| 3443 | padr.setRegion("somewhere" ); |
| 3444 | contactP.saveDetail(detail: &padr); |
| 3445 | } |
| 3446 | if (allTypes.contains(t: QContactEmailAddress::Type)) { |
| 3447 | QContactEmailAddress ped; |
| 3448 | ped.setEmailAddress("fred@test.domain" ); |
| 3449 | contactP.saveDetail(detail: &ped); |
| 3450 | } |
| 3451 | if (allTypes.contains(t: QContactPhoneNumber::Type)) { |
| 3452 | QContactPhoneNumber pp; |
| 3453 | pp.setNumber("55555" ); |
| 3454 | contactP.saveDetail(detail: &pp); |
| 3455 | } |
| 3456 | if (allTypes.contains(t: QContactName::Type)) { |
| 3457 | QContactName pn; |
| 3458 | pn.setFirstName("Frederick" ); // Contact P matches Frederic (contains). |
| 3459 | pn.setLastName("Gumboots" ); |
| 3460 | contactP.saveDetail(detail: &pn); |
| 3461 | } |
| 3462 | if (allTypes.contains(t: QContactTag::Type)) { |
| 3463 | QContactTag pt; |
| 3464 | pt.setTag("Soccer" ); |
| 3465 | contactP.saveDetail(detail: &pt); |
| 3466 | } |
| 3467 | // Contact Q ---------------------------------------- |
| 3468 | QContact contactQ; |
| 3469 | if (allTypes.contains(t: QContactAddress::Type)) { |
| 3470 | QContactAddress qadr; |
| 3471 | qadr.setStreet("some road" ); |
| 3472 | qadr.setLocality("testplace" ); |
| 3473 | qadr.setRegion("somewhere" ); |
| 3474 | contactQ.saveDetail(detail: &qadr); |
| 3475 | } |
| 3476 | if (allTypes.contains(t: QContactEmailAddress::Type)) { |
| 3477 | QContactEmailAddress qed; |
| 3478 | qed.setEmailAddress("frfd@test.domain" ); |
| 3479 | contactQ.saveDetail(detail: &qed); |
| 3480 | } |
| 3481 | if (allTypes.contains(t: QContactPhoneNumber::Type)) { |
| 3482 | QContactPhoneNumber qp; |
| 3483 | qp.setNumber("66666" ); |
| 3484 | contactQ.saveDetail(detail: &qp); |
| 3485 | } |
| 3486 | if (allTypes.contains(t: QContactName::Type)) { |
| 3487 | QContactName qn; |
| 3488 | qn.setFirstName("Frfdfrick" ); |
| 3489 | qn.setLastName("Gumboots" ); |
| 3490 | contactQ.saveDetail(detail: &qn); |
| 3491 | } |
| 3492 | if (allTypes.contains(t: QContactTag::Type)) { |
| 3493 | QContactTag qt; |
| 3494 | qt.setTag("Soccer" ); |
| 3495 | contactQ.saveDetail(detail: &qt); |
| 3496 | } |
| 3497 | if (allTypes.contains(t: QContactFavorite::Type)) { |
| 3498 | QContactFavorite qf; |
| 3499 | qf.setFavorite(true); // Contact Q matches favorite = true |
| 3500 | contactQ.saveDetail(detail: &qf); |
| 3501 | } |
| 3502 | // Contact R ---------------------------------------- |
| 3503 | QContact contactR; |
| 3504 | if (allTypes.contains(t: QContactAddress::Type)) { |
| 3505 | QContactAddress radr; |
| 3506 | radr.setStreet("some road" ); |
| 3507 | radr.setLocality("testplace" ); |
| 3508 | radr.setRegion("somewhere" ); |
| 3509 | contactR.saveDetail(detail: &radr); |
| 3510 | } |
| 3511 | if (allTypes.contains(t: QContactEmailAddress::Type)) { |
| 3512 | QContactEmailAddress red; |
| 3513 | red.setEmailAddress("frgd@test.domain" ); |
| 3514 | contactR.saveDetail(detail: &red); |
| 3515 | } |
| 3516 | if (allTypes.contains(t: QContactPhoneNumber::Type)) { |
| 3517 | QContactPhoneNumber rp; |
| 3518 | rp.setNumber("77777" ); |
| 3519 | contactR.saveDetail(detail: &rp); |
| 3520 | } |
| 3521 | if (allTypes.contains(t: QContactName::Type)) { |
| 3522 | QContactName rn; |
| 3523 | rn.setFirstName("Frgdgrick" ); |
| 3524 | rn.setLastName("Gumboots" ); |
| 3525 | contactR.saveDetail(detail: &rn); |
| 3526 | } |
| 3527 | if (allTypes.contains(t: QContactTag::Type)) { |
| 3528 | QContactTag rt; |
| 3529 | rt.setTag("Football" ); // Contact R matches Football |
| 3530 | contactR.saveDetail(detail: &rt); |
| 3531 | } |
| 3532 | // --------------------- save. |
| 3533 | Q_FATAL_VERIFY(cm->saveContact(&contactL)); |
| 3534 | Q_FATAL_VERIFY(cm->saveContact(&contactM)); |
| 3535 | Q_FATAL_VERIFY(cm->saveContact(&contactN)); |
| 3536 | Q_FATAL_VERIFY(cm->saveContact(&contactO)); |
| 3537 | Q_FATAL_VERIFY(cm->saveContact(&contactP)); |
| 3538 | Q_FATAL_VERIFY(cm->saveContact(&contactQ)); |
| 3539 | Q_FATAL_VERIFY(cm->saveContact(&contactR)); |
| 3540 | // --------------------- end. |
| 3541 | |
| 3542 | /* Reload the contacts to pick up any changes */ |
| 3543 | contactA = cm->contact(contactId: contactA.id()); |
| 3544 | contactB = cm->contact(contactId: contactB.id()); |
| 3545 | contactC = cm->contact(contactId: contactC.id()); |
| 3546 | contactD = cm->contact(contactId: contactD.id()); |
| 3547 | contactE = cm->contact(contactId: contactE.id()); |
| 3548 | contactF = cm->contact(contactId: contactF.id()); |
| 3549 | contactG = cm->contact(contactId: contactG.id()); |
| 3550 | contactH = cm->contact(contactId: contactH.id()); |
| 3551 | contactI = cm->contact(contactId: contactI.id()); |
| 3552 | contactJ = cm->contact(contactId: contactJ.id()); |
| 3553 | contactK = cm->contact(contactId: contactK.id()); |
| 3554 | contactL = cm->contact(contactId: contactL.id()); |
| 3555 | contactM = cm->contact(contactId: contactM.id()); |
| 3556 | contactN = cm->contact(contactId: contactN.id()); |
| 3557 | contactO = cm->contact(contactId: contactO.id()); |
| 3558 | contactP = cm->contact(contactId: contactP.id()); |
| 3559 | contactQ = cm->contact(contactId: contactQ.id()); |
| 3560 | contactR = cm->contact(contactId: contactR.id()); |
| 3561 | |
| 3562 | QList<QContactId> list; |
| 3563 | |
| 3564 | /* Add our newly saved contacts to our internal list of added contacts */ |
| 3565 | foreach (const QContactId &id, (QList<QContactId>() << contactR.id() |
| 3566 | << contactQ.id() |
| 3567 | << contactP.id() |
| 3568 | << contactO.id() |
| 3569 | << contactN.id() |
| 3570 | << contactM.id() |
| 3571 | << contactL.id() |
| 3572 | << contactK.id() |
| 3573 | << contactJ.id() |
| 3574 | << contactI.id() |
| 3575 | << contactH.id() |
| 3576 | << contactG.id() |
| 3577 | << contactF.id() |
| 3578 | << contactE.id() |
| 3579 | << contactD.id() |
| 3580 | << contactC.id() |
| 3581 | << contactB.id() |
| 3582 | << contactA.id())) { |
| 3583 | if (!id.isNull()) { |
| 3584 | contactsAddedToManagers.insert(akey: cm, avalue: id); |
| 3585 | list.prepend(t: id); |
| 3586 | } |
| 3587 | } |
| 3588 | |
| 3589 | return list; |
| 3590 | } |
| 3591 | |
| 3592 | /* ============ Utility functions ============= */ |
| 3593 | |
| 3594 | void tst_QContactManagerFiltering::dumpContactDifferences(const QContact& ca, const QContact& cb) |
| 3595 | { |
| 3596 | // Try to narrow down the differences |
| 3597 | QContact a(ca); |
| 3598 | QContact b(cb); |
| 3599 | |
| 3600 | QContactName n1 = a.detail(type: QContactName::Type); |
| 3601 | QContactName n2 = b.detail(type: QContactName::Type); |
| 3602 | |
| 3603 | // Check the name components in more detail |
| 3604 | QCOMPARE(n1.firstName(), n2.firstName()); |
| 3605 | QCOMPARE(n1.middleName(), n2.middleName()); |
| 3606 | QCOMPARE(n1.lastName(), n2.lastName()); |
| 3607 | QCOMPARE(n1.prefix(), n2.prefix()); |
| 3608 | QCOMPARE(n1.suffix(), n2.suffix()); |
| 3609 | |
| 3610 | // Check the display label |
| 3611 | QCOMPARE(a.detail<QContactDisplayLabel>().label(), b.detail<QContactDisplayLabel>().label()); |
| 3612 | |
| 3613 | // Now look at the rest |
| 3614 | QList<QContactDetail> aDetails = a.details(); |
| 3615 | QList<QContactDetail> bDetails = b.details(); |
| 3616 | |
| 3617 | // They can be in any order, so loop |
| 3618 | // First remove any matches |
| 3619 | foreach(QContactDetail d, aDetails) { |
| 3620 | foreach(QContactDetail d2, bDetails) { |
| 3621 | if(d == d2) { |
| 3622 | a.removeDetail(detail: &d); |
| 3623 | b.removeDetail(detail: &d2); |
| 3624 | break; |
| 3625 | } |
| 3626 | } |
| 3627 | } |
| 3628 | |
| 3629 | // Now dump the extra details that were unmatched in A |
| 3630 | aDetails = a.details(); |
| 3631 | bDetails = b.details(); |
| 3632 | foreach(QContactDetail d, aDetails) { |
| 3633 | if (d.type() != QContactDisplayLabel::Type) |
| 3634 | qDebug() << "A contact had extra detail:" << d.type() << d.values(); |
| 3635 | } |
| 3636 | // and same for B |
| 3637 | foreach(QContactDetail d, bDetails) { |
| 3638 | if (d.type() != QContactDisplayLabel::Type) |
| 3639 | qDebug() << "B contact had extra detail:" << d.type() << d.values(); |
| 3640 | } |
| 3641 | |
| 3642 | QCOMPARE(b, a); |
| 3643 | } |
| 3644 | |
| 3645 | bool tst_QContactManagerFiltering::isSuperset(const QContact& ca, const QContact& cb) |
| 3646 | { |
| 3647 | // returns true if contact ca is a superset of contact cb |
| 3648 | // we use this test instead of equality because dynamic information |
| 3649 | // such as presence/location, and synthesised information such as |
| 3650 | // display label and (possibly) type, may differ between a contact |
| 3651 | // in memory and the contact in the managed store. |
| 3652 | |
| 3653 | QContact a(ca); |
| 3654 | QContact b(cb); |
| 3655 | QList<QContactDetail> aDetails = a.details(); |
| 3656 | QList<QContactDetail> bDetails = b.details(); |
| 3657 | |
| 3658 | // They can be in any order, so loop |
| 3659 | // First remove any matches |
| 3660 | foreach(QContactDetail d, aDetails) { |
| 3661 | foreach(QContactDetail d2, bDetails) { |
| 3662 | if(d == d2) { |
| 3663 | a.removeDetail(detail: &d); |
| 3664 | b.removeDetail(detail: &d2); |
| 3665 | break; |
| 3666 | } |
| 3667 | } |
| 3668 | } |
| 3669 | |
| 3670 | // check for contact type updates |
| 3671 | if (a.type() != b.type()) |
| 3672 | return false; // nonempty type is different. |
| 3673 | |
| 3674 | // Now check to see if b has any details remaining; if so, a is not a superset. |
| 3675 | // Note that the DisplayLabel and Type can never be removed. |
| 3676 | if (b.details().size() > 2 |
| 3677 | || (b.details().size() == 2 && (b.details().value(i: 0).type() != QContactDisplayLabel::Type |
| 3678 | || b.details().value(i: 1).type() != QContactType::Type))) |
| 3679 | return false; |
| 3680 | return true; |
| 3681 | } |
| 3682 | |
| 3683 | void tst_QContactManagerFiltering::dumpContact(const QContact& contact) |
| 3684 | { |
| 3685 | QContactManager m; |
| 3686 | qDebug() << "Contact: " << contact.id() << "(" << contact.detail<QContactDisplayLabel>().label() << ")" ; |
| 3687 | QList<QContactDetail> details = contact.details(); |
| 3688 | foreach(QContactDetail d, details) { |
| 3689 | qDebug() << " " << d.type() << ":" ; |
| 3690 | qDebug() << " Vals:" << d.values(); |
| 3691 | } |
| 3692 | } |
| 3693 | |
| 3694 | void tst_QContactManagerFiltering::dumpContacts() |
| 3695 | { |
| 3696 | QContactManager m; |
| 3697 | QList<QContactId> ids = m.contactIds(); |
| 3698 | |
| 3699 | foreach(QContactId id, ids) { |
| 3700 | QContact c = m.contact(contactId: id); |
| 3701 | dumpContact(contact: c); |
| 3702 | } |
| 3703 | } |
| 3704 | |
| 3705 | QTEST_MAIN(tst_QContactManagerFiltering) |
| 3706 | #include "tst_qcontactmanagerfiltering.moc" |
| 3707 | #include "qcontactmanager.h" |
| 3708 | |