File indexing completed on 2024-06-09 04:23:55

0001 /*
0002  * SPDX-FileCopyrightText: 2020 boud <boud@valdyas.org>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 #include "TestTagResourceModel.h"
0007 
0008 #include <simpletest.h>
0009 #include <QStandardPaths>
0010 #include <QDir>
0011 #include <QVersionNumber>
0012 #include <QDirIterator>
0013 #include <QSqlError>
0014 #include <QSqlQuery>
0015 #include <QAbstractItemModelTester>
0016 
0017 #include <kconfig.h>
0018 #include <kconfiggroup.h>
0019 #include <ksharedconfig.h>
0020 
0021 #include <KisResourceCacheDb.h>
0022 #include <KisResourceLocator.h>
0023 #include <KisResourceModel.h>
0024 #include <KisTagModel.h>
0025 #include <KisTagResourceModel.h>
0026 #include <KisResourceTypes.h>
0027 
0028 #include <DummyResource.h>
0029 #include <ResourceTestHelper.h>
0030 
0031 #ifndef FILES_DATA_DIR
0032 #error "FILES_DATA_DIR not set. A directory with the data used for testing installing resources"
0033 #endif
0034 
0035 
0036 void TestTagResourceModel::initTestCase()
0037 {
0038     ResourceTestHelper::initTestDb();
0039     ResourceTestHelper::createDummyLoaderRegistry();
0040 
0041     m_srcLocation = QString(FILES_DATA_DIR);
0042     QVERIFY2(QDir(m_srcLocation).exists(), m_srcLocation.toUtf8());
0043 
0044     m_dstLocation = ResourceTestHelper::filesDestDir();
0045     ResourceTestHelper::cleanDstLocation(m_dstLocation);
0046 
0047     KConfigGroup cfg(KSharedConfig::openConfig(), "");
0048     cfg.writeEntry(KisResourceLocator::resourceLocationKey, m_dstLocation);
0049 
0050     m_locator = KisResourceLocator::instance();
0051 
0052     if (!KisResourceCacheDb::initialize(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation))) {
0053         qDebug() << "Could not initialize KisResourceCacheDb on" << QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
0054     }
0055     QVERIFY(KisResourceCacheDb::isValid());
0056 
0057     KisResourceLocator::LocatorError r = m_locator->initialize(m_srcLocation);
0058     if (!m_locator->errorMessages().isEmpty()) qDebug() << m_locator->errorMessages();
0059 
0060     QVERIFY(r == KisResourceLocator::LocatorError::Ok);
0061     QVERIFY(QDir(m_dstLocation).exists());
0062 }
0063 
0064 void TestTagResourceModel::testWithTagModelTester()
0065 {
0066     KisAllTagResourceModel model(ResourceType::PaintOpPresets);
0067     auto tester = new QAbstractItemModelTester(&model);
0068     Q_UNUSED(tester);
0069 }
0070 
0071 
0072 void TestTagResourceModel::testRowCount()
0073 {
0074     QSqlQuery q;
0075     QVERIFY(q.prepare("SELECT count(*)\n"
0076                       "FROM   resource_tags\n"
0077                       "WHERE  resource_tags.active = 1\n"));
0078     QVERIFY(q.exec());
0079     q.first();
0080     int rowCount = q.value(0).toInt();
0081     QCOMPARE(rowCount, 2);
0082 
0083     KisAllTagResourceModel tagResourceModel(ResourceType::PaintOpPresets);
0084     QCOMPARE(tagResourceModel.rowCount(), rowCount);
0085 }
0086 
0087 bool testDataInColumnAndRole(KisAllTagResourceModel &tagResourceModel, int columnRole)
0088 {
0089     QModelIndex idx = tagResourceModel.index(0, columnRole);
0090     QVariant data1 = tagResourceModel.data(idx, Qt::DisplayRole);
0091 
0092     idx = tagResourceModel.index(0, 0);
0093     QVariant data2 = tagResourceModel.data(idx, Qt::UserRole + columnRole);
0094     bool success = data1 == data2;
0095     if (!success) {
0096         qInfo() << "Column: " << columnRole << "Data from column: " << data1 << "Data from role: " << data2;
0097     }
0098     return success;
0099 }
0100 
0101 bool testDataInColumnAndRole(KisAllTagResourceModel &tagResourceModel, int columnRole, QVariant expected)
0102 {
0103     QModelIndex idx = tagResourceModel.index(0, columnRole);
0104     QVariant data = tagResourceModel.data(idx, Qt::DisplayRole);
0105     bool columnSuccess = data == expected;
0106     if (!columnSuccess) {
0107         qInfo() << "Column: " << columnRole << "Expected: " << expected << "Actual: " << data;
0108     }
0109 
0110     idx = tagResourceModel.index(0, 0);
0111     data = tagResourceModel.data(idx, Qt::UserRole + columnRole);
0112     bool roleSuccess = data == expected;
0113     if (!roleSuccess) {
0114         qInfo() << "Column: " << columnRole << "Expected: " << expected << "Actual: " << data;
0115     }
0116     return columnSuccess && roleSuccess;
0117 
0118 }
0119 
0120 void TestTagResourceModel::testData()
0121 {
0122      KisAllTagResourceModel tagResourceModel(ResourceType::PaintOpPresets);
0123      QModelIndex idx = tagResourceModel.index(0, 0);
0124      QVERIFY(idx.isValid());
0125 
0126      // *** columns from ResourceModel, via ResourceQueryMapper *** //
0127     QVERIFY(testDataInColumnAndRole(tagResourceModel, KisAbstractResourceModel::Id, 3));
0128     QVERIFY(testDataInColumnAndRole(tagResourceModel, KisAbstractResourceModel::StorageId, 1));
0129     QVERIFY(testDataInColumnAndRole(tagResourceModel, KisAbstractResourceModel::Name, "test0.kpp"));
0130     QVERIFY(testDataInColumnAndRole(tagResourceModel, KisAbstractResourceModel::Filename, "test0.kpp"));
0131     QVERIFY(testDataInColumnAndRole(tagResourceModel, KisAbstractResourceModel::Tooltip, "test0.kpp"));
0132 
0133     // Thumbnail -- without checking the value, just if both are the same
0134     QVERIFY(testDataInColumnAndRole(tagResourceModel, KisAbstractResourceModel::Thumbnail));
0135     // Status -- skip
0136 
0137     QVERIFY(testDataInColumnAndRole(tagResourceModel, KisAbstractResourceModel::Location, ""));
0138     QVERIFY(testDataInColumnAndRole(tagResourceModel, KisAbstractResourceModel::ResourceType, ResourceType::PaintOpPresets));
0139 
0140     // Tags -- only in role; there is no column like that, the result in QVariant()
0141     QStringList tagList = tagResourceModel.data(idx, Qt::UserRole + KisAbstractResourceModel::Tags).value<QStringList>();
0142     QCOMPARE(tagList.count(), 1);
0143     QCOMPARE(tagList[0], "* Favorites");
0144 
0145     // Large Thumbnail -- without checking the value, just if both are the same
0146     QVERIFY(testDataInColumnAndRole(tagResourceModel, KisAbstractResourceModel::LargeThumbnail));
0147 
0148     QVERIFY(testDataInColumnAndRole(tagResourceModel, KisAbstractResourceModel::Dirty, false));
0149 
0150     // MetaData -- only in role; there is no column like that, the result in QVariant()
0151     QMap<QString, QVariant> metadata = tagResourceModel.data(idx, Qt::UserRole + KisAbstractResourceModel::MetaData).value<QMap<QString, QVariant>>();
0152     QCOMPARE(metadata.count(), 0);
0153 
0154     QVERIFY(testDataInColumnAndRole(tagResourceModel, KisAbstractResourceModel::ResourceActive, true));
0155     QVERIFY(testDataInColumnAndRole(tagResourceModel, KisAbstractResourceModel::StorageActive, true));
0156 
0157      // *** TagResourceModel own columns *** //
0158      QVERIFY(testDataInColumnAndRole(tagResourceModel, KisAllTagResourceModel::TagId, 1));
0159      QVERIFY(testDataInColumnAndRole(tagResourceModel, KisAllTagResourceModel::ResourceId, 3));
0160 
0161      KisTagSP tag = tagResourceModel.data(idx, Qt::UserRole + KisAllTagResourceModel::Tag).value<KisTagSP>();
0162      QVERIFY(tag);
0163      QVERIFY(tag->valid());
0164      QCOMPARE(tag->name(), "* Favorites");
0165      QCOMPARE(tag->id(), 1);
0166 
0167      KoResourceSP resource = tagResourceModel.data(idx, Qt::UserRole + KisAllTagResourceModel::Resource).value<KoResourceSP>();
0168      QVERIFY(resource);
0169      QVERIFY(resource->valid());
0170      QCOMPARE(resource->name(), "test0.kpp");
0171      QCOMPARE(resource->resourceId(), 3);
0172 
0173      QVERIFY(testDataInColumnAndRole(tagResourceModel, KisAllTagResourceModel::TagActive, true));
0174      QVERIFY(testDataInColumnAndRole(tagResourceModel, KisAllTagResourceModel::ResourceActive, true));
0175      QVERIFY(testDataInColumnAndRole(tagResourceModel, KisAllTagResourceModel::ResourceStorageActive, true));
0176 
0177      QVERIFY(testDataInColumnAndRole(tagResourceModel, KisAllTagResourceModel::ResourceName, "test0.kpp"));
0178      QVERIFY(testDataInColumnAndRole(tagResourceModel, KisAllTagResourceModel::TagName, "* Favorites"));
0179 
0180 
0181 }
0182 
0183 void TestTagResourceModel::testTagResource()
0184 {
0185     KisResourceModel resourceModel(ResourceType::PaintOpPresets);
0186     KoResourceSP resource = resourceModel.resourcesForName("test2.kpp").first();
0187     Q_ASSERT(resource);
0188 
0189     KisTagModel tagModel(ResourceType::PaintOpPresets);
0190     KisTagSP tag = tagModel.tagForIndex(tagModel.index(2, 0));
0191     Q_ASSERT(tag);
0192 
0193     KisAllTagResourceModel tagResourceModel(ResourceType::PaintOpPresets);
0194     if (tagResourceModel.isResourceTagged(tag, resource->resourceId())) {
0195         tagResourceModel.untagResources(tag, { resource->resourceId() });
0196     }
0197 
0198     int rowCount = tagResourceModel.rowCount();
0199 
0200     QVERIFY(tagResourceModel.tagResources(tag, { resource->resourceId() }));
0201 
0202     QCOMPARE(tagResourceModel.rowCount(), rowCount + 1);
0203 }
0204 
0205 void TestTagResourceModel::testUntagResource()
0206 {
0207     KisResourceModel resourceModel(ResourceType::PaintOpPresets);
0208     KoResourceSP resource = resourceModel.resourcesForName("test1.kpp").first();
0209     QVERIFY(resource);
0210 
0211     KisTagModel tagModel(ResourceType::PaintOpPresets);
0212     KisTagSP tag = tagModel.tagForIndex(tagModel.index(2, 0));
0213     QVERIFY(tag);
0214 
0215     KisAllTagResourceModel tagResourceModel(ResourceType::PaintOpPresets);
0216 
0217     if (!tagResourceModel.isResourceTagged(tag, resource->resourceId())) {
0218         tagResourceModel.tagResources(tag, { resource->resourceId() });
0219     }
0220 
0221     int rowCount = tagResourceModel.rowCount();
0222     tagResourceModel.untagResources(tag, { resource->resourceId() });
0223 
0224     QCOMPARE(tagResourceModel.rowCount(), rowCount - 1);
0225 }
0226 
0227 void TestTagResourceModel::testIsResourceTagged()
0228 {
0229     KisResourceModel resourceModel(ResourceType::PaintOpPresets);
0230     KoResourceSP resource = resourceModel.resourcesForName("test2.kpp").first();
0231     Q_ASSERT(resource);
0232 
0233     KisTagModel tagModel(ResourceType::PaintOpPresets);
0234     KisTagSP tag = tagModel.tagForIndex(tagModel.index(2, 0));
0235     Q_ASSERT(tag);
0236 
0237     KisAllTagResourceModel tagResourceModel(ResourceType::PaintOpPresets);
0238 
0239     QVERIFY(tagResourceModel.tagResources(tag, { resource->resourceId() }));
0240     QCOMPARE(tagResourceModel.isResourceTagged(tag, resource->resourceId()), true);
0241 
0242     resource = resourceModel.resourcesForName("test1.kpp").first();
0243     QVERIFY(resource);
0244 
0245     tag = tagModel.tagForIndex(tagModel.index(2, 0));
0246     QVERIFY(tag);
0247 
0248     tagResourceModel.untagResources(tag, { resource->resourceId() });
0249     QCOMPARE(tagResourceModel.isResourceTagged(tag, resource->resourceId()), false);
0250 }
0251 
0252 void TestTagResourceModel::testFilterTagResource()
0253 {
0254     KisResourceModel resourceModel(ResourceType::PaintOpPresets);
0255     KoResourceSP resource = resourceModel.resourcesForName("test2.kpp").first();
0256     Q_ASSERT(resource);
0257 
0258     KisTagModel tagModel(ResourceType::PaintOpPresets);
0259     KisTagSP tag = tagModel.tagForIndex(tagModel.index(2, 0));
0260     Q_ASSERT(tag);
0261 
0262     KisTagResourceModel tagResourceModel(ResourceType::PaintOpPresets);
0263     QCOMPARE(tagResourceModel.rowCount(), 2);
0264 
0265     QVector<int> tagIds;
0266     tagIds << tag->id();
0267     tagResourceModel.setTagsFilter(tagIds);
0268 
0269     QVector<int> resourceIds;
0270     resourceIds << resource->resourceId();
0271     tagResourceModel.setResourcesFilter(resourceIds);
0272 
0273     QCOMPARE(tagResourceModel.rowCount(), 1);
0274 }
0275 
0276 
0277 void printOutModel(QAbstractItemModel* model)
0278 {
0279     if (model->inherits("KisTagResourceModel")) {
0280         KisTagResourceModel* tagResourceModel = dynamic_cast<KisTagResourceModel*>(model);
0281         if (!tagResourceModel) {
0282             return;
0283         }
0284         for (int i = 0; i < tagResourceModel->rowCount(); i++) {
0285             QModelIndex idx = tagResourceModel->index(i, 0);
0286             qCritical() << "Tag Resource | i: " << i << "| resource id: " << tagResourceModel->data(idx, Qt::UserRole + KisAllTagResourceModel::ResourceId).toInt()
0287                         << "| tag id: " << tagResourceModel->data(idx, Qt::UserRole + KisAllTagResourceModel::TagId).toInt()
0288                         << "(" << tagResourceModel->data(idx, Qt::UserRole + KisAllTagResourceModel::TagName).toString() << ")";
0289         }
0290         return;
0291     }
0292 
0293     if (model->inherits("KisTagModel")) {
0294         KisTagModel* tagModel = dynamic_cast<KisTagModel*>(model);
0295         if (!tagModel) {
0296             return;
0297         }
0298         for (int i = 0; i < tagModel->rowCount(); i++) {
0299             QModelIndex idx = tagModel->index(i, 0);
0300             qCritical() << "Tag | i: " << i << "| real id: " << tagModel->data(idx, Qt::UserRole + KisAllTagsModel::Id).toInt()
0301                         << "| name: " << tagModel->data(idx, Qt::UserRole + KisAllTagsModel::Name).toString();
0302         }
0303         return;
0304     }
0305 
0306     if (model->inherits("KisResourceModel")) {
0307         KisResourceModel* resourceModel = dynamic_cast<KisResourceModel*>(model);
0308         if (!resourceModel) {
0309             return;
0310         }
0311         for (int i = 0; i < resourceModel->rowCount(); i++) {
0312             QModelIndex idx = resourceModel->index(i, 0);
0313             qCritical() << "Resource | i: " << i << "| real id: " << resourceModel->data(idx, Qt::UserRole + KisAllResourcesModel::Id).toInt()
0314                         << "| name: " << resourceModel->data(idx, Qt::UserRole + KisAllResourcesModel::Name).toString();
0315         }
0316         return;
0317     }
0318 
0319 }
0320 
0321 
0322 void TestTagResourceModel::testBeginEndInsert()
0323 {
0324     KisTagResourceModel tagResourceModel(ResourceType::PaintOpPresets);
0325     KisResourceModel resourceModel(ResourceType::PaintOpPresets);
0326     KisTagModel tagModel(ResourceType::PaintOpPresets);
0327 
0328     QList<KoResourceSP> resources;
0329     QList<int> resourceIds;
0330 
0331     // prepare signal checker
0332     typedef ModelSignalChecker SC;
0333     ModelSignalChecker checker({5, 5, 4, 4}, {5, 5, 5, 5}, {SC::AboutInsert, SC::Insert, SC::AboutInsert, SC::Insert});
0334 
0335     // debug tips:
0336     // to see the content of the signal checker, use:
0337     //checker.printOut();
0338     // to see the content of the tagResourceModel, use:
0339     //printOutModel(&tagResourceModel);
0340 
0341     connect(&tagResourceModel, SIGNAL(rowsAboutToBeInserted(const QModelIndex, int, int)), &checker, SLOT(rowsAboutToBeInserted(const QModelIndex, int, int)));
0342     connect(&tagResourceModel, SIGNAL(rowsAboutToBeRemoved(const QModelIndex, int, int)), &checker, SLOT(rowsAboutToBeRemoved(const QModelIndex, int, int)));
0343     connect(&tagResourceModel, SIGNAL(rowsInserted(const QModelIndex, int, int)), &checker, SLOT(rowsInserted(const QModelIndex, int, int)));
0344     connect(&tagResourceModel, SIGNAL(rowsRemoved(const QModelIndex, int, int)), &checker, SLOT(rowsRemoved(const QModelIndex, int, int)));
0345 
0346     // this builds a list of resources
0347     for (int i = 0; i < resourceModel.rowCount(); i++) {
0348         QModelIndex idx = resourceModel.index(i, 0);
0349         if (resources.length() < 4) { // sanity check
0350             resources << resourceModel.resourceForIndex(idx);
0351             resourceIds << resourceModel.data(idx, Qt::UserRole + KisAllResourcesModel::Id).toInt();
0352         }
0353     }
0354 
0355     // ////
0356     tagModel.addTag("Tag1", true, {});
0357     tagModel.addTag("Tag2", true, {});
0358     tagModel.addTag("TagSpecial", true, {});
0359 
0360 
0361     QList<KisTagSP> tags;
0362     // this builds a list of tags
0363 
0364     for (int i = 0; i < tagModel.rowCount(); i++) {
0365         QModelIndex idx = tagModel.index(i, 0);
0366         int realId = tagModel.data(idx, Qt::UserRole + KisAllTagsModel::Id).toInt();
0367         if (tags.length() < 5 && realId >= 0) { // sanity check
0368             tags << tagModel.tagForIndex(idx);
0369         }
0370     }
0371 
0372     QCOMPARE(tags.count(), 4);
0373     QCOMPARE(resources.count(), 3);
0374 
0375 
0376     // tag assignment to resources:
0377     // other1 - res1
0378     // other2 - res2
0379     // special - res2
0380     // special - res3
0381     // other2 - res3
0382     // special - res1
0383     // other1 - res2
0384     //
0385     // this is done in order for tagging and untagging having to process
0386     // multiple batches of rows
0387     // and not just one consequent group of rows
0388     KisTagSP other1 = tags[1];
0389     KisTagSP other2 = tags[2];
0390     KisTagSP special = tags[3];
0391 
0392     // --- tagging
0393     tagResourceModel.tagResources(other1, { resources[0]->resourceId() });
0394     tagResourceModel.tagResources(other2, { resources[1]->resourceId() });
0395 
0396     tagResourceModel.tagResources(special, { resources[2]->resourceId() }); // <- special
0397     tagResourceModel.tagResources(special, { resources[1]->resourceId() }); // <- special
0398 
0399     tagResourceModel.tagResources(other2, { resources[2]->resourceId() });
0400 
0401     tagResourceModel.tagResources(special, { resources[0]->resourceId() }); // <- special
0402 
0403     tagResourceModel.tagResources(other1, { resources[1]->resourceId() });
0404 
0405     // --- untagging
0406 
0407     checker.reset();
0408     checker.setInfo({4, 4, 5, 5}, {5, 5, 5, 5}, {SC::AboutRemove, SC::Remove, SC::AboutRemove, SC::Remove});
0409 
0410     tagResourceModel.untagResources(special, QVector<int>() << resourceIds[2] << resourceIds[1] << resourceIds[0]);
0411 
0412     QVERIFY2(checker.isCorrect(), "Detected incorrect/unexpected signals sent to views");
0413 
0414 
0415 
0416     // *** *** //
0417     checker.reset();
0418     checker.setInfo({5, 5, 4, 4}, {5, 5, 5, 5}, {SC::AboutInsert, SC::Insert, SC::AboutInsert, SC::Insert});
0419 
0420     tagResourceModel.tagResources(special, { resourceIds[2], resourceIds[1], resourceIds[0] });
0421 
0422     QVERIFY2(checker.isCorrect(), "Detected incorrect/unexpected signals sent to views");
0423 
0424     // *** *** //
0425 
0426     checker.reset();
0427     checker.setInfo({4, 4, 5, 5}, {5, 5, 5, 5}, {SC::AboutRemove, SC::Remove, SC::AboutRemove, SC::Remove});
0428 
0429     tagResourceModel.untagResources(special, QVector<int>() << resourceIds[2] << resourceIds[1] << resourceIds[0]);
0430 
0431     QVERIFY2(checker.isCorrect(), "Detected incorrect/unexpected signals sent to views");
0432 
0433     // *** *** //
0434 
0435     checker.reset();
0436     checker.setInfo({5, 5, 4, 4}, {5, 5, 5, 5}, {SC::AboutInsert, SC::Insert, SC::AboutInsert, SC::Insert});
0437 
0438     tagResourceModel.tagResources(special, { resourceIds[0], resourceIds[1], resourceIds[2] });
0439 
0440     QVERIFY2(checker.isCorrect(), "Detected incorrect/unexpected signals sent to views");
0441 
0442     // *** *** //
0443 
0444     checker.reset();
0445     checker.setInfo({4, 4, 5, 5}, {5, 5, 5, 5}, {SC::AboutRemove, SC::Remove, SC::AboutRemove, SC::Remove});
0446 
0447     tagResourceModel.untagResources(special, { resourceIds[2], resourceIds[1], resourceIds[0] });
0448 
0449     QVERIFY2(checker.isCorrect(), "Detected incorrect/unexpected signals sent to views");
0450 
0451     // *** *** //
0452 
0453     checker.reset();
0454     checker.setInfo({}, {}, {}); // no signals expected, because all of them are untagged now
0455 
0456     tagResourceModel.untagResources(special, { resourceIds[2], resourceIds[1], resourceIds[0] });
0457 
0458     QVERIFY2(checker.isCorrect(), "Detected incorrect/unexpected signals sent to views");
0459 
0460     // *** *** //
0461 
0462     checker.reset();
0463     checker.setInfo({5, 5, 4, 4}, {5, 5, 4, 4}, {SC::AboutInsert, SC::Insert, SC::AboutInsert, SC::Insert});
0464 
0465     tagResourceModel.tagResources(special, { resourceIds[2], resourceIds[0] });
0466 
0467     QVERIFY2(checker.isCorrect(), "Detected incorrect/unexpected signals sent to views");
0468 
0469     // just to clean up space (to have all resources tagged)
0470     checker.reset();
0471 
0472     tagResourceModel.tagResources(special, { resourceIds[2], resourceIds[1], resourceIds[0] });
0473 
0474     // *** *** //
0475 
0476     checker.reset();
0477     checker.setInfo({4, 4, 6, 6}, {4, 4, 6, 6}, {SC::AboutRemove, SC::Remove, SC::AboutRemove, SC::Remove});
0478 
0479     tagResourceModel.untagResources(special, { resourceIds[2], resourceIds[0] });
0480 
0481     QVERIFY2(checker.isCorrect(), "Detected incorrect/unexpected signals sent to views");
0482 
0483     // *** *** //
0484 
0485     checker.reset();
0486     checker.setInfo({4, 4}, {4, 4}, {SC::AboutRemove, SC::Remove});
0487 
0488     tagResourceModel.untagResources(special, { resourceIds[1], resourceIds[0]});
0489 
0490     QVERIFY2(checker.isCorrect(), "Detected incorrect/unexpected signals sent to views");
0491 
0492     // *** *** //
0493     // check adding multiple new tag-resource assignments at once
0494 
0495     checker.reset();
0496     checker.setInfo({6, 6, 9, 9}, {8, 8, 11, 11}, {SC::AboutInsert, SC::Insert, SC::AboutInsert, SC::Insert});
0497 
0498     tagModel.addTag("tagExtra1", true, { resources[2], resources[1], resources[0]});
0499     tagModel.addTag("tagExtra2", true, {});
0500     KisTagSP tagExtra1 = tagModel.tagForUrl("tagExtra2");
0501     tagResourceModel.tagResources(tagExtra1, { resourceIds[2], resourceIds[1], resourceIds[0]});
0502 
0503 
0504     QVERIFY2(checker.isCorrect(), "Detected incorrect/unexpected signals sent to views");
0505 }
0506 
0507 void TestTagResourceModel::cleanupTestCase()
0508 {
0509     ResourceTestHelper::rmTestDb();
0510     ResourceTestHelper::cleanDstLocation(m_dstLocation);
0511 }
0512 
0513 #include <kistest.h>
0514 
0515 // ***** MODEL SIGNAL CHECKER Function definitions *****
0516 
0517 
0518 ModelSignalChecker::ModelSignalChecker(QList<int> _expectedFirsts, QList<int> _expectedLasts, QList<ModelSignalChecker::TYPE> _expectedTypes)
0519 {
0520     setInfo(_expectedFirsts, _expectedLasts, _expectedTypes);
0521 }
0522 
0523 void ModelSignalChecker::setInfo(QList<int> _expectedFirsts, QList<int> _expectedLasts, QList<ModelSignalChecker::TYPE> _expectedTypes)
0524 {
0525     KIS_ASSERT(_expectedFirsts.count() == _expectedLasts.count() && _expectedFirsts.count() == _expectedTypes.count() && "Incorrect data supplied to SignalChecker");
0526     expectedAmount = _expectedFirsts.count();
0527 
0528     expectedFirsts = _expectedFirsts;
0529     expectedLasts = _expectedLasts;
0530     expectedTypes = _expectedTypes;
0531     reset();
0532 }
0533 
0534 void ModelSignalChecker::reset()
0535 {
0536     firsts = QList<int>();
0537     lasts = QList<int>();
0538     types = QList<TYPE>();
0539     amount = 0;
0540 }
0541 
0542 bool ModelSignalChecker::isCorrect() {
0543     if (expectedFirsts.count() != firsts.count()) return false;
0544     if (expectedLasts.count() != lasts.count()) return false;
0545     if (expectedTypes.count() != types.count()) return false;
0546     if (expectedAmount != amount) return false;
0547 
0548     for (int i = 0; i < firsts.count(); i++) {
0549         if (expectedFirsts[i] != firsts[i]) return false;
0550     }
0551 
0552     for (int i = 0; i < lasts.count(); i++) {
0553         if (expectedLasts[i] != lasts[i]) return false;
0554     }
0555 
0556     for (int i = 0; i < types.count(); i++) {
0557         if (expectedTypes[i] != types[i]) return false;
0558     }
0559 
0560     return true;
0561 }
0562 
0563 void ModelSignalChecker::printOut()
0564 {
0565 
0566     qCritical() << "*** SignalChecker write out ***";
0567 
0568     int n = qMin(qMin(amount, firsts.count()), qMin(lasts.count(), types.count()));
0569     int nmax = qMax(qMax(amount, firsts.count()), qMax(lasts.count(), types.count()));
0570     if (n != nmax) {
0571         qCritical() << "The amounts differ!" << amount << firsts.count() << lasts.count() << types.count();
0572     }
0573 
0574     for (int i = 0; i < n; i++) {
0575         QString type = "[type]";
0576         switch(types[i]) {
0577         case AboutInsert:
0578             type = "About Insert";
0579             break;
0580         case AboutRemove:
0581             type = "About Remove";
0582             break;
0583         case Insert:
0584             type = "Insert";
0585             break;
0586         case Remove:
0587             type = "Remove";
0588             break;
0589         }
0590         qCritical() << i << type << firsts[i] << lasts[i];
0591     }
0592 
0593     qCritical() << "*** SignalChecker write out END ***";
0594 }
0595 
0596 void ModelSignalChecker::rowsAboutToBeInserted(const QModelIndex &parent, int first, int last)
0597 {
0598     Q_UNUSED(parent);
0599     addSignalInfo(first, last, AboutInsert);
0600 }
0601 
0602 void ModelSignalChecker::rowsInserted(const QModelIndex &parent, int first, int last)
0603 {
0604     Q_UNUSED(parent);
0605     addSignalInfo(first, last, Insert);
0606 }
0607 
0608 void ModelSignalChecker::rowsAboutToBeRemoved(const QModelIndex &parent, int first, int last)
0609 {
0610     Q_UNUSED(parent);
0611     addSignalInfo(first, last, AboutRemove);
0612 }
0613 
0614 void ModelSignalChecker::rowsRemoved(const QModelIndex &parent, int first, int last)
0615 {
0616     Q_UNUSED(parent);
0617     addSignalInfo(first, last, Remove);
0618 }
0619 
0620 void ModelSignalChecker::addSignalInfo(int first, int last, ModelSignalChecker::TYPE type)
0621 {
0622     amount++;
0623     firsts << first;
0624     lasts << last;
0625     types << type;
0626 }
0627 
0628 KISTEST_MAIN(TestTagResourceModel)
0629