File indexing completed on 2025-01-19 04:56:59

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 <QMimeData>
0010 #include <QStandardItemModel>
0011 #include <QStringListModel>
0012 #include <QTreeView>
0013 #include <QWidgetAction>
0014 
0015 #include <algorithm>
0016 
0017 #include "utils/mem_fn.h"
0018 
0019 #include "domain/task.h"
0020 
0021 #include "presentation/taskfilterproxymodel.h"
0022 #include "presentation/querytreemodelbase.h"
0023 #include "presentation/runningtaskmodelinterface.h"
0024 
0025 #include "widgets/applicationcomponents.h"
0026 #include "widgets/availablepagesview.h"
0027 #include "widgets/availablesourcesview.h"
0028 #include "widgets/editorview.h"
0029 #include "widgets/filterwidget.h"
0030 #include "widgets/pageview.h"
0031 #include "widgets/pageviewerrorhandler.h"
0032 #include "widgets/quickselectdialog.h"
0033 #include "widgets/runningtaskwidget.h"
0034 
0035 
0036 class CustomModelStub : public QStandardItemModel
0037 {
0038     Q_OBJECT
0039 
0040     QMimeData *mimeData(const QModelIndexList &indexes) const override
0041     {
0042         QStringList dataString;
0043         std::transform(indexes.begin(), indexes.end(),
0044                        std::back_inserter(dataString),
0045                        [] (const QModelIndex &index) {
0046                            return index.data().toString();
0047                        });
0048 
0049         auto data = new QMimeData;
0050         data->setData(QStringLiteral("application/x-zanshin-object"), "object");
0051         data->setProperty("objects", QVariant::fromValue(dataString));
0052 
0053         return data;
0054     }
0055 
0056     bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &destination) override
0057     {
0058         Q_UNUSED(action);
0059 
0060         Q_ASSERT(row == -1);
0061         Q_ASSERT(column == -1);
0062         Q_ASSERT(destination.isValid());
0063         Q_ASSERT(data->hasFormat(QStringLiteral("application/x-zanshin-object")));
0064 
0065         auto dataString = data->property("objects").toStringList();
0066         Q_ASSERT(!dataString.isEmpty());
0067 
0068         droppedItemDataString = dataString;
0069         dropDestination = destination.data().toString();
0070 
0071         return true;
0072     }
0073 
0074 public:
0075     QStringList droppedItemDataString;
0076     QString dropDestination;
0077 };
0078 
0079 class ApplicationModelStub : public QObject
0080 {
0081     Q_OBJECT
0082     Q_PROPERTY(QObject* currentPage READ currentPage WRITE setCurrentPage)
0083 public:
0084     typedef QSharedPointer<ApplicationModelStub> Ptr;
0085 
0086     explicit ApplicationModelStub(QObject *parent = nullptr)
0087         : QObject(parent), m_currentPage(nullptr) {}
0088 
0089     QObject *currentPage()
0090     {
0091         return m_currentPage;
0092     }
0093 
0094     void setCurrentPage(QObject *page)
0095     {
0096         if (page == m_currentPage)
0097             return;
0098 
0099         m_currentPage = page;
0100         emit currentPageChanged(m_currentPage);
0101     }
0102 
0103 signals:
0104     void currentPageChanged(QObject *page);
0105 
0106 private:
0107     QObject *m_currentPage;
0108 };
0109 
0110 class AvailablePagesModelStub : public QObject
0111 {
0112     Q_OBJECT
0113     Q_PROPERTY(QAbstractItemModel* pageListModel READ pageListModel)
0114 public:
0115     explicit AvailablePagesModelStub(QObject *parent = nullptr)
0116         : QObject(parent)
0117     {
0118         QStandardItem *inbox = new QStandardItem;
0119         inbox->setData("Inbox", Qt::DisplayRole);
0120         itemModel.appendRow(inbox);
0121 
0122         QStandardItem *project = new QStandardItem;
0123         project->setData("Project", Qt::DisplayRole);
0124         itemModel.appendRow(project);
0125     }
0126 
0127     QAbstractItemModel *pageListModel()
0128     {
0129         return &itemModel;
0130     }
0131 
0132     Q_SCRIPTABLE QObject *createPageForIndex(const QModelIndex &index)
0133     {
0134         auto page = new QObject(this);
0135         auto model = new QStringListModel(page);
0136         model->setStringList(QStringList() << QStringLiteral("Items") << QStringLiteral("from") << index.data().toString());
0137         page->setProperty("centralListModel",
0138                           QVariant::fromValue<QAbstractItemModel*>(model));
0139         createdPages << page;
0140         return page;
0141     }
0142 
0143 public:
0144     QList<QObject*> createdPages;
0145     CustomModelStub itemModel;
0146 };
0147 
0148 class PageModelStub : public QObject
0149 {
0150     Q_OBJECT
0151     Q_PROPERTY(QAbstractItemModel* centralListModel READ centralListModel)
0152 public:
0153     QAbstractItemModel *centralListModel()
0154     {
0155         return &itemModel;
0156     }
0157 
0158     void addTask(const QString &title)
0159     {
0160         auto task = Domain::Task::Ptr::create();
0161         task->setTitle(title);
0162         addTask(task);
0163     }
0164 
0165     void addTask(const Domain::Task::Ptr &task)
0166     {
0167         QStandardItem *item = new QStandardItem;
0168         item->setData(QVariant::fromValue(task), Presentation::QueryTreeModelBase::ObjectRole);
0169         item->setData(task->title(), Qt::DisplayRole);
0170         itemModel.appendRow(item);
0171     }
0172 
0173     Domain::Task::Ptr itemAtRow(int row) const
0174     {
0175         return itemModel.index(row, 0).data(Presentation::QueryTreeModelBase::ObjectRole)
0176                                       .value<Domain::Task::Ptr>();
0177     }
0178 
0179     QModelIndexList selectedIndexes() const
0180     {
0181         return selectedItems;
0182     }
0183 
0184 public:
0185     QModelIndexList selectedItems;
0186     CustomModelStub itemModel;
0187 };
0188 
0189 class EditorModelStub : public QObject
0190 {
0191     Q_OBJECT
0192 public:
0193     explicit EditorModelStub(QObject *parent = nullptr)
0194         : QObject(parent)
0195     {
0196     }
0197 
0198     void setPropertyAndSignal(const QByteArray &name, const QVariant &value)
0199     {
0200         if (property(name) == value)
0201             return;
0202 
0203         setProperty(name, value);
0204         if (name == "text")
0205             emit textChanged(value.toString());
0206         else if (name == "title")
0207             emit titleChanged(value.toString());
0208         else if (name == "done")
0209             emit doneChanged(value.toBool());
0210         else if (name == "startDate")
0211             emit startDateChanged(value.toDate());
0212         else if (name == "dueDate")
0213             emit dueDateChanged(value.toDate());
0214         else
0215             qFatal("Unsupported property %s", name.constData());
0216     }
0217 
0218 public slots:
0219     void setTitle(const QString &title) { setPropertyAndSignal("title", title); }
0220     void setText(const QString &text) { setPropertyAndSignal("text", text); }
0221     void setDone(bool done) { setPropertyAndSignal("done", done); }
0222     void setStartDate(const QDate &start) { setPropertyAndSignal("startDate", start); }
0223     void setDueDate(const QDate &due) { setPropertyAndSignal("dueDate", due); }
0224 
0225 signals:
0226     void textChanged(const QString &text);
0227     void titleChanged(const QString &title);
0228     void doneChanged(bool done);
0229     void startDateChanged(const QDate &date);
0230     void dueDateChanged(const QDate &due);
0231 };
0232 
0233 class RunningTaskModelStub : public Presentation::RunningTaskModelInterface
0234 {
0235     Q_OBJECT
0236 public:
0237     explicit RunningTaskModelStub(QObject *parent = nullptr)
0238         : Presentation::RunningTaskModelInterface(parent)
0239     {
0240     }
0241 
0242     Domain::Task::Ptr runningTask() const override { return {}; }
0243     void setRunningTask(const Domain::Task::Ptr &) override {}
0244     void taskDeleted(const Domain::Task::Ptr &) override {}
0245     void stopTask() override {}
0246     void doneTask() override {}
0247 };
0248 
0249 class QuickSelectDialogStub : public Widgets::QuickSelectDialogInterface
0250 {
0251 public:
0252     typedef QSharedPointer<QuickSelectDialogStub> Ptr;
0253 
0254     explicit QuickSelectDialogStub()
0255         : parent(nullptr),
0256           execCount(0),
0257           itemModel(nullptr)
0258     {
0259     }
0260 
0261     int exec() override
0262     {
0263         execCount++;
0264         return QDialog::Accepted;
0265     }
0266 
0267     void setModel(QAbstractItemModel *model) override
0268     {
0269         itemModel = model;
0270     }
0271 
0272     QPersistentModelIndex selectedIndex() const override
0273     {
0274         return index;
0275     }
0276 
0277     QWidget *parent;
0278     int execCount;
0279     QAbstractItemModel *itemModel;
0280     QPersistentModelIndex index;
0281 };
0282 
0283 class ApplicationComponentsTest : public QObject
0284 {
0285     Q_OBJECT
0286 public:
0287     explicit ApplicationComponentsTest(QObject *parent = nullptr)
0288         : QObject(parent)
0289     {
0290         qputenv("ZANSHIN_UNIT_TEST_RUN", "1");
0291     }
0292 
0293 private slots:
0294     void shouldHaveApplicationModelAndSetErrorHandler()
0295     {
0296         // GIVEN
0297         Widgets::ApplicationComponents components;
0298         auto model = QObjectPtr::create();
0299 
0300         // WHEN
0301         components.setModel(model);
0302 
0303         // THEN
0304         QCOMPARE(components.model(), model);
0305         auto errorHandlerBase = model->property("errorHandler").value<Presentation::ErrorHandler*>();
0306         QVERIFY(errorHandlerBase);
0307         auto errorHandler = static_cast<Widgets::PageViewErrorHandler*>(errorHandlerBase);
0308         QVERIFY(errorHandler);
0309         QVERIFY(!errorHandler->pageView());
0310 
0311         // WHEN
0312         auto pageView = components.pageView();
0313 
0314         // THEN
0315         QCOMPARE(errorHandler->pageView(), pageView);
0316     }
0317 
0318     void shouldApplyAvailableSourcesModelToAvailableSourcesView()
0319     {
0320         // GIVEN
0321         Widgets::ApplicationComponents components;
0322         auto model = QObjectPtr::create();
0323         QObject availableSources;
0324         model->setProperty("availableSources", QVariant::fromValue(&availableSources));
0325 
0326         // WHEN
0327         components.setModel(model);
0328 
0329         // THEN
0330         QCOMPARE(components.availableSourcesView()->model(), &availableSources);
0331     }
0332 
0333     void shouldApplyAvailableSourcesModelAlsoToCreatedAvailableSourcesView()
0334     {
0335         // GIVEN
0336         Widgets::ApplicationComponents components;
0337         // Force creation
0338         components.availableSourcesView();
0339 
0340         auto model = QObjectPtr::create();
0341         QObject availableSources;
0342         model->setProperty("availableSources", QVariant::fromValue(&availableSources));
0343 
0344         // WHEN
0345         components.setModel(model);
0346 
0347         // THEN
0348         QCOMPARE(components.availableSourcesView()->model(), &availableSources);
0349     }
0350 
0351     void shouldApplyAvailablePagesModelToAvailablePagesView()
0352     {
0353         // GIVEN
0354         Widgets::ApplicationComponents components;
0355         auto model = QObjectPtr::create();
0356 
0357         QObject availablePages;
0358         model->setProperty("availablePages", QVariant::fromValue(&availablePages));
0359 
0360         QObject availableSources;
0361         QAbstractItemModel *sourcesModel = new QStandardItemModel(model.data());
0362         availableSources.setProperty("sourceListModel", QVariant::fromValue(sourcesModel));
0363         model->setProperty("availableSources", QVariant::fromValue(&availableSources));
0364 
0365         // WHEN
0366         components.setModel(model);
0367 
0368         // THEN
0369         QCOMPARE(components.availablePagesView()->model(), &availablePages);
0370         QCOMPARE(components.availablePagesView()->projectSourcesModel(), sourcesModel);
0371     }
0372 
0373     void shouldApplyAvailablePagesModelAlsoToCreatedAvailablePagesView()
0374     {
0375         // GIVEN
0376         Widgets::ApplicationComponents components;
0377         // Force creation
0378         components.availablePagesView();
0379 
0380         auto model = QObjectPtr::create();
0381         QObject availablePages;
0382         QAbstractItemModel *sourcesModel = new QStandardItemModel(model.data());
0383         model->setProperty("dataSourcesModel", QVariant::fromValue(sourcesModel));
0384         model->setProperty("availablePages", QVariant::fromValue(&availablePages));
0385 
0386         // WHEN
0387         components.setModel(model);
0388 
0389         // THEN
0390         QCOMPARE(components.availablePagesView()->model(), &availablePages);
0391         QCOMPARE(components.availablePagesView()->projectSourcesModel(), sourcesModel);
0392     }
0393 
0394     void shouldApplyCurrentPageModelToPageView()
0395     {
0396         // GIVEN
0397         Widgets::ApplicationComponents components;
0398         auto model = QObjectPtr::create();
0399         QObject currentPage;
0400         model->setProperty("currentPage", QVariant::fromValue(&currentPage));
0401 
0402         // WHEN
0403         components.setModel(model);
0404 
0405         // THEN
0406         QCOMPARE(components.pageView()->model(), &currentPage);
0407     }
0408 
0409     void shouldApplyCurrentPageModelAlsoToCreatedPageView()
0410     {
0411         // GIVEN
0412         Widgets::ApplicationComponents components;
0413         // Force creation
0414         components.pageView();
0415 
0416         auto model = QObjectPtr::create();
0417         QObject currentPage;
0418         model->setProperty("currentPage", QVariant::fromValue(&currentPage));
0419 
0420         // WHEN
0421         components.setModel(model);
0422 
0423         // THEN
0424         QCOMPARE(components.pageView()->model(), &currentPage);
0425     }
0426 
0427     void shouldApplyRunningTaskModelToPageView()
0428     {
0429         // GIVEN
0430         Widgets::ApplicationComponents components;
0431         auto model = QObjectPtr::create();
0432         auto runningTaskModel = new RunningTaskModelStub(model.data());
0433         model->setProperty("runningTaskModel", QVariant::fromValue<Presentation::RunningTaskModelInterface*>(runningTaskModel));
0434 
0435         // WHEN
0436         components.setModel(model);
0437 
0438         // THEN
0439         QCOMPARE(components.pageView()->runningTaskModel(), runningTaskModel);
0440     }
0441 
0442     void shouldApplyRunningTaskModelAlsoToCreatedPageView()
0443     {
0444         // GIVEN
0445         Widgets::ApplicationComponents components;
0446         // Force creation
0447         components.pageView();
0448 
0449         auto model = QObjectPtr::create();
0450         auto runningTaskModel = new RunningTaskModelStub(model.data());
0451         model->setProperty("runningTaskModel", QVariant::fromValue<Presentation::RunningTaskModelInterface*>(runningTaskModel));
0452 
0453         // WHEN
0454         components.setModel(model);
0455 
0456         // THEN
0457         QCOMPARE(components.pageView()->runningTaskModel(), runningTaskModel);
0458     }
0459 
0460     void shouldApplyEditorModelToEditorView()
0461     {
0462         // GIVEN
0463         Widgets::ApplicationComponents components;
0464         auto model = QObjectPtr::create();
0465         QObject *editorModel = new EditorModelStub(model.data());
0466         model->setProperty("editor", QVariant::fromValue(editorModel));
0467 
0468         // WHEN
0469         components.setModel(model);
0470 
0471         // THEN
0472         QCOMPARE(components.editorView()->model(), editorModel);
0473     }
0474 
0475     void shouldApplyEditorModelAlsoToCreatedPageView()
0476     {
0477         // GIVEN
0478         Widgets::ApplicationComponents components;
0479         // Force creation
0480         components.editorView();
0481 
0482         auto model = QObjectPtr::create();
0483         QObject *editorModel = new EditorModelStub(model.data());
0484         model->setProperty("editor", QVariant::fromValue(editorModel));
0485 
0486         // WHEN
0487         components.setModel(model);
0488 
0489         // THEN
0490         QCOMPARE(components.editorView()->model(), editorModel);
0491     }
0492 
0493     void shouldApplyRunningTaskModelToRunningTaskView()
0494     {
0495         // GIVEN
0496         Widgets::ApplicationComponents components;
0497         auto model = QObjectPtr::create();
0498         auto runningTaskModel = new RunningTaskModelStub(model.data());
0499         model->setProperty("runningTaskModel", QVariant::fromValue<Presentation::RunningTaskModelInterface*>(runningTaskModel));
0500 
0501         // WHEN
0502         components.setModel(model);
0503 
0504         // THEN
0505         QCOMPARE(components.runningTaskView()->model(), runningTaskModel);
0506     }
0507 
0508     void shouldApplyRunningTaskModelAlsoToCreatedRunningTaskView()
0509     {
0510         // GIVEN
0511         Widgets::ApplicationComponents components;
0512         // Force creation
0513         components.runningTaskView();
0514 
0515         auto model = QObjectPtr::create();
0516         auto runningTaskModel = new RunningTaskModelStub(model.data());
0517         model->setProperty("runningTaskModel", QVariant::fromValue<Presentation::RunningTaskModelInterface*>(runningTaskModel));
0518 
0519         // WHEN
0520         components.setModel(model);
0521 
0522         // THEN
0523         QCOMPARE(components.runningTaskView()->model(), runningTaskModel);
0524     }
0525 
0526 
0527     void shouldPropageNullModelsToViews()
0528     {
0529         // GIVEN
0530         Widgets::ApplicationComponents components;
0531 
0532         auto model = QObjectPtr::create();
0533         auto availableSources = new QObject(model.data());
0534         model->setProperty("availableSources", QVariant::fromValue(availableSources));
0535         auto availablePages = new QObject(model.data());
0536         model->setProperty("availablePages", QVariant::fromValue(availablePages));
0537         auto currentPage = new QObject(model.data());
0538         model->setProperty("currentPage", QVariant::fromValue(currentPage));
0539         auto editorModel = new EditorModelStub(model.data());
0540         model->setProperty("editor", QVariant::fromValue<QObject*>(editorModel));
0541         auto runningTaskModel = new RunningTaskModelStub(model.data());
0542         model->setProperty("runningTaskModel", QVariant::fromValue<Presentation::RunningTaskModelInterface*>(runningTaskModel));
0543 
0544         components.setModel(model);
0545 
0546         // WHEN
0547         components.setModel(QObjectPtr());
0548         components.availableSourcesView();
0549         components.availablePagesView();
0550         components.pageView();
0551         components.editorView();
0552         components.runningTaskView();
0553 
0554         // THEN
0555         QVERIFY(!components.availableSourcesView()->model());
0556         QVERIFY(!components.availablePagesView()->model());
0557         QVERIFY(!components.pageView()->model());
0558         QVERIFY(!components.editorView()->model());
0559         QVERIFY(!components.runningTaskView()->model());
0560     }
0561 
0562     void shouldPropageNullModelsToCreatedViews()
0563     {
0564         // GIVEN
0565         Widgets::ApplicationComponents components;
0566         components.availableSourcesView();
0567         components.availablePagesView();
0568         components.pageView();
0569         components.editorView();
0570         components.runningTaskView();
0571 
0572         auto model = QObjectPtr::create();
0573         auto availableSources = new QObject(model.data());
0574         model->setProperty("availableSources", QVariant::fromValue(availableSources));
0575         auto availablePages = new QObject(model.data());
0576         model->setProperty("availablePages", QVariant::fromValue(availablePages));
0577         auto currentPage = new QObject(model.data());
0578         model->setProperty("currentPage", QVariant::fromValue(currentPage));
0579         auto editorModel = new EditorModelStub(model.data());
0580         model->setProperty("editor", QVariant::fromValue<QObject*>(editorModel));
0581         auto runningTaskModel = new RunningTaskModelStub(model.data());
0582         model->setProperty("runningTaskModel", QVariant::fromValue<Presentation::RunningTaskModelInterface*>(runningTaskModel));
0583 
0584         components.setModel(model);
0585 
0586         // WHEN
0587         components.setModel(QObjectPtr());
0588 
0589         // THEN
0590         QVERIFY(!components.availableSourcesView()->model());
0591         QVERIFY(!components.availablePagesView()->model());
0592         QVERIFY(!components.pageView()->model());
0593         QVERIFY(!components.editorView()->model());
0594         QVERIFY(!components.runningTaskView()->model());
0595     }
0596 
0597     void shouldApplyAvailablePagesSelectionToApplicationModel()
0598     {
0599         // GIVEN
0600         auto model = ApplicationModelStub::Ptr::create();
0601 
0602         AvailablePagesModelStub availablePagesModel;
0603         model->setProperty("availablePages", QVariant::fromValue<QObject*>(&availablePagesModel));
0604         model->setProperty("currentPage", QVariant::fromValue<QObject*>(nullptr));
0605 
0606         QObject editorModel;
0607         editorModel.setProperty("task",
0608                                 QVariant::fromValue(Domain::Task::Ptr::create()));
0609         model->setProperty("editor", QVariant::fromValue<QObject*>(&editorModel));
0610 
0611         Widgets::ApplicationComponents components;
0612         components.setModel(model);
0613 
0614         Widgets::AvailablePagesView *availablePagesView = components.availablePagesView();
0615         auto pagesView = availablePagesView->findChild<QTreeView*>(QStringLiteral("pagesView"));
0616         QVERIFY(pagesView);
0617 
0618         Widgets::PageView *pageView = components.pageView();
0619         QVERIFY(pageView);
0620         QVERIFY(!pageView->model());
0621 
0622         QModelIndex index = pagesView->model()->index(0, 0);
0623 
0624         // WHEN
0625         pagesView->selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect);
0626 
0627         // THEN
0628         QCOMPARE(availablePagesModel.createdPages.size(), 1);
0629         QCOMPARE(model->property("currentPage").value<QObject*>(),
0630                  availablePagesModel.createdPages.first());
0631         QCOMPARE(pageView->model(),
0632                  availablePagesModel.createdPages.first());
0633         QVERIFY(editorModel.property("task").value<Domain::Task::Ptr>().isNull());
0634     }
0635 
0636     void shouldApplyPageViewSelectionToEditorModel()
0637     {
0638         // GIVEN
0639         auto model = QObjectPtr::create();
0640 
0641         PageModelStub pageModel;
0642         pageModel.addTask(QStringLiteral("0. First task"));
0643         pageModel.addTask(QStringLiteral("1. Second task"));
0644         pageModel.addTask(QStringLiteral("2. Third task"));
0645         pageModel.addTask(QStringLiteral("3. Yet another task"));
0646         model->setProperty("currentPage", QVariant::fromValue<QObject*>(&pageModel));
0647 
0648         EditorModelStub editorModel;
0649         model->setProperty("editor", QVariant::fromValue<QObject*>(&editorModel));
0650 
0651         Widgets::ApplicationComponents components;
0652         components.setModel(model);
0653 
0654         Widgets::PageView *pageView = components.pageView();
0655         auto centralView = pageView->findChild<QTreeView*>(QStringLiteral("centralView"));
0656         QModelIndex index = centralView->model()->index(2, 0);
0657 
0658         // WHEN
0659         centralView->selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect);
0660 
0661         // THEN
0662         QCOMPARE(editorModel.property("task").value<Domain::Task::Ptr>(),
0663                  pageModel.itemAtRow(index.row()));
0664     }
0665 
0666     void shouldHaveDefaultActionsList()
0667     {
0668         // GIVEN
0669         Widgets::ApplicationComponents components;
0670 
0671         // WHEN
0672         auto actions = components.globalActions();
0673 
0674         // THEN
0675 
0676         // availablePages view
0677         auto available = components.availablePagesView();
0678         auto availableGlobalActions = available->globalActions();
0679         for (auto it = availableGlobalActions.cbegin(); it != availableGlobalActions.cend(); ++it)
0680             QCOMPARE(actions.value(it.key()), it.value());
0681 
0682         // availableSources view
0683         auto availableSources = components.availableSourcesView();
0684         auto availableSourcesGlobalActions = availableSources->globalActions();
0685         for (auto it = availableSourcesGlobalActions.cbegin(); it != availableSourcesGlobalActions.cend(); ++it)
0686             QCOMPARE(actions.value(it.key()), it.value());
0687 
0688         // page view
0689         auto page = components.pageView();
0690         auto pageGlobalActions = page->globalActions();
0691         for (auto it = pageGlobalActions.cbegin(); it != pageGlobalActions.cend(); ++it)
0692             QCOMPARE(actions.value(it.key()), it.value());
0693 
0694         // application component own action
0695         auto moveAction = components.findChild<QAction*>(QStringLiteral("moveItemAction"));
0696         QCOMPARE(actions.value(QStringLiteral("page_view_move")), moveAction);
0697     }
0698 
0699     void shouldMoveItem()
0700     {
0701         // GIVEN
0702         auto model = QObjectPtr::create();
0703 
0704         PageModelStub pageModel;
0705         pageModel.addTask(QStringLiteral("0. First task"));
0706         pageModel.addTask(QStringLiteral("1. Second task"));
0707         pageModel.addTask(QStringLiteral("2. Third task"));
0708         pageModel.addTask(QStringLiteral("3. Yet another task"));
0709         model->setProperty("currentPage", QVariant::fromValue<QObject*>(&pageModel));
0710 
0711         AvailablePagesModelStub availablePagesModelStub;
0712         model->setProperty("availablePages", QVariant::fromValue<QObject*>(&availablePagesModelStub));
0713 
0714         QWidget *mainWidget = new QWidget;
0715         Widgets::ApplicationComponents components(mainWidget);
0716         components.setModel(model);
0717 
0718         auto availablePageView = components.availablePagesView();
0719         auto availablePagesTreeView = availablePageView->findChild<QTreeView*>(QStringLiteral("pagesView"));
0720         Q_ASSERT(availablePagesTreeView);
0721 
0722         auto dialogStub = QuickSelectDialogStub::Ptr::create();
0723         dialogStub->index = availablePagesModelStub.pageListModel()->index(0, 0); // inbox selected
0724         components.setQuickSelectDialogFactory([dialogStub] (QWidget *parent) {
0725             dialogStub->parent = parent;
0726             return dialogStub;
0727         });
0728 
0729         auto pageView = components.pageView();
0730         auto centralView = pageView->findChild<QTreeView*>(QStringLiteral("centralView"));
0731         QModelIndex index1 = pageModel.itemModel.index(0,0);
0732         QModelIndex index2 = pageModel.itemModel.index(2,0);
0733 
0734         auto filterWidget = pageView->findChild<Widgets::FilterWidget*>(QStringLiteral("filterWidget"));
0735         auto displayedModel = filterWidget->proxyModel();
0736         auto displayedIndex = displayedModel->index(0, 0);
0737         auto displayedIndex2 = displayedModel->index(2, 0);
0738 
0739         auto moveAction = components.findChild<QAction*>(QStringLiteral("moveItemAction"));
0740 
0741         // WHEN
0742         pageModel.selectedItems << index1 << index2;
0743         centralView->selectionModel()->setCurrentIndex(displayedIndex, QItemSelectionModel::ClearAndSelect);
0744         centralView->selectionModel()->setCurrentIndex(displayedIndex2, QItemSelectionModel::Select);
0745 
0746         moveAction->trigger();
0747 
0748         // THEN
0749         QCOMPARE(dialogStub->execCount, 1);
0750         QCOMPARE(dialogStub->parent, pageView);
0751         QCOMPARE(dialogStub->itemModel, availablePagesModelStub.pageListModel());
0752 
0753         QCOMPARE(availablePagesModelStub.itemModel.dropDestination, QStringLiteral("Inbox"));
0754         QCOMPARE(availablePagesModelStub.itemModel.droppedItemDataString.size(), 2);
0755         QCOMPARE(availablePagesModelStub.itemModel.droppedItemDataString.at(0), index1.data().toString());
0756         QCOMPARE(availablePagesModelStub.itemModel.droppedItemDataString.at(1), index2.data().toString());
0757     }
0758 };
0759 
0760 ZANSHIN_TEST_MAIN(ApplicationComponentsTest)
0761 
0762 #include "applicationcomponentstest.moc"