File indexing completed on 2024-05-19 04:39:50

0001 /*
0002     SPDX-FileCopyrightText: 2007 Alexander Dymo <adymo@kdevelop.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "test_viewactivation.h"
0008 
0009 #include <QTest>
0010 #include <QSignalSpy>
0011 
0012 #include <QListView>
0013 #include <QTextEdit>
0014 #include <QDockWidget>
0015 #include <QFocusEvent>
0016 #include <QStandardPaths>
0017 
0018 #include <sublime/view.h>
0019 #include <sublime/area.h>
0020 #include <sublime/controller.h>
0021 #include <sublime/mainwindow.h>
0022 #include <sublime/container.h>
0023 #include <sublime/tooldocument.h>
0024 
0025 using namespace Sublime;
0026 
0027 template <class Widget>
0028 class SpecialWidgetFactory: public SimpleToolWidgetFactory<Widget> {
0029 public:
0030     explicit SpecialWidgetFactory(const QString &id): SimpleToolWidgetFactory<Widget>(id) {}
0031     QWidget* create(ToolDocument *doc, QWidget *parent = nullptr) override
0032     {
0033         auto* w = new QWidget(parent);
0034         auto *inner = new Widget(w);
0035         inner->setObjectName(doc->title()+"_inner");
0036         w->setObjectName(doc->title()+"_outer");
0037         return w;
0038     }
0039 };
0040 
0041 void TestViewActivation::initTestCase()
0042 {
0043     QStandardPaths::setTestModeEnabled(true);
0044     qRegisterMetaType<View*>("View*");
0045 }
0046 
0047 void TestViewActivation::init()
0048 {
0049     controller = new Controller(this);
0050     doc1 = new ToolDocument(QStringLiteral("doc1"), controller, new SimpleToolWidgetFactory<QListView>(QStringLiteral("doc1")));
0051     //this document will create special widgets - QListView nested in QWidget
0052     doc2 = new ToolDocument(QStringLiteral("doc2"), controller, new SpecialWidgetFactory<QListView>(QStringLiteral("doc2")));
0053     doc3 = new ToolDocument(QStringLiteral("doc3"), controller, new SimpleToolWidgetFactory<QListView>(QStringLiteral("doc3")));
0054     doc4 = new ToolDocument(QStringLiteral("doc4"), controller, new SimpleToolWidgetFactory<QListView>(QStringLiteral("doc4")));
0055 
0056     tool1 = new ToolDocument(QStringLiteral("tool1"), controller, new SimpleToolWidgetFactory<QListView>(QStringLiteral("tool1")));
0057     tool2 = new ToolDocument(QStringLiteral("tool2"), controller, new SimpleToolWidgetFactory<QTextEdit>(QStringLiteral("tool2")));
0058     tool3 = new ToolDocument(QStringLiteral("tool3"), controller, new SimpleToolWidgetFactory<QTextEdit>(QStringLiteral("tool3")));
0059 
0060     area = new Area(controller, QStringLiteral("Area"));
0061 
0062     view211 = doc1->createView();
0063     view211->setObjectName(QStringLiteral("view211"));
0064     area->addView(view211);
0065     view212 = doc1->createView();
0066     view212->setObjectName(QStringLiteral("view212"));
0067     area->addView(view212);
0068     view221 = doc2->createView();
0069     area->addView(view221, view211, Qt::Vertical);
0070     view231 = doc3->createView();
0071     area->addView(view231, view221, Qt::Horizontal);
0072     view241 = doc4->createView();
0073     area->addView(view241, view212, Qt::Vertical);
0074     viewT11 = tool1->createView();
0075     area->addToolView(viewT11, Sublime::Bottom);
0076     viewT21 = tool2->createView();
0077     area->addToolView(viewT21, Sublime::Right);
0078     viewT31 = tool3->createView();
0079     area->addToolView(viewT31, Sublime::Top);
0080     viewT32 = tool3->createView();
0081     area->addToolView(viewT32, Sublime::Top);
0082 }
0083 
0084 void TestViewActivation::cleanup()
0085 {
0086     delete controller;
0087 }
0088 
0089 void TestViewActivation::signalsOnViewCreationAndDeletion()
0090 {
0091     auto *controller = new Controller(this);
0092     auto* doc1 = new ToolDocument(QStringLiteral("doc1"), controller, new SimpleToolWidgetFactory<QListView>(QStringLiteral("doc1")));
0093     Area *area = new Area(controller, QStringLiteral("Area"));
0094 
0095     QSignalSpy spy(controller, SIGNAL(viewAdded(Sublime::View*)));
0096     View *v = doc1->createView();
0097     area->addView(v);
0098     QCOMPARE(spy.count(), 1);
0099 
0100     QSignalSpy spy2(controller, SIGNAL(aboutToRemoveView(Sublime::View*)));
0101     area->removeView(v);
0102     QCOMPARE(spy2.count(), 1);
0103 
0104     QSignalSpy spy3(controller, SIGNAL(toolViewAdded(Sublime::View*)));
0105     v = doc1->createView();
0106     area->addToolView(v, Sublime::Bottom);
0107     QCOMPARE(spy3.count(), 1);
0108 
0109     QSignalSpy spy4(controller, SIGNAL(aboutToRemoveToolView(Sublime::View*)));
0110     area->removeToolView(v);
0111     QCOMPARE(spy4.count(), 1);
0112 
0113     delete controller;
0114 }
0115 
0116 void TestViewActivation::viewActivation()
0117 {
0118     auto* mw = new MainWindow(controller);
0119     controller->addDefaultArea(area); // Q_ASSERT without this.
0120     controller->addMainWindow(mw);
0121 
0122     controller->showArea(area, mw);
0123     //we should have an active view immediately after the area is shown
0124     QCOMPARE(mw->activeView(), view211);
0125 
0126     //add some widgets that are not in layout
0127     auto *breaker = new QTextEdit(mw);
0128     breaker->setObjectName(QStringLiteral("breaker"));
0129     auto *toolBreaker = new QTextEdit(mw);
0130     toolBreaker->setObjectName(QStringLiteral("toolBreaker"));
0131 
0132     auto* dock = new QDockWidget(mw);
0133     dock->setWidget(toolBreaker);
0134     mw->addDockWidget(Qt::LeftDockWidgetArea, dock);
0135 
0136     QFocusEvent focusEvent(QEvent::FocusIn);
0137     //now post events to the widgets and see if mainwindow has the right active views
0138     //activate view
0139     qApp->sendEvent(view212->widget(), &focusEvent);
0140     QString failMsg = QStringLiteral("\nWas expecting %1 to be active but got %2").
0141                       arg(view212->objectName(), mw->activeView()->objectName());
0142     QVERIFY2(mw->activeView() == view212, failMsg.toLatin1().data());
0143 
0144     //activate tool view and check that both view and tool view are active
0145     qApp->sendEvent(viewT31->widget(), &focusEvent);
0146     QCOMPARE(mw->activeView(), view212);
0147     QCOMPARE(mw->activeToolView(), viewT31);
0148 
0149     //active another view
0150     qApp->sendEvent(view241->widget(), &focusEvent);
0151     QCOMPARE(mw->activeView(), view241);
0152     QCOMPARE(mw->activeToolView(), viewT31);
0153 
0154     //focus a widget not in the area
0155     qApp->sendEvent(breaker, &focusEvent);
0156     QCOMPARE(mw->activeView(), view241);
0157     QCOMPARE(mw->activeToolView(), viewT31);
0158 
0159     //focus a dock not in the area
0160     qApp->sendEvent(toolBreaker, &focusEvent);
0161     QCOMPARE(mw->activeView(), view241);
0162     QCOMPARE(mw->activeToolView(), viewT31);
0163 
0164     //focus inner widget for view221
0165     auto *inner = mw->findChild<QListView*>(QStringLiteral("doc2_inner"));
0166     QVERIFY(inner);
0167     qApp->sendEvent(inner, &focusEvent);
0168     QCOMPARE(mw->activeView(), view221);
0169     QCOMPARE(mw->activeToolView(), viewT31);
0170 }
0171 
0172 void TestViewActivation::activationInMultipleMainWindows()
0173 {
0174     MainWindow mw(controller);
0175     controller->showArea(area, &mw);
0176     QCOMPARE(mw.activeView(), view211);
0177 
0178     //check that new mainwindow always have active view right after displaying area
0179     MainWindow mw2(controller);
0180     controller->showArea(area, &mw2);
0181     QVERIFY(mw2.activeView());
0182     QCOMPARE(mw2.activeView()->document(), doc1);
0183 }
0184 
0185 void TestViewActivation::activationAfterViewRemoval()
0186 {
0187     MainWindow mw(controller);
0188     controller->showArea(area, &mw);
0189     QCOMPARE(mw.activeView(), view211);
0190 
0191     //check what happens if we remove a view which is not the only one in container
0192     delete area->removeView(view211);
0193     QCOMPARE(mw.activeView(), view212);
0194 
0195     //check what happens if we remove a view which is alone in container
0196     mw.activateView(view231);
0197     QCOMPARE(mw.activeView(), view231);
0198     delete area->removeView(view231);
0199     QCOMPARE(mw.activeView(), view221);
0200 }
0201 
0202 void TestViewActivation::activationAfterRemovalSimplestCase()
0203 {
0204     //we don't have split views - just two views in one area index
0205     MainWindow mw(controller);
0206     Area *area = new Area(controller, QStringLiteral("Area"));
0207     View *v1 = doc1->createView();
0208     View *v2 = doc2->createView();
0209     area->addView(v1);
0210     area->addView(v2, v1);
0211     controller->showArea(area, &mw);
0212     mw.activateView(v2);
0213 
0214     //delete active view and check that previous is activated
0215     delete area->removeView(v2);
0216     QCOMPARE(mw.activeView(), v1);
0217 }
0218 
0219 QTEST_MAIN(TestViewActivation)
0220 
0221 #include "moc_test_viewactivation.cpp"