File indexing completed on 2025-01-19 04:57:00
0001 /* 0002 * SPDX-FileCopyrightText: 2014 Kevin Ottens <ervin@kde.org> 0003 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0004 */ 0005 0006 0007 #include <testlib/qtest_gui_zanshin.h> 0008 0009 #include <QAbstractItemModel> 0010 #include <QSortFilterProxyModel> 0011 #include <QAction> 0012 #include <QHeaderView> 0013 #include <QLayout> 0014 #include <QLineEdit> 0015 #include <QMessageBox> 0016 #include <QStandardItemModel> 0017 #include <QToolButton> 0018 #include <QTreeView> 0019 #include <runningtaskmodelinterface.h> 0020 0021 #include <KConfig> 0022 #include <KConfigGroup> 0023 #include <KLocalizedString> 0024 #include <KMessageWidget> 0025 #include <KSharedConfig> 0026 0027 #include "domain/task.h" 0028 0029 #include "presentation/taskfilterproxymodel.h" 0030 #include "presentation/metatypes.h" 0031 #include "presentation/querytreemodelbase.h" 0032 0033 #include "widgets/filterwidget.h" 0034 #include "widgets/itemdelegate.h" 0035 #include "widgets/pageview.h" 0036 0037 #include "messageboxstub.h" 0038 0039 class PageModelStub : public QObject 0040 { 0041 Q_OBJECT 0042 Q_PROPERTY(QAbstractItemModel* centralListModel READ centralListModel) 0043 public: 0044 void setProxyModel(QAbstractProxyModel *proxy) 0045 { 0046 proxyModel = proxy; 0047 proxyModel->setSourceModel(&itemModel); 0048 } 0049 0050 QAbstractItemModel *centralListModel() 0051 { 0052 if (proxyModel) 0053 return proxyModel; 0054 return &itemModel; 0055 } 0056 0057 QStandardItem *addStubItem(const QString &title, QStandardItem *parentItem = nullptr) 0058 { 0059 QStandardItem *item = new QStandardItem; 0060 item->setData(title, Qt::DisplayRole); 0061 if (!parentItem) 0062 itemModel.appendRow(item); 0063 else 0064 parentItem->appendRow(item); 0065 0066 taskNames << title; 0067 return item; 0068 } 0069 0070 Domain::Task::Ptr addTaskItem(const QString &title, QStandardItem *parentItem = nullptr) 0071 { 0072 auto item = addStubItem(title, parentItem); 0073 auto task = Domain::Task::Ptr::create(); 0074 task->setTitle(title); 0075 item->setData(QVariant::fromValue(task), Presentation::QueryTreeModelBase::ObjectRole); 0076 return task; 0077 } 0078 0079 void addStubItems(const QStringList &list) 0080 { 0081 foreach (const QString &title, list) { 0082 addStubItem(title); 0083 } 0084 } 0085 0086 public slots: 0087 void addItem(const QString &name, const QModelIndex &parentIndex) 0088 { 0089 taskNames << name; 0090 parentIndices << parentIndex; 0091 } 0092 0093 void removeItem(const QModelIndex &index) 0094 { 0095 removedIndices << index; 0096 } 0097 0098 void promoteItem(const QModelIndex &index) 0099 { 0100 promotedIndices << index; 0101 } 0102 0103 public: 0104 QStringList taskNames; 0105 QList<QPersistentModelIndex> parentIndices; 0106 QList<QPersistentModelIndex> removedIndices; 0107 QList<QPersistentModelIndex> promotedIndices; 0108 QStandardItemModel itemModel; 0109 QAbstractProxyModel *proxyModel = nullptr; 0110 }; 0111 0112 class RunningTaskModelStub : public Presentation::RunningTaskModelInterface 0113 { 0114 Q_OBJECT 0115 public: 0116 Domain::Task::Ptr runningTask() const override { return m_runningTask; } 0117 void setRunningTask(const Domain::Task::Ptr &task) override { m_runningTask = task; } 0118 void taskDeleted(const Domain::Task::Ptr &task) override { m_deletedTask = task; } 0119 void stopTask() override {} 0120 void doneTask() override {} 0121 private: 0122 Domain::Task::Ptr m_runningTask; 0123 Domain::Task::Ptr m_deletedTask; 0124 }; 0125 0126 class PageViewTest : public QObject 0127 { 0128 Q_OBJECT 0129 private: 0130 KConfigGroup configGroup() 0131 { 0132 return KConfigGroup(KSharedConfig::openConfig(), "General"); 0133 } 0134 0135 private slots: 0136 void shouldHaveDefaultState() 0137 { 0138 Widgets::PageView page; 0139 QCOMPARE(page.contentsMargins(), QMargins(0, 0, 0, 0)); 0140 QCOMPARE(page.layout()->contentsMargins(), QMargins(0, 0, 0, 3)); 0141 0142 auto messageWidget = page.findChild<KMessageWidget*>(QStringLiteral("messageWidget")); 0143 QVERIFY(messageWidget); 0144 QVERIFY(!messageWidget->isVisibleTo(&page)); 0145 QVERIFY(!messageWidget->isCloseButtonVisible()); 0146 QVERIFY(messageWidget->wordWrap()); 0147 QVERIFY(messageWidget->text().isEmpty()); 0148 QVERIFY(messageWidget->icon().isNull()); 0149 QCOMPARE(messageWidget->messageType(), KMessageWidget::Error); 0150 QVERIFY(!messageWidget->isShowAnimationRunning()); 0151 QVERIFY(!messageWidget->isHideAnimationRunning()); 0152 0153 auto centralView = page.findChild<QTreeView*>(QStringLiteral("centralView")); 0154 QVERIFY(centralView); 0155 QVERIFY(centralView->isVisibleTo(&page)); 0156 QVERIFY(!centralView->header()->isVisibleTo(&page)); 0157 QVERIFY(qobject_cast<Widgets::ItemDelegate*>(centralView->itemDelegate())); 0158 QVERIFY(centralView->alternatingRowColors()); 0159 QCOMPARE(centralView->dragDropMode(), QTreeView::DragDrop); 0160 0161 auto filter = page.findChild<Widgets::FilterWidget*>(QStringLiteral("filterWidget")); 0162 QVERIFY(filter); 0163 QVERIFY(!filter->isVisibleTo(&page)); 0164 QVERIFY(filter->proxyModel()); 0165 QCOMPARE(filter->proxyModel(), centralView->model()); 0166 0167 QLineEdit *quickAddEdit = page.findChild<QLineEdit*>(QStringLiteral("quickAddEdit")); 0168 QVERIFY(quickAddEdit); 0169 QVERIFY(quickAddEdit->isVisibleTo(&page)); 0170 QVERIFY(quickAddEdit->text().isEmpty()); 0171 QCOMPARE(quickAddEdit->placeholderText(), i18n("Type and press enter to add a task")); 0172 0173 auto addAction = page.findChild<QAction*>(QStringLiteral("addItemAction")); 0174 QVERIFY(addAction); 0175 auto cancelAddAction = page.findChild<QAction*>(QStringLiteral("cancelAddItemAction")); 0176 QVERIFY(cancelAddAction); 0177 auto removeAction = page.findChild<QAction*>(QStringLiteral("removeItemAction")); 0178 QVERIFY(removeAction); 0179 auto promoteAction = page.findChild<QAction*>(QStringLiteral("promoteItemAction")); 0180 QVERIFY(promoteAction); 0181 auto filterAction = page.findChild<QAction*>(QStringLiteral("filterViewAction")); 0182 QVERIFY(filterAction); 0183 QVERIFY(filterAction->isCheckable()); 0184 QVERIFY(!filterAction->isChecked()); 0185 auto doneAction = page.findChild<QAction*>(QStringLiteral("doneViewAction")); 0186 QVERIFY(doneAction); 0187 QVERIFY(doneAction->isCheckable()); 0188 QVERIFY(doneAction->isChecked()); 0189 auto futureAction = page.findChild<QAction*>(QStringLiteral("futureViewAction")); 0190 QVERIFY(futureAction); 0191 QVERIFY(futureAction->isCheckable()); 0192 QVERIFY(futureAction->isChecked()); 0193 auto runTaskAction = page.findChild<QAction*>(QStringLiteral("runTaskAction")); 0194 QVERIFY(runTaskAction); 0195 QVERIFY(!runTaskAction->isEnabled()); 0196 0197 auto actions = page.globalActions(); 0198 QCOMPARE(actions.value(QStringLiteral("page_view_add")), addAction); 0199 QCOMPARE(actions.value(QStringLiteral("page_view_remove")), removeAction); 0200 QCOMPARE(actions.value(QStringLiteral("page_view_promote")), promoteAction); 0201 QCOMPARE(actions.value(QStringLiteral("page_view_filter")), filterAction); 0202 QCOMPARE(actions.value(QStringLiteral("page_view_done")), doneAction); 0203 QCOMPARE(actions.value(QStringLiteral("page_view_future")), futureAction); 0204 QCOMPARE(actions.value(QStringLiteral("page_run_task")), runTaskAction); 0205 } 0206 0207 void shouldDisplayListFromPageModel() 0208 { 0209 // GIVEN 0210 QStandardItemModel model; 0211 0212 QObject stubPageModel; 0213 stubPageModel.setProperty("centralListModel", QVariant::fromValue(static_cast<QAbstractItemModel*>(&model))); 0214 0215 Widgets::PageView page; 0216 auto centralView = page.findChild<QTreeView*>(QStringLiteral("centralView")); 0217 QVERIFY(centralView); 0218 auto proxyModel = qobject_cast<Presentation::TaskFilterProxyModel*>(centralView->model()); 0219 QVERIFY(proxyModel); 0220 QVERIFY(!proxyModel->sourceModel()); 0221 0222 // WHEN 0223 page.setModel(&stubPageModel); 0224 0225 // THEN 0226 QCOMPARE(page.model(), &stubPageModel); 0227 QVERIFY(page.isEnabled()); 0228 QCOMPARE(proxyModel->sourceModel(), &model); 0229 } 0230 0231 void shouldNotCrashWithNullModel() 0232 { 0233 // GIVEN 0234 QStandardItemModel model; 0235 QObject stubPageModel; 0236 stubPageModel.setProperty("centralListModel", QVariant::fromValue(static_cast<QAbstractItemModel*>(&model))); 0237 0238 Widgets::PageView page; 0239 page.setModel(&stubPageModel); 0240 0241 auto centralView = page.findChild<QTreeView*>(QStringLiteral("centralView")); 0242 QVERIFY(centralView); 0243 auto proxyModel = qobject_cast<Presentation::TaskFilterProxyModel*>(centralView->model()); 0244 QVERIFY(proxyModel); 0245 QCOMPARE(proxyModel->sourceModel(), &model); 0246 0247 // WHEN 0248 page.setModel(nullptr); 0249 0250 // THEN 0251 QVERIFY(!page.model()); 0252 QVERIFY(!page.isEnabled()); 0253 QVERIFY(!proxyModel->sourceModel()); 0254 } 0255 0256 void shouldManageFocusThroughActions() 0257 { 0258 // GIVEN 0259 Widgets::PageView page; 0260 auto centralView = page.findChild<QTreeView*>(QStringLiteral("centralView")); 0261 auto quickAddEdit = page.findChild<QLineEdit*>(QStringLiteral("quickAddEdit")); 0262 auto filter = page.findChild<Widgets::FilterWidget*>(QStringLiteral("filterWidget")); 0263 auto filterEdit = filter->findChild<QLineEdit*>(); 0264 QVERIFY(filterEdit); 0265 page.show(); 0266 page.activateWindow(); 0267 QVERIFY(QTest::qWaitForWindowActive(&page)); 0268 0269 centralView->setFocus(); 0270 QVERIFY(centralView->hasFocus()); 0271 QVERIFY(!quickAddEdit->hasFocus()); 0272 QVERIFY(!filter->isVisibleTo(&page)); 0273 QVERIFY(!filterEdit->hasFocus()); 0274 0275 auto addAction = page.findChild<QAction*>(QStringLiteral("addItemAction")); 0276 auto cancelAddAction = page.findChild<QAction*>(QStringLiteral("cancelAddItemAction")); 0277 auto filterAction = page.findChild<QAction*>(QStringLiteral("filterViewAction")); 0278 0279 // WHEN 0280 addAction->trigger(); 0281 0282 // THEN 0283 QVERIFY(!centralView->hasFocus()); 0284 QVERIFY(quickAddEdit->hasFocus()); 0285 QVERIFY(!filter->isVisibleTo(&page)); 0286 QVERIFY(!filterEdit->hasFocus()); 0287 0288 // WHEN 0289 cancelAddAction->trigger(); 0290 0291 // THEN 0292 QVERIFY(centralView->hasFocus()); 0293 QVERIFY(!quickAddEdit->hasFocus()); 0294 QVERIFY(!filter->isVisibleTo(&page)); 0295 QVERIFY(!filterEdit->hasFocus()); 0296 0297 // WHEN 0298 filterAction->trigger(); 0299 0300 // THEN 0301 QVERIFY(!centralView->hasFocus()); 0302 QVERIFY(!quickAddEdit->hasFocus()); 0303 QVERIFY(filter->isVisibleTo(&page)); 0304 QVERIFY(filterEdit->hasFocus()); 0305 0306 // WHEN 0307 cancelAddAction->trigger(); 0308 0309 // THEN 0310 QVERIFY(centralView->hasFocus()); 0311 QVERIFY(!quickAddEdit->hasFocus()); 0312 QVERIFY(filter->isVisibleTo(&page)); 0313 QVERIFY(!filterEdit->hasFocus()); 0314 } 0315 0316 void shouldManageFilterVisibilityThroughAction() 0317 { 0318 // GIVEN 0319 Widgets::PageView page; 0320 auto centralView = page.findChild<QTreeView*>(QStringLiteral("centralView")); 0321 auto filter = page.findChild<Widgets::FilterWidget*>(QStringLiteral("filterWidget")); 0322 auto filterEdit = filter->findChild<QLineEdit*>(); 0323 QVERIFY(filterEdit); 0324 page.show(); 0325 page.activateWindow(); 0326 QVERIFY(QTest::qWaitForWindowActive(&page)); 0327 0328 centralView->setFocus(); 0329 QVERIFY(centralView->hasFocus()); 0330 QVERIFY(!filter->isVisibleTo(&page)); 0331 QVERIFY(!filterEdit->hasFocus()); 0332 0333 auto filterAction = page.findChild<QAction*>(QStringLiteral("filterViewAction")); 0334 0335 // WHEN 0336 filterAction->trigger(); 0337 0338 // THEN 0339 QVERIFY(!centralView->hasFocus()); 0340 QVERIFY(filter->isVisibleTo(&page)); 0341 QVERIFY(filterEdit->hasFocus()); 0342 0343 // WHEN 0344 filterEdit->setText("Foo"); 0345 0346 // THEN 0347 QCOMPARE(filterEdit->text(), QString("Foo")); 0348 0349 // WHEN 0350 filterAction->trigger(); 0351 0352 // THEN 0353 QVERIFY(centralView->hasFocus()); 0354 QVERIFY(!filter->isVisibleTo(&page)); 0355 QVERIFY(!filterEdit->hasFocus()); 0356 QVERIFY(filterEdit->text().isEmpty()); 0357 } 0358 0359 void shouldManageDoneTasksVisibilityThroughAction() 0360 { 0361 // GIVEN 0362 Widgets::PageView page; 0363 auto filter = page.findChild<Widgets::FilterWidget*>(QStringLiteral("filterWidget")); 0364 auto filterProxy = filter->proxyModel(); 0365 QVERIFY(filterProxy); 0366 0367 QVERIFY(filterProxy->showDoneTasks()); 0368 0369 auto doneAction = page.findChild<QAction*>(QStringLiteral("doneViewAction")); 0370 0371 // WHEN 0372 doneAction->trigger(); 0373 0374 // THEN 0375 QVERIFY(!filterProxy->showDoneTasks()); 0376 0377 // WHEN 0378 doneAction->trigger(); 0379 0380 // THEN 0381 QVERIFY(filterProxy->showDoneTasks()); 0382 } 0383 0384 void shouldStoreDoneTasksVisibilityDefaultState() 0385 { 0386 // GIVEN 0387 configGroup().deleteEntry("ShowDone"); 0388 0389 { 0390 Widgets::PageView page; 0391 auto doneAction = page.findChild<QAction*>(QStringLiteral("doneViewAction")); 0392 0393 // THEN 0394 QVERIFY(doneAction->isChecked()); 0395 } 0396 0397 // WHEN 0398 configGroup().writeEntry("ShowDone", false); 0399 0400 { 0401 Widgets::PageView page; 0402 auto doneAction = page.findChild<QAction*>(QStringLiteral("doneViewAction")); 0403 0404 // THEN 0405 QVERIFY(!doneAction->isChecked()); 0406 } 0407 0408 // WHEN 0409 configGroup().writeEntry("ShowDone", true); 0410 0411 { 0412 Widgets::PageView page; 0413 auto doneAction = page.findChild<QAction*>(QStringLiteral("doneViewAction")); 0414 0415 // THEN 0416 QVERIFY(doneAction->isChecked()); 0417 } 0418 0419 // WHEN 0420 configGroup().deleteEntry("ShowDone"); 0421 0422 { 0423 Widgets::PageView page; 0424 auto doneAction = page.findChild<QAction*>(QStringLiteral("doneViewAction")); 0425 0426 // THEN 0427 QVERIFY(doneAction->isChecked()); 0428 } 0429 0430 // WHEN 0431 Widgets::PageView page; 0432 auto doneAction = page.findChild<QAction*>(QStringLiteral("doneViewAction")); 0433 doneAction->trigger(); 0434 0435 // THEN 0436 QVERIFY(configGroup().hasKey("ShowDone")); 0437 QVERIFY(!configGroup().readEntry("ShowDone", true)); 0438 0439 // WHEN 0440 doneAction->trigger(); 0441 0442 // THEN 0443 QVERIFY(configGroup().hasKey("ShowDone")); 0444 QVERIFY(configGroup().readEntry("ShowDone", false)); 0445 } 0446 0447 void shouldManageFutureTasksVisibilityThroughAction() 0448 { 0449 // GIVEN 0450 Widgets::PageView page; 0451 auto filter = page.findChild<Widgets::FilterWidget*>(QStringLiteral("filterWidget")); 0452 auto filterProxy = filter->proxyModel(); 0453 QVERIFY(filterProxy); 0454 0455 QVERIFY(filterProxy->showFutureTasks()); 0456 0457 auto futureAction = page.findChild<QAction*>(QStringLiteral("futureViewAction")); 0458 0459 // WHEN 0460 futureAction->trigger(); 0461 0462 // THEN 0463 QVERIFY(!filterProxy->showFutureTasks()); 0464 0465 // WHEN 0466 futureAction->trigger(); 0467 0468 // THEN 0469 QVERIFY(filterProxy->showFutureTasks()); 0470 } 0471 0472 void shouldStoreFutureTasksVisibilityDefaultState() 0473 { 0474 // GIVEN 0475 configGroup().deleteEntry("ShowFuture"); 0476 0477 { 0478 Widgets::PageView page; 0479 auto futureAction = page.findChild<QAction*>(QStringLiteral("futureViewAction")); 0480 0481 // THEN 0482 QVERIFY(futureAction->isChecked()); 0483 } 0484 0485 // WHEN 0486 configGroup().writeEntry("ShowFuture", false); 0487 0488 { 0489 Widgets::PageView page; 0490 auto futureAction = page.findChild<QAction*>(QStringLiteral("futureViewAction")); 0491 0492 // THEN 0493 QVERIFY(!futureAction->isChecked()); 0494 } 0495 0496 // WHEN 0497 configGroup().writeEntry("ShowFuture", true); 0498 0499 { 0500 Widgets::PageView page; 0501 auto futureAction = page.findChild<QAction*>(QStringLiteral("futureViewAction")); 0502 0503 // THEN 0504 QVERIFY(futureAction->isChecked()); 0505 } 0506 0507 // WHEN 0508 configGroup().deleteEntry("ShowFuture"); 0509 0510 { 0511 Widgets::PageView page; 0512 auto futureAction = page.findChild<QAction*>(QStringLiteral("futureViewAction")); 0513 0514 // THEN 0515 QVERIFY(futureAction->isChecked()); 0516 } 0517 0518 // WHEN 0519 Widgets::PageView page; 0520 auto futureAction = page.findChild<QAction*>(QStringLiteral("futureViewAction")); 0521 futureAction->trigger(); 0522 0523 // THEN 0524 QVERIFY(configGroup().hasKey("ShowFuture")); 0525 QVERIFY(!configGroup().readEntry("ShowFuture", true)); 0526 0527 // WHEN 0528 futureAction->trigger(); 0529 0530 // THEN 0531 QVERIFY(configGroup().hasKey("ShowFuture")); 0532 QVERIFY(configGroup().readEntry("ShowFuture", false)); 0533 } 0534 0535 void shouldCreateTasksWithNoParentWhenHittingReturnWithoutSelectedIndex() 0536 { 0537 // GIVEN 0538 PageModelStub stubPageModel; 0539 Widgets::PageView page; 0540 page.setModel(&stubPageModel); 0541 auto quickAddEdit = page.findChild<QLineEdit*>(QStringLiteral("quickAddEdit")); 0542 0543 // WHEN 0544 QTest::keyClick(quickAddEdit, Qt::Key_Return); // Does nothing (edit empty) 0545 QTest::keyClicks(quickAddEdit, QStringLiteral("Foo")); 0546 QTest::keyClick(quickAddEdit, Qt::Key_Return); 0547 QTest::keyClick(quickAddEdit, Qt::Key_Return); // Does nothing (edit empty) 0548 QTest::keyClicks(quickAddEdit, QStringLiteral("Bar")); 0549 QTest::keyClick(quickAddEdit, Qt::Key_Return); 0550 QTest::keyClick(quickAddEdit, Qt::Key_Return); // Does nothing (edit empty) 0551 0552 // THEN 0553 QCOMPARE(stubPageModel.taskNames, QStringList() << QStringLiteral("Foo") << QStringLiteral("Bar")); 0554 QCOMPARE(stubPageModel.parentIndices.size(), 2); 0555 QCOMPARE(stubPageModel.parentIndices.first(), QPersistentModelIndex()); 0556 QCOMPARE(stubPageModel.parentIndices.last(), QPersistentModelIndex()); 0557 } 0558 0559 void shouldCreateTasksWithNoParentWhenHittingReturnWithSeveralSelectedIndices() 0560 { 0561 // GIVEN 0562 PageModelStub stubPageModel; 0563 Q_ASSERT(stubPageModel.property("centralListModel").canConvert<QAbstractItemModel*>()); 0564 stubPageModel.addStubItems(QStringList() << QStringLiteral("A") << QStringLiteral("B") << QStringLiteral("C")); 0565 QPersistentModelIndex index0 = stubPageModel.itemModel.index(0, 0); 0566 QPersistentModelIndex index1 = stubPageModel.itemModel.index(1, 0); 0567 0568 Widgets::PageView page; 0569 page.setModel(&stubPageModel); 0570 0571 auto centralView = page.findChild<QTreeView*>(QStringLiteral("centralView")); 0572 centralView->selectionModel()->select(index0, QItemSelectionModel::ClearAndSelect); 0573 centralView->selectionModel()->select(index1, QItemSelectionModel::Select); 0574 0575 auto quickAddEdit = page.findChild<QLineEdit*>(QStringLiteral("quickAddEdit")); 0576 0577 // WHEN 0578 QTest::keyClicks(quickAddEdit, QStringLiteral("Foo")); 0579 QTest::keyClick(quickAddEdit, Qt::Key_Return); 0580 0581 // THEN 0582 QCOMPARE(stubPageModel.taskNames, QStringList() << QStringLiteral("A") 0583 << QStringLiteral("B") 0584 << QStringLiteral("C") 0585 << QStringLiteral("Foo")); 0586 QCOMPARE(stubPageModel.parentIndices.size(), 1); 0587 QCOMPARE(stubPageModel.parentIndices.first(), QPersistentModelIndex()); 0588 } 0589 0590 void shouldCreateTasksWithParentWhenHittingReturnWithOneSelectedIndex() 0591 { 0592 // GIVEN 0593 PageModelStub stubPageModel; 0594 Q_ASSERT(stubPageModel.property("centralListModel").canConvert<QAbstractItemModel*>()); 0595 stubPageModel.addStubItems(QStringList() << QStringLiteral("A") << QStringLiteral("B") << QStringLiteral("C")); 0596 QPersistentModelIndex index = stubPageModel.itemModel.index(1, 0); 0597 0598 Widgets::PageView page; 0599 page.setModel(&stubPageModel); 0600 0601 auto centralView = page.findChild<QTreeView*>(QStringLiteral("centralView")); 0602 centralView->selectionModel()->select(index, QItemSelectionModel::ClearAndSelect); 0603 0604 auto quickAddEdit = page.findChild<QLineEdit*>(QStringLiteral("quickAddEdit")); 0605 0606 // WHEN 0607 QTest::keyClicks(quickAddEdit, QStringLiteral("Foo")); 0608 QTest::keyClick(quickAddEdit, Qt::Key_Return); 0609 0610 // THEN 0611 QCOMPARE(stubPageModel.taskNames, QStringList() << QStringLiteral("A") 0612 << QStringLiteral("B") 0613 << QStringLiteral("C") 0614 << QStringLiteral("Foo")); 0615 QCOMPARE(stubPageModel.parentIndices.size(), 1); 0616 QCOMPARE(stubPageModel.parentIndices.first(), index); 0617 } 0618 0619 void shouldDeleteItemWhenHittingTheDeleteKey() 0620 { 0621 // GIVEN 0622 PageModelStub stubPageModel; 0623 Q_ASSERT(stubPageModel.property("centralListModel").canConvert<QAbstractItemModel*>()); 0624 stubPageModel.addStubItems(QStringList() << QStringLiteral("A") << QStringLiteral("B") << QStringLiteral("C")); 0625 QPersistentModelIndex index = stubPageModel.itemModel.index(1, 0); 0626 0627 Widgets::PageView page; 0628 page.setModel(&stubPageModel); 0629 0630 QTreeView *centralView = page.findChild<QTreeView*>(QStringLiteral("centralView")); 0631 centralView->selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect); 0632 centralView->setFocus(); 0633 0634 // Needed for shortcuts to work 0635 page.show(); 0636 page.activateWindow(); 0637 QVERIFY(QTest::qWaitForWindowActive(&page)); 0638 0639 // WHEN 0640 QTest::keyPress(centralView, Qt::Key_Delete); 0641 0642 // THEN 0643 QCOMPARE(stubPageModel.removedIndices.size(), 1); 0644 QCOMPARE(stubPageModel.removedIndices.first(), index); 0645 } 0646 0647 void shouldNotTryToDeleteIfThereIsNoSelection() 0648 { 0649 // GIVEN 0650 PageModelStub stubPageModel; 0651 Q_ASSERT(stubPageModel.property("centralListModel").canConvert<QAbstractItemModel*>()); 0652 stubPageModel.addStubItems(QStringList() << QStringLiteral("A") << QStringLiteral("B") << QStringLiteral("C")); 0653 0654 Widgets::PageView page; 0655 page.setModel(&stubPageModel); 0656 0657 QTreeView *centralView = page.findChild<QTreeView*>(QStringLiteral("centralView")); 0658 centralView->clearSelection(); 0659 page.findChild<QLineEdit*>(QStringLiteral("quickAddEdit"))->setFocus(); 0660 0661 // Needed for shortcuts to work 0662 page.show(); 0663 page.activateWindow(); 0664 QVERIFY(QTest::qWaitForWindowActive(&page)); 0665 0666 // WHEN 0667 QTest::keyPress(centralView, Qt::Key_Delete); 0668 0669 // THEN 0670 QVERIFY(stubPageModel.removedIndices.isEmpty()); 0671 } 0672 0673 void shouldDisplayNotificationWhenHittingTheDeleteKeyOnAnItemWithChildren() 0674 { 0675 // GIVEN 0676 PageModelStub stubPageModel; 0677 Q_ASSERT(stubPageModel.property("centralListModel").canConvert<QAbstractItemModel*>()); 0678 stubPageModel.addStubItems(QStringList() << QStringLiteral("A") << QStringLiteral("B")); 0679 QStandardItem *parentIndex = stubPageModel.itemModel.item(1, 0); 0680 stubPageModel.addStubItem(QStringLiteral("C"), parentIndex); 0681 QPersistentModelIndex index = stubPageModel.itemModel.index(1, 0); 0682 0683 Widgets::PageView page; 0684 page.setModel(&stubPageModel); 0685 auto msgbox = MessageBoxStub::Ptr::create(); 0686 page.setMessageBoxInterface(msgbox); 0687 0688 QTreeView *centralView = page.findChild<QTreeView*>(QStringLiteral("centralView")); 0689 centralView->selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect); 0690 QVERIFY(centralView->selectionModel()->currentIndex().isValid()); 0691 centralView->setFocus(); 0692 0693 // Needed for shortcuts to work 0694 page.show(); 0695 page.activateWindow(); 0696 QVERIFY(QTest::qWaitForWindowActive(&page)); 0697 0698 // WHEN 0699 QTest::keyPress(centralView, Qt::Key_Delete); 0700 0701 // THEN 0702 QVERIFY(msgbox->called()); 0703 QCOMPARE(stubPageModel.removedIndices.size(), 1); 0704 QCOMPARE(stubPageModel.removedIndices.first(), index); 0705 } 0706 0707 void shouldDisplayNotificationWhenHittingTheDeleteKeyOnAnItemWithHiddenChildren() 0708 { 0709 // GIVEN 0710 PageModelStub stubPageModel; 0711 Q_ASSERT(stubPageModel.property("centralListModel").canConvert<QAbstractItemModel*>()); 0712 stubPageModel.addStubItems(QStringList() << QStringLiteral("A") << QStringLiteral("B")); 0713 QStandardItem *parentIndex = stubPageModel.itemModel.item(1, 0); 0714 stubPageModel.addStubItem(QStringLiteral("C"), parentIndex); 0715 0716 QSortFilterProxyModel proxyModel; 0717 stubPageModel.setProxyModel(&proxyModel); 0718 proxyModel.setFilterRegularExpression(QStringLiteral("B")); 0719 0720 QPersistentModelIndex index = stubPageModel.centralListModel()->index(0, 0); 0721 QCOMPARE(index.data().toString(), QLatin1StringView("B")); 0722 Widgets::PageView page; 0723 page.setModel(&stubPageModel); 0724 auto msgbox = MessageBoxStub::Ptr::create(); 0725 page.setMessageBoxInterface(msgbox); 0726 0727 QTreeView *centralView = page.findChild<QTreeView*>(QStringLiteral("centralView")); 0728 centralView->selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect); 0729 QVERIFY(centralView->selectionModel()->currentIndex().isValid()); 0730 centralView->setFocus(); 0731 0732 // Needed for shortcuts to work 0733 page.show(); 0734 page.activateWindow(); 0735 QVERIFY(QTest::qWaitForWindowActive(&page)); 0736 0737 // WHEN 0738 QTest::keyPress(centralView, Qt::Key_Delete); 0739 0740 // THEN 0741 QVERIFY(msgbox->called()); 0742 QCOMPARE(stubPageModel.removedIndices.size(), 1); 0743 QCOMPARE(stubPageModel.removedIndices.first(), index); 0744 } 0745 0746 void shouldDeleteItemsWhenHittingTheDeleteKey() 0747 { 0748 // GIVEN 0749 PageModelStub stubPageModel; 0750 Q_ASSERT(stubPageModel.property("centralListModel").canConvert<QAbstractItemModel*>()); 0751 stubPageModel.addStubItems(QStringList() << QStringLiteral("A") << QStringLiteral("B") << QStringLiteral("C")); 0752 QPersistentModelIndex index = stubPageModel.itemModel.index(1, 0); 0753 QPersistentModelIndex index2 = stubPageModel.itemModel.index(2, 0); 0754 0755 Widgets::PageView page; 0756 page.setModel(&stubPageModel); 0757 auto msgbox = MessageBoxStub::Ptr::create(); 0758 page.setMessageBoxInterface(msgbox); 0759 0760 QTreeView *centralView = page.findChild<QTreeView*>(QStringLiteral("centralView")); 0761 centralView->selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect); 0762 centralView->selectionModel()->setCurrentIndex(index2, QItemSelectionModel::Select); 0763 centralView->setFocus(); 0764 0765 // Needed for shortcuts to work 0766 page.show(); 0767 page.activateWindow(); 0768 QVERIFY(QTest::qWaitForWindowActive(&page)); 0769 0770 // WHEN 0771 QTest::keyPress(centralView, Qt::Key_Delete); 0772 0773 // THEN 0774 QVERIFY(msgbox->called()); 0775 QCOMPARE(stubPageModel.removedIndices.size(), 2); 0776 QCOMPARE(stubPageModel.removedIndices.first(), index); 0777 QCOMPARE(stubPageModel.removedIndices.at(1), index2); 0778 } 0779 0780 void shouldPromoteItem() 0781 { 0782 // GIVEN 0783 PageModelStub stubPageModel; 0784 Q_ASSERT(stubPageModel.property("centralListModel").canConvert<QAbstractItemModel*>()); 0785 stubPageModel.addStubItems(QStringList() << QStringLiteral("A") << QStringLiteral("B") << QStringLiteral("C")); 0786 QPersistentModelIndex index = stubPageModel.itemModel.index(1, 0); 0787 0788 Widgets::PageView page; 0789 page.setModel(&stubPageModel); 0790 0791 auto promoteAction = page.findChild<QAction*>(QStringLiteral("promoteItemAction")); 0792 QVERIFY(promoteAction); 0793 0794 QTreeView *centralView = page.findChild<QTreeView*>(QStringLiteral("centralView")); 0795 centralView->selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect); 0796 centralView->setFocus(); 0797 0798 // WHEN 0799 promoteAction->trigger(); 0800 0801 // THEN 0802 QCOMPARE(stubPageModel.promotedIndices.size(), 1); 0803 QCOMPARE(stubPageModel.promotedIndices.first(), index); 0804 } 0805 0806 void shouldNotTryToPromoteItemIfThereIsNoSelection() 0807 { 0808 // GIVEN 0809 PageModelStub stubPageModel; 0810 Q_ASSERT(stubPageModel.property("centralListModel").canConvert<QAbstractItemModel*>()); 0811 stubPageModel.addStubItems(QStringList() << QStringLiteral("A") << QStringLiteral("B") << QStringLiteral("C")); 0812 0813 Widgets::PageView page; 0814 page.setModel(&stubPageModel); 0815 0816 auto promoteAction = page.findChild<QAction*>(QStringLiteral("promoteItemAction")); 0817 QVERIFY(promoteAction); 0818 0819 QTreeView *centralView = page.findChild<QTreeView*>(QStringLiteral("centralView")); 0820 centralView->selectionModel()->clear(); 0821 centralView->setFocus(); 0822 0823 // WHEN 0824 promoteAction->trigger(); 0825 0826 // THEN 0827 QVERIFY(stubPageModel.promotedIndices.isEmpty()); 0828 } 0829 0830 void shouldClearCentralViewSelectionOnEscape() 0831 { 0832 // GIVEN 0833 PageModelStub stubPageModel; 0834 Q_ASSERT(stubPageModel.property("centralListModel").canConvert<QAbstractItemModel*>()); 0835 stubPageModel.addStubItems(QStringList() << QStringLiteral("A") << QStringLiteral("B") << QStringLiteral("C")); 0836 QPersistentModelIndex index = stubPageModel.itemModel.index(1, 0); 0837 0838 Widgets::PageView page; 0839 page.setModel(&stubPageModel); 0840 0841 auto centralView = page.findChild<QTreeView*>(QStringLiteral("centralView")); 0842 centralView->selectionModel()->select(index, QItemSelectionModel::ClearAndSelect); 0843 QVERIFY(!centralView->selectionModel()->selectedIndexes().isEmpty()); 0844 0845 // WHEN 0846 QTest::keyClick(centralView, Qt::Key_Escape); 0847 0848 // THEN 0849 QVERIFY(centralView->selectionModel()->selectedIndexes().isEmpty()); 0850 } 0851 0852 void shouldReturnSelectedIndexes() 0853 { 0854 // GIVEN 0855 PageModelStub stubPageModel; 0856 Q_ASSERT(stubPageModel.property("centralListModel").canConvert<QAbstractItemModel*>()); 0857 stubPageModel.addStubItems(QStringList() << QStringLiteral("A") << QStringLiteral("B") << QStringLiteral("C")); 0858 auto index = stubPageModel.itemModel.index(1, 0); 0859 auto index2 = stubPageModel.itemModel.index(2, 0); 0860 0861 Widgets::PageView page; 0862 page.setModel(&stubPageModel); 0863 0864 auto centralView = page.findChild<QTreeView*>(QStringLiteral("centralView")); 0865 auto filterWidget = page.findChild<Widgets::FilterWidget*>(QStringLiteral("filterWidget")); 0866 0867 auto displayedModel = filterWidget->proxyModel(); 0868 auto displayedIndex = displayedModel->index(1, 0); 0869 auto displayedIndex2 = displayedModel->index(2, 0); 0870 0871 // WHEN 0872 centralView->selectionModel()->setCurrentIndex(displayedIndex, QItemSelectionModel::ClearAndSelect); 0873 centralView->selectionModel()->setCurrentIndex(displayedIndex2, QItemSelectionModel::Select); 0874 0875 // THEN 0876 auto selectedIndexes = page.selectedIndexes(); 0877 QCOMPARE(selectedIndexes.size(), 2); 0878 0879 QCOMPARE(selectedIndexes.at(0), index); 0880 QCOMPARE(selectedIndexes.at(1), index2); 0881 0882 QCOMPARE(selectedIndexes.at(0).model(), index.model()); 0883 QCOMPARE(selectedIndexes.at(1).model(), index2.model()); 0884 } 0885 0886 void shouldDisplayMessageOnError() 0887 { 0888 // GIVEN 0889 Widgets::PageView page; 0890 page.show(); 0891 QVERIFY(QTest::qWaitForWindowExposed(&page)); 0892 QTest::qWait(100); 0893 0894 auto messageWidget = page.findChild<KMessageWidget*>(QStringLiteral("messageWidget")); 0895 QVERIFY(messageWidget); 0896 QVERIFY(!messageWidget->isVisibleTo(&page)); 0897 0898 QCOMPARE(messageWidget->findChildren<QToolButton*>().size(), 1); 0899 auto closeButton = messageWidget->findChildren<QToolButton*>().first(); 0900 QVERIFY(closeButton); 0901 0902 // WHEN 0903 page.displayErrorMessage(QStringLiteral("Foo Error")); 0904 0905 // THEN 0906 QVERIFY(messageWidget->isVisibleTo(&page)); 0907 QVERIFY(messageWidget->isCloseButtonVisible()); 0908 QCOMPARE(messageWidget->text(), QStringLiteral("Foo Error")); 0909 QVERIFY(messageWidget->icon().isNull()); 0910 QCOMPARE(messageWidget->messageType(), KMessageWidget::Error); 0911 QVERIFY(messageWidget->isShowAnimationRunning()); 0912 QVERIFY(!messageWidget->isHideAnimationRunning()); 0913 0914 // WHEN 0915 QTest::qWait(800); 0916 0917 // THEN 0918 QVERIFY(!messageWidget->isShowAnimationRunning()); 0919 QVERIFY(!messageWidget->isHideAnimationRunning()); 0920 0921 // WHEN 0922 closeButton->click(); 0923 0924 // THEN 0925 QVERIFY(!messageWidget->isShowAnimationRunning()); 0926 QVERIFY(messageWidget->isHideAnimationRunning()); 0927 0928 // WHEN 0929 QTest::qWait(800); 0930 0931 // THEN 0932 QVERIFY(!messageWidget->isShowAnimationRunning()); 0933 QVERIFY(!messageWidget->isHideAnimationRunning()); 0934 } 0935 0936 void shouldRunTask() 0937 { 0938 // GIVEN 0939 PageModelStub stubPageModel; 0940 Q_ASSERT(stubPageModel.property("centralListModel").canConvert<QAbstractItemModel*>()); 0941 auto task1 = stubPageModel.addTaskItem(QStringLiteral("Task1")); 0942 auto task2 = stubPageModel.addTaskItem(QStringLiteral("Task2")); 0943 Widgets::PageView page; 0944 page.setModel(&stubPageModel); 0945 RunningTaskModelStub stubRunningTaskModel; 0946 page.setRunningTaskModel(&stubRunningTaskModel); 0947 auto centralView = page.findChild<QTreeView*>(QStringLiteral("centralView")); 0948 0949 QModelIndex index = stubPageModel.itemModel.index(0, 0); 0950 centralView->selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect); 0951 QVERIFY(centralView->selectionModel()->currentIndex().isValid()); 0952 0953 auto runTaskAction = page.findChild<QAction*>(QStringLiteral("runTaskAction")); 0954 QVERIFY(runTaskAction); 0955 QVERIFY(runTaskAction->isEnabled()); 0956 0957 // WHEN starting the first task 0958 runTaskAction->trigger(); 0959 0960 // THEN 0961 QCOMPARE(stubRunningTaskModel.property("runningTask").value<Domain::Task::Ptr>(), task1); 0962 QCOMPARE(task1->startDate(), QDate::currentDate()); 0963 0964 // WHEN starting the second task 0965 QModelIndex index2 = stubPageModel.itemModel.index(1, 0); 0966 centralView->selectionModel()->setCurrentIndex(index2, QItemSelectionModel::ClearAndSelect); 0967 runTaskAction->trigger(); 0968 0969 // THEN 0970 QCOMPARE(stubRunningTaskModel.property("runningTask").value<Domain::Task::Ptr>(), task2); 0971 QCOMPARE(task2->startDate(), QDate::currentDate()); 0972 } 0973 }; 0974 0975 ZANSHIN_TEST_MAIN(PageViewTest) 0976 0977 #include "pageviewtest.moc"