File indexing completed on 2024-05-12 05:10:05
0001 /*************************************************************************** 0002 Copyright (C) 2017 Robby Stephenson <robby@periapsis.org> 0003 ***************************************************************************/ 0004 0005 /*************************************************************************** 0006 * * 0007 * This program is free software; you can redistribute it and/or * 0008 * modify it under the terms of the GNU General Public License as * 0009 * published by the Free Software Foundation; either version 2 of * 0010 * the License or (at your option) version 3 or any later version * 0011 * accepted by the membership of KDE e.V. (or its successor approved * 0012 * by the membership of KDE e.V.), which shall act as a proxy * 0013 * defined in Section 14 of version 3 of the license. * 0014 * * 0015 * This program is distributed in the hope that it will be useful, * 0016 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0018 * GNU General Public License for more details. * 0019 * * 0020 * You should have received a copy of the GNU General Public License * 0021 * along with this program. If not, see <http://www.gnu.org/licenses/>. * 0022 * * 0023 ***************************************************************************/ 0024 0025 #undef QT_NO_CAST_FROM_ASCII 0026 0027 #include "tellicomodeltest.h" 0028 #include "modeltest.h" 0029 #include "../models/entrymodel.h" 0030 #include "../models/entryiconmodel.h" 0031 #include "../models/entrysortmodel.h" 0032 #include "../models/filtermodel.h" 0033 #include "../models/borrowermodel.h" 0034 #include "../models/entrygroupmodel.h" 0035 #include "../models/groupsortmodel.h" 0036 #include "../models/modeliterator.h" 0037 #include "../models/entryselectionmodel.h" 0038 #include "../collections/bookcollection.h" 0039 #include "../collectionfactory.h" 0040 #include "../document.h" 0041 #include "../entrygroup.h" 0042 #include "../images/imagefactory.h" 0043 #include "../images/image.h" 0044 0045 #include <KLocalizedString> 0046 0047 #include <QTest> 0048 #include <QSignalSpy> 0049 #include <QStandardPaths> 0050 #include <QLoggingCategory> 0051 0052 QTEST_MAIN( TellicoModelTest ) 0053 0054 void TellicoModelTest::initTestCase() { 0055 QStandardPaths::setTestModeEnabled(true); 0056 KLocalizedString::setApplicationDomain("tellico"); 0057 Tellico::ImageFactory::init(); 0058 Tellico::RegisterCollection<Tellico::Data::BookCollection> registerBook(Tellico::Data::Collection::Book, "book"); 0059 QLoggingCategory::setFilterRules(QStringLiteral("tellico.debug = true\ntellico.info = false")); 0060 } 0061 0062 void TellicoModelTest::testEntryModel() { 0063 Tellico::Data::CollPtr coll(new Tellico::Data::BookCollection(true)); // add default fields 0064 Tellico::Data::EntryPtr entry1(new Tellico::Data::Entry(coll)); 0065 entry1->setField(QStringLiteral("title"), QStringLiteral("Star Wars")); 0066 const QUrl u = QUrl::fromLocalFile(QFINDTESTDATA("../../icons/128-apps-tellico.png")); 0067 const QString imageId = Tellico::ImageFactory::addImage(u); 0068 entry1->setField(QStringLiteral("cover"), imageId); 0069 coll->addEntries(entry1); 0070 0071 Tellico::EntryModel entryModel(this); 0072 ModelTest test1(&entryModel); 0073 0074 Tellico::EntryIconModel iconModel(this); 0075 ModelTest test2(&iconModel); 0076 0077 Tellico::EntrySortModel sortModel(this); 0078 ModelTest test3(&sortModel); 0079 0080 iconModel.setSourceModel(&entryModel); 0081 sortModel.setSourceModel(&entryModel); 0082 0083 entryModel.setFields(coll->fields()); 0084 entryModel.setEntries(coll->entries()); 0085 QCOMPARE(entryModel.index(0, 0), entryModel.indexFromEntry(entry1)); 0086 0087 Tellico::Data::FieldPtr field1(new Tellico::Data::Field(QStringLiteral("test"), QStringLiteral("test"))); 0088 coll->addField(field1); 0089 entryModel.setFields(coll->fields()); 0090 0091 Tellico::Data::EntryPtr entry2(new Tellico::Data::Entry(coll)); 0092 coll->addEntries(entry2); 0093 entryModel.addEntries(Tellico::Data::EntryList() << entry2); 0094 0095 Tellico::Data::FieldPtr field2(new Tellico::Data::Field(QStringLiteral("test2"), QStringLiteral("test2"))); 0096 coll->addField(field2); 0097 entryModel.addFields(Tellico::Data::FieldList() << field2); 0098 0099 // Check FieldPtrRole in model data 0100 QModelIndex index = entryModel.index(0, entryModel.columnCount()-1); 0101 QVERIFY(index.isValid()); 0102 QCOMPARE(entryModel.data(index, Tellico::FieldPtrRole), 0103 QVariant::fromValue(field2)); 0104 //check FieldPtrRole in header model data 0105 QCOMPARE(entryModel.headerData(entryModel.columnCount()-1, Qt::Horizontal, Tellico::FieldPtrRole), 0106 QVariant::fromValue(field2)); 0107 0108 sortModel.setSortColumn(0); 0109 sortModel.setSecondarySortColumn(1); 0110 sortModel.setTertiarySortColumn(2); 0111 QCOMPARE(sortModel.sortColumn(), 0); 0112 QCOMPARE(sortModel.secondarySortColumn(), 1); 0113 QCOMPARE(sortModel.tertiarySortColumn(), 2); 0114 sortModel.sort(0); 0115 sortModel.setSortRole(Tellico::RowCountRole); 0116 sortModel.sort(0); 0117 sortModel.setSortRole(Tellico::EntryPtrRole); 0118 sortModel.sort(0); 0119 0120 QVariant icon1 = iconModel.data(iconModel.index(0, 0), Qt::DecorationRole); 0121 QVERIFY(icon1.isValid()); 0122 QVERIFY(!icon1.isNull()); 0123 QVERIFY(icon1.canConvert<QIcon>()); 0124 auto& img1 = Tellico::ImageFactory::imageById(imageId); 0125 QVERIFY(!img1.isNull()); 0126 0127 Tellico::FilterRule* rule1 = new Tellico::FilterRule(QStringLiteral("title"), 0128 QStringLiteral("Star Wars"), 0129 Tellico::FilterRule::FuncEquals); 0130 Tellico::FilterPtr filter(new Tellico::Filter(Tellico::Filter::MatchAny)); 0131 filter->append(rule1); 0132 0133 sortModel.setFilter(filter); 0134 0135 entryModel.clear(); 0136 entryModel.setFields(coll->fields()); 0137 entryModel.setEntries(coll->entries()); 0138 QCOMPARE(entryModel.index(0, 0), entryModel.indexFromEntry(entry1)); 0139 0140 Tellico::Data::FieldPtr field3(new Tellico::Data::Field(QStringLiteral("test"), QStringLiteral("test-new"))); 0141 coll->modifyField(field3); 0142 QCOMPARE(coll->fields().count(), entryModel.columnCount(QModelIndex())); 0143 entryModel.modifyField(field2, field3); 0144 0145 coll->removeField(field3); 0146 entryModel.removeFields(Tellico::Data::FieldList() << field3); 0147 QCOMPARE(coll->fields().count(), entryModel.columnCount(QModelIndex())); 0148 0149 QCOMPARE(coll->entries().count(), entryModel.rowCount(QModelIndex())); 0150 coll->removeEntries(Tellico::Data::EntryList() << entry2); 0151 QCOMPARE(coll->entries().count() + 1, entryModel.rowCount(QModelIndex())); 0152 entryModel.removeEntries(Tellico::Data::EntryList() << entry2); 0153 QCOMPARE(coll->entries().count(), entryModel.rowCount(QModelIndex())); 0154 0155 for(Tellico::ModelIterator eIt(&entryModel); eIt.entry(); ++eIt) { 0156 QVERIFY(eIt.isValid()); 0157 } 0158 } 0159 0160 void TellicoModelTest::testFilterModel() { 0161 Tellico::FilterModel filterModel(this); 0162 ModelTest test1(&filterModel); 0163 0164 Tellico::FilterRule* rule1 = new Tellico::FilterRule(QStringLiteral("title"), 0165 QStringLiteral("Star Wars"), 0166 Tellico::FilterRule::FuncEquals); 0167 Tellico::FilterPtr filter(new Tellico::Filter(Tellico::Filter::MatchAny)); 0168 filter->append(rule1); 0169 filterModel.addFilter(filter); 0170 0171 Tellico::Data::CollPtr c = Tellico::Data::Document::self()->collection(); 0172 Tellico::Data::EntryPtr entry1(new Tellico::Data::Entry(c)); 0173 entry1->setField(QStringLiteral("title"), QStringLiteral("Star Wars")); 0174 c->addEntries(entry1); 0175 0176 filterModel.clear(); 0177 filterModel.addFilter(filter); 0178 QCOMPARE(filter, filterModel.filter(filterModel.index(0, 0))); 0179 QVERIFY(filterModel.indexContainsEntry(filterModel.index(0, 0), entry1)); 0180 0181 filterModel.invalidate(filterModel.index(0, 0)); 0182 QCOMPARE(filter, filterModel.filter(filterModel.index(0, 0))); 0183 QVERIFY(filterModel.indexContainsEntry(filterModel.index(0, 0), entry1)); 0184 } 0185 0186 void TellicoModelTest::testGroupModel() { 0187 Tellico::Data::CollPtr coll(new Tellico::Data::BookCollection(true)); // add default fields 0188 Tellico::Data::EntryPtr entry1(new Tellico::Data::Entry(coll)); 0189 entry1->setField(QStringLiteral("title"), QStringLiteral("Star Wars")); 0190 entry1->setField(QStringLiteral("author"), QStringLiteral("George Lucas")); 0191 coll->addEntries(entry1); 0192 Tellico::Data::EntryPtr entry2(new Tellico::Data::Entry(coll)); 0193 entry2->setField(QStringLiteral("title"), QStringLiteral("Empire Strikes Back")); 0194 entry2->setField(QStringLiteral("author"), QStringLiteral("George Lucas")); 0195 coll->addEntries(entry2); 0196 Tellico::Data::EntryPtr entry3(new Tellico::Data::Entry(coll)); 0197 entry3->setField(QStringLiteral("title"), QStringLiteral("1632")); 0198 entry3->setField(QStringLiteral("author"), QStringLiteral("Eric Flint")); 0199 coll->addEntries(entry3); 0200 0201 Tellico::EntryGroupModel groupModel(this); 0202 ModelTest test1(&groupModel); 0203 0204 Tellico::GroupSortModel sortModel(this); 0205 ModelTest test2(&sortModel); 0206 0207 sortModel.setSourceModel(&groupModel); 0208 0209 Tellico::Data::EntryGroupDict* dict = coll->entryGroupDictByName(QStringLiteral("author")); 0210 groupModel.addGroups(dict->values(), QString()); 0211 QCOMPARE(sortModel.rowCount(), 2); 0212 0213 sortModel.sort(0); 0214 sortModel.setEntrySortField(QStringLiteral("author")); 0215 QCOMPARE(sortModel.entrySortField(), QLatin1String("author")); 0216 sortModel.sort(0, Qt::AscendingOrder); 0217 0218 Tellico::ModelIterator gIt(&sortModel); 0219 QVERIFY(gIt.isValid()); 0220 auto group = gIt.group(); 0221 QVERIFY(group); 0222 QCOMPARE(group->groupName(), QStringLiteral("Flint, Eric")); 0223 QCOMPARE(group->fieldName(), QStringLiteral("author")); 0224 QCOMPARE(group->size(), 1); 0225 QVERIFY(!group->hasEmptyGroupName()); 0226 0227 ++gIt; 0228 QVERIFY(gIt.isValid()); 0229 group = gIt.group(); 0230 QVERIFY(group); 0231 QCOMPARE(group->groupName(), QStringLiteral("Lucas, George")); 0232 QCOMPARE(group->fieldName(), QStringLiteral("author")); 0233 QCOMPARE(group->size(), 2); 0234 QVERIFY(!group->hasEmptyGroupName()); 0235 0236 ++gIt; 0237 QVERIFY(!gIt.group()); 0238 } 0239 0240 void TellicoModelTest::testSelectionModel() { 0241 qRegisterMetaType<Tellico::Data::EntryList>("Tellico::Data::EntryList"); 0242 // this mimics the model dependencies used in mainwindow.cpp 0243 Tellico::EntryModel entryModel(this); 0244 ModelTest test1(&entryModel); 0245 Tellico::EntryIconModel iconModel(this); 0246 ModelTest test2(&iconModel); 0247 iconModel.setSourceModel(&entryModel); 0248 0249 QItemSelectionModel selModel(&entryModel, this); 0250 Tellico::EntrySelectionModel proxySelect(&iconModel, &selModel, this); 0251 0252 Tellico::Data::CollPtr coll(new Tellico::Data::Collection(true)); // add default fields 0253 Tellico::Data::EntryPtr entry1(new Tellico::Data::Entry(coll)); 0254 entry1->setField(QStringLiteral("title"), QStringLiteral("Test1")); 0255 coll->addEntries(entry1); 0256 0257 entryModel.setFields(coll->fields()); 0258 entryModel.setEntries(coll->entries()); 0259 0260 QSignalSpy entriesSelectedSpy(&proxySelect, SIGNAL(entriesSelected(Tellico::Data::EntryList))); 0261 selModel.select(entryModel.index(0,0), QItemSelectionModel::Select); 0262 QCOMPARE(entriesSelectedSpy.count(), 1); 0263 0264 Tellico::Data::EntryList entries = proxySelect.selectedEntries(); 0265 QCOMPARE(entries.count(), 1); 0266 QCOMPARE(entries.at(0)->title(), QStringLiteral("Test1")); 0267 0268 Tellico::Data::EntryPtr entry2(new Tellico::Data::Entry(coll)); 0269 entry2->setField(QStringLiteral("title"), QStringLiteral("test2")); 0270 coll->addEntries(entry2); 0271 entryModel.addEntries(Tellico::Data::EntryList() << entry2); 0272 0273 entries = proxySelect.selectedEntries(); 0274 QCOMPARE(entries.count(), 1); 0275 QCOMPARE(entries.at(0)->title(), QStringLiteral("Test1")); 0276 0277 selModel.select(entryModel.index(1,0), QItemSelectionModel::Select); 0278 entries = proxySelect.selectedEntries(); 0279 QCOMPARE(entries.count(), 2); 0280 QCOMPARE(entries.at(0)->title(), QStringLiteral("Test1")); 0281 QCOMPARE(entries.at(1)->title(), QStringLiteral("Test2")); 0282 0283 selModel.select(entryModel.index(0,0), QItemSelectionModel::Toggle); 0284 entries = proxySelect.selectedEntries(); 0285 QCOMPARE(entries.count(), 1); 0286 QCOMPARE(entries.at(0)->title(), QStringLiteral("Test2")); 0287 0288 entryModel.clear(); 0289 // now there should be no selection since EntryModel::clear calls modelReset() 0290 // and the proxy selection is connected to that signal 0291 entries = proxySelect.selectedEntries(); 0292 QCOMPARE(entries.count(), 0); 0293 } 0294 0295 void TellicoModelTest::testBorrowerModel() { 0296 Tellico::BorrowerModel borrowerModel(this); 0297 ModelTest test1(&borrowerModel); 0298 0299 Tellico::Data::BorrowerPtr borr(new Tellico::Data::Borrower(QStringLiteral("name1"), QStringLiteral("uid1"))); 0300 borrowerModel.addBorrower(borr); 0301 0302 Tellico::Data::CollPtr c = Tellico::Data::Document::self()->collection(); 0303 Tellico::Data::EntryPtr entry(new Tellico::Data::Entry(c)); 0304 entry->setField(QStringLiteral("title"), QStringLiteral("Star Wars")); 0305 c->addEntries(entry); 0306 Tellico::Data::LoanPtr loan(new Tellico::Data::Loan(entry, 0307 QDate::currentDate(), 0308 QDate::currentDate(), 0309 QStringLiteral("note"))); 0310 borr->addLoan(loan); 0311 0312 borrowerModel.clear(); 0313 borrowerModel.addBorrower(borr); 0314 0315 QModelIndex borrIndex = borrowerModel.index(0, 0); 0316 QVERIFY(borrIndex.isValid()); 0317 QModelIndex loanIndex = borrowerModel.index(0, 0, borrIndex); 0318 QVERIFY(loanIndex.isValid()); 0319 0320 QCOMPARE(borr, borrowerModel.borrower(borrIndex)); 0321 QCOMPARE(loan, borrowerModel.loan(loanIndex)); 0322 QCOMPARE(entry, borrowerModel.entry(loanIndex)); 0323 }