1 /*
2     SPDX-FileCopyrightText: 2006-2007 Alexander Dymo <adymo@kdevelop.org>
3 
4     SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6 
7 #include "test_areaoperation.h"
8 
9 #include <QTest>
10 #include <QListView>
11 #include <QTextEdit>
12 #include <QSplitter>
13 #include <QUrl>
14 #include <QDebug>
15 
16 #include <KSharedConfig>
17 
18 #include <sublime/view.h>
19 #include <sublime/area.h>
20 #include <sublime/sublimedefs.h>
21 #include <sublime/tooldocument.h>
22 #include <sublime/urldocument.h>
23 #include <sublime/controller.h>
24 #include <sublime/mainwindow.h>
25 #include <sublime/container.h>
26 
27 #include "areaprinter.h"
28 
29 using namespace Sublime;
30 
31 struct ViewCounter {
ViewCounterViewCounter32     ViewCounter() {}
operator ()ViewCounter33     Area::WalkerMode operator()(AreaIndex *index)
34     {
35         count += index->views().count();
36         return Area::ContinueWalker;
37     }
38     int count = 0;
39 };
40 
initTestCase()41 void TestAreaOperation::initTestCase()
42 {
43     QStandardPaths::setTestModeEnabled(true);
44 }
45 
init()46 void TestAreaOperation::init()
47 {
48     m_controller = new Controller(this);
49     Document *doc1 = new UrlDocument(m_controller, QUrl::fromLocalFile(QStringLiteral("~/foo.cpp")));
50     Document *doc2 = new UrlDocument(m_controller, QUrl::fromLocalFile(QStringLiteral("~/boo.cpp")));
51     Document *doc3 = new UrlDocument(m_controller, QUrl::fromLocalFile(QStringLiteral("~/moo.cpp")));
52     Document *doc4 = new UrlDocument(m_controller, QUrl::fromLocalFile(QStringLiteral("~/zoo.cpp")));
53 
54     //documents for tool views
55     Document *tool1 = new ToolDocument(QStringLiteral("tool1"), m_controller, new SimpleToolWidgetFactory<QListView>(QStringLiteral("tool1")));
56     Document *tool2 = new ToolDocument(QStringLiteral("tool2"), m_controller, new SimpleToolWidgetFactory<QTextEdit>(QStringLiteral("tool2")));
57     Document *tool3 = new ToolDocument(QStringLiteral("tool3"), m_controller, new SimpleToolWidgetFactory<QTextEdit>(QStringLiteral("tool3")));
58 
59     //areas (aka perspectives)
60     //view object names are in form AreaNumber.DocumentNumber.ViewNumber
61     //"tool" prefix is there for tooldocument views
62     m_area1 = new Area(m_controller, QStringLiteral("Area 1"));
63     m_pView111 = doc1->createView();
64     m_pView111->setObjectName(QStringLiteral("view1.1.1"));
65     m_area1->addView(m_pView111);
66     m_pView121 = doc2->createView();
67     m_pView121->setObjectName(QStringLiteral("view1.2.1"));
68     m_area1->addView(m_pView121);
69     m_pView122 = doc2->createView();
70     m_pView122->setObjectName(QStringLiteral("view1.2.2"));
71     m_area1->addView(m_pView122);
72     m_pView131 = doc3->createView();
73     m_pView131->setObjectName(QStringLiteral("view1.3.1"));
74     m_area1->addView(m_pView131);
75 
76     View *view = tool1->createView();
77     view->setObjectName(QStringLiteral("toolview1.1.1"));
78     m_area1->addToolView(view, Sublime::Left);
79     view = tool2->createView();
80     view->setObjectName(QStringLiteral("toolview1.2.1"));
81     m_area1->addToolView(view, Sublime::Bottom);
82     view = tool2->createView();
83     view->setObjectName(QStringLiteral("toolview1.2.2"));
84     m_area1->addToolView(view, Sublime::Bottom);
85 
86     m_area2 = new Area(m_controller, QStringLiteral("Area 2"));
87     View *view211 = doc1->createView();
88     view211->setObjectName(QStringLiteral("view2.1.1"));
89     m_area2->addView(view211);
90     View *view212 = doc1->createView();
91     view212->setObjectName(QStringLiteral("view2.1.2"));
92     m_area2->addView(view212);
93     View *view221 = doc2->createView();
94     view221->setObjectName(QStringLiteral("view2.2.1"));
95     m_area2->addView(view221, view211, Qt::Vertical);
96     View *view231 = doc3->createView();
97     view231->setObjectName(QStringLiteral("view2.3.1"));
98     m_area2->addView(view231, view221, Qt::Horizontal);
99     View *view241 = doc4->createView();
100     view241->setObjectName(QStringLiteral("view2.4.1"));
101     m_area2->addView(view241, view212, Qt::Vertical);
102     view = tool1->createView();
103     view->setObjectName(QStringLiteral("toolview2.1.1"));
104     m_area2->addToolView(view, Sublime::Bottom);
105     view = tool2->createView();
106     view->setObjectName(QStringLiteral("toolview2.2.1"));
107     m_area2->addToolView(view, Sublime::Right);
108     view = tool3->createView();
109     view->setObjectName(QStringLiteral("toolview2.3.1"));
110     m_area2->addToolView(view, Sublime::Top);
111     view = tool3->createView();
112     view->setObjectName(QStringLiteral("toolview2.3.2"));
113     m_area2->addToolView(view, Sublime::Top);
114 
115     m_area3 = new Area(m_controller, QStringLiteral("Area 3"));
116     View *view0 = doc1->createView();
117     view0->setObjectName(QStringLiteral("view3.1.1"));
118     m_area3->addView(view0);
119     View *view1 = doc2->createView();
120     view1->setObjectName(QStringLiteral("view3.1.2"));
121     m_area3->addView(view1, view0);
122     View *view2 = doc3->createView();
123     view2->setObjectName(QStringLiteral("view3.1.3"));
124     m_area3->addView(view2, view1);
125     View *view3 = doc4->createView();
126     view3->setObjectName(QStringLiteral("view3.1.4"));
127     m_area3->addView(view3, view1);
128 
129     m_controller->addDefaultArea(m_area1);
130     m_controller->addDefaultArea(m_area2);
131     m_controller->addDefaultArea(m_area3);
132 
133 }
134 
cleanup()135 void TestAreaOperation::cleanup()
136 {
137     delete m_area1;
138     delete m_area2;
139     delete m_controller;
140     m_area1 = nullptr;
141     m_area2 = nullptr;
142     m_controller = nullptr;
143 }
144 
areaConstruction()145 void TestAreaOperation::areaConstruction()
146 {
147     //check if areas has proper object names
148     QCOMPARE(m_area1->objectName(), QStringLiteral("Area 1"));
149     QCOMPARE(m_area2->objectName(), QStringLiteral("Area 2"));
150 
151     //check that area1 contents is properly initialised
152     AreaViewsPrinter viewsPrinter1;
153     m_area1->walkViews(viewsPrinter1, m_area1->rootIndex());
154     QCOMPARE(viewsPrinter1.result, QStringLiteral("\n\
155 [ view1.1.1 view1.2.1 view1.2.2 view1.3.1 ]\n\
156 "));
157     AreaToolViewsPrinter toolViewsPrinter1;
158     m_area1->walkToolViews(toolViewsPrinter1, Sublime::AllPositions);
159     QCOMPARE(toolViewsPrinter1.result, QStringLiteral("\n\
160 toolview1.1.1 [ left ]\n\
161 toolview1.2.1 [ bottom ]\n\
162 toolview1.2.2 [ bottom ]\n\
163 "));
164 
165     //check that area2 contents is properly initialised
166     AreaViewsPrinter viewsPrinter2;
167     m_area2->walkViews(viewsPrinter2, m_area2->rootIndex());
168     QCOMPARE(viewsPrinter2.result, QStringLiteral("\n\
169 [ vertical splitter ]\n\
170     [ vertical splitter ]\n\
171         [ view2.1.1 view2.1.2 ]\n\
172         [ view2.4.1 ]\n\
173     [ horizontal splitter ]\n\
174         [ view2.2.1 ]\n\
175         [ view2.3.1 ]\n\
176 "));
177     AreaToolViewsPrinter toolViewsPrinter2;
178     m_area2->walkToolViews(toolViewsPrinter2, Sublime::AllPositions);
179     QCOMPARE(toolViewsPrinter2.result, QStringLiteral("\n\
180 toolview2.1.1 [ bottom ]\n\
181 toolview2.2.1 [ right ]\n\
182 toolview2.3.1 [ top ]\n\
183 toolview2.3.2 [ top ]\n\
184 "));
185 }
186 
mainWindowConstruction()187 void TestAreaOperation::mainWindowConstruction()
188 {
189     //====== check for m_area1 ======
190     MainWindow mw1(m_controller);
191     m_controller->showArea(m_area1, &mw1);
192     checkArea1(&mw1);
193 
194 /////////////
195  //====== check for m_area2 ======
196     MainWindow mw2(m_controller);
197     m_controller->showArea(m_area2, &mw2);
198     checkArea2(&mw2);
199 }
200 
checkArea1(MainWindow * mw)201 void TestAreaOperation::checkArea1(MainWindow *mw)
202 {
203     Area *area = mw->area();
204     //check that all docks have their widgets
205     const auto toolDocks = mw->toolDocks();
206     for (View* dock : toolDocks) {
207         //QVERIFY(dock->widget() != 0);
208         QVERIFY(dock->hasWidget());
209     }
210     QCOMPARE(toolDocks.count(), area->toolViews().count());
211 
212     //check that mainwindow have all splitters and widgets in splitters inside centralWidget
213     QWidget *central = mw->centralWidget();
214     QVERIFY(central != nullptr);
215     QVERIFY(central->inherits("QWidget"));
216 
217     QWidget *splitter = central->findChild<QSplitter*>();
218     QVERIFY(splitter);
219     QVERIFY(splitter->inherits("QSplitter"));
220 
221     //check that we have a container and 4 views inside
222     auto *container = splitter->findChild<Sublime::Container*>();
223     QVERIFY(container);
224     ViewCounter c;
225     area->walkViews(c, area->rootIndex());
226     QCOMPARE(container->count(), c.count);
227     for (int i = 0; i < container->count(); ++i)
228         QVERIFY(container->widget(i) != nullptr);
229 }
230 
checkArea2(MainWindow * mw)231 void TestAreaOperation::checkArea2(MainWindow *mw)
232 {
233     Area *area = mw->area();
234     //check that all docks have their widgets
235     const auto toolDocks = mw->toolDocks();
236     for (View* dock : toolDocks) {
237         //QVERIFY(dock->widget() != 0);
238         QVERIFY(dock->hasWidget());
239     }
240     QCOMPARE(toolDocks.count(), area->toolViews().count());
241 
242     //check that mainwindow have all splitters and widgets in splitters inside centralWidget
243     QWidget *central = mw->centralWidget();
244     QVERIFY(central != nullptr);
245     QVERIFY(central->inherits("QWidget"));
246 
247     QWidget *splitter = central->findChild<QSplitter*>();
248     QVERIFY(splitter);
249     QVERIFY(splitter->inherits("QSplitter"));
250 
251     //check that we have 4 properly initialized containers
252     const QList<Container*> containers = splitter->findChildren<Sublime::Container*>();
253     QCOMPARE(containers.count(), 4);
254 
255     int widgetCount = 0;
256     for (Container* c : containers) {
257         for (int i = 0; i < c->count(); ++i)
258             QVERIFY(c->widget(i) != nullptr);
259         widgetCount += c->count();
260     }
261 
262     ViewCounter c;
263     area->walkViews(c, area->rootIndex());
264     QCOMPARE(widgetCount, c.count);
265 
266     //check that we have 7 splitters: 2 vertical and 1 horizontal, rest is not split
267     QList<QSplitter*> splitters = splitter->findChildren<QSplitter*>();
268     splitters.append(qobject_cast<QSplitter*>(splitter));
269     QCOMPARE(splitters.count(), 6+1); //6 child splitters + 1 central itself = 7 splitters
270     int verticalSplitterCount = 0;
271     int horizontalSplitterCount = 0;
272     for (QSplitter* s : qAsConst(splitters)) {
273         if (s->count() == 1)
274             continue;   //this is a splitter with container inside, its orientation is not relevant
275         if (s->orientation() == Qt::Vertical)
276             verticalSplitterCount += 1;
277         else
278             horizontalSplitterCount += 1;
279     }
280     QCOMPARE(verticalSplitterCount, 2);
281     QCOMPARE(horizontalSplitterCount, 1);
282 }
283 
areaCloning()284 void TestAreaOperation::areaCloning()
285 {
286     //show m_area1 in MainWindow1
287     MainWindow mw1(m_controller);
288     m_controller->showArea(m_area1, &mw1);
289     checkArea1(&mw1);
290 
291     //now try to show the same area in MainWindow2 and check that we get a clone
292     MainWindow mw2(m_controller);
293     m_controller->showArea(m_area1, &mw2);
294 
295     //two mainwindows have different areas
296     QVERIFY(mw1.area() != mw2.area());
297     //the area for the second mainwindow is a clone of the
298     //original area and should have the same name.
299     QVERIFY(mw2.area()->objectName() == mw1.area()->objectName());
300 
301     //check mainwindow layouts - original and copy
302     checkArea1(&mw1);
303     checkArea1(&mw2);
304 }
305 
306 /*! Functor used by areaSwitchingInSameMainWindow()
307     Walks all Views and checks if they got a widget.
308     hasWidget will be set to false if any View lacks a widget.*/
309 struct AreaWidgetChecker {
310     AreaWidgetChecker() = default;
operator ()AreaWidgetChecker311     Area::WalkerMode operator()(AreaIndex *index)
312     {
313         for (View* view : qAsConst(index->views())) {
314             if (!view->hasWidget()) {
315                 failureMessage += view->objectName() + " has no widget\n";
316                 foundViewWithoutWidget = true;
317             }
318         }
319         return Area::ContinueWalker;
320     }
operator ()AreaWidgetChecker321     Area::WalkerMode operator()(View *view, Sublime::Position)
322     {
323         if (!view->hasWidget()) {
324             foundViewWithoutWidget = true;
325             failureMessage += view->objectName() + " has no widget\n";
326         }
327         return Area::ContinueWalker;
328     }
329 
330     bool foundViewWithoutWidget = false;
331     QString failureMessage;
332 };
333 
areaSwitchingInSameMainwindow()334 void TestAreaOperation::areaSwitchingInSameMainwindow()
335 {
336     MainWindow mw(m_controller);
337     m_controller->showArea(m_area1, &mw);
338     checkArea1(&mw);
339 
340     m_controller->showArea(m_area2, &mw);
341     checkArea2(&mw);
342 
343     //check what happened to area1 widgets, they should be intact
344     AreaWidgetChecker checker;
345     m_area1->walkViews(checker, m_area1->rootIndex());
346     m_area1->walkToolViews(checker, Sublime::AllPositions);
347     QVERIFY2(!checker.foundViewWithoutWidget, checker.failureMessage.toLatin1().data());
348 }
349 
simpleViewAdditionAndDeletion()350 void TestAreaOperation::simpleViewAdditionAndDeletion()
351 {
352     // set TabBarOpenAfterCurrent=0, otherwise we'd have a different order of tabs
353     int oldTabBarOpenAfterCurrent;
354     {
355         KConfigGroup uiGroup = KSharedConfig::openConfig()->group("UiSettings");
356         oldTabBarOpenAfterCurrent = uiGroup.readEntry("TabBarOpenAfterCurrent", 1);
357         uiGroup.writeEntry("TabBarOpenAfterCurrent", 0);
358         uiGroup.sync();
359     }
360     m_controller->loadSettings();
361 
362     MainWindow mw(m_controller);
363     m_controller->addMainWindow(&mw);
364 
365     m_controller->showArea(m_area1, &mw);
366     checkArea1(&mw);
367 
368     Document *doc5 = new UrlDocument(m_controller, QUrl::fromLocalFile(QStringLiteral("~/new.cpp")));
369     View *view = doc5->createView();
370     view->setObjectName(QStringLiteral("view1.5.1"));
371     m_area1->addView(view);
372 
373     checkAreaViewsDisplay(&mw, m_area1,
374         QStringLiteral("\n[ view1.1.1 view1.2.1 view1.2.2 view1.3.1 view1.5.1 ]\n"),
375         1, 1, QStringLiteral("Added an url view (view1.5.1)"));
376 
377     //now remove view and check that area is valid
378     delete m_area1->removeView(view);
379 
380     checkAreaViewsDisplay(&mw, m_area1,
381         QStringLiteral("\n[ view1.1.1 view1.2.1 view1.2.2 view1.3.1 ]\n"),
382         1, 1, QStringLiteral("Removed the url view (view1.5.1)"));
383 
384     //now remove all other views one by one and leave an empty container
385     const QList<View*> list(m_area1->views());
386     for (View* view : list) {
387         delete m_area1->removeView(view);
388     }
389 
390     checkAreaViewsDisplay(&mw, m_area1,
391         QStringLiteral("\n[ horizontal splitter ]\n"),
392         0, 1, QStringLiteral("Removed all views. Only horizontal splitter should remain."));
393 
394     //add a view again and check that mainwindow is correctly reconstructed
395     view = doc5->createView();
396     view->setObjectName(QStringLiteral("view1.5.1"));
397     m_area1->addView(view);
398 
399     checkAreaViewsDisplay(&mw, m_area1,
400         QStringLiteral("\n[ view1.5.1 ]\n"),
401         1, 1, QStringLiteral("Added a single view to previously emptied mainwindow."));
402 
403     {
404         KConfigGroup uiGroup = KSharedConfig::openConfig()->group("UiSettings");
405         uiGroup.writeEntry("TabBarOpenAfterCurrent", oldTabBarOpenAfterCurrent);
406         uiGroup.sync();
407     }
408     m_controller->loadSettings();
409 }
410 
complexViewAdditionAndDeletion()411 void TestAreaOperation::complexViewAdditionAndDeletion()
412 {
413     Area *area = m_area2;
414     MainWindow mw(m_controller);
415     m_controller->addMainWindow(&mw);
416 
417     m_controller->showArea(m_area2, &mw);
418 
419     Document *doc5 = new UrlDocument(m_controller, QUrl::fromLocalFile(QStringLiteral("~/new.cpp")));
420     View *view = doc5->createView();
421     view->setObjectName(QStringLiteral("view2.5.1"));
422 
423     View *view221 = findNamedView(area, QStringLiteral("view2.2.1"));
424     QVERIFY(view221);
425     area->addView(view, view221, Qt::Vertical);
426 
427     checkAreaViewsDisplay(&mw, area, QStringLiteral("\n\
428 [ vertical splitter ]\n\
429     [ vertical splitter ]\n\
430         [ view2.1.1 view2.1.2 ]\n\
431         [ view2.4.1 ]\n\
432     [ horizontal splitter ]\n\
433         [ vertical splitter ]\n\
434             [ view2.2.1 ]\n\
435             [ view2.5.1 ]\n\
436         [ view2.3.1 ]\n\
437 "), 5, 8+1);
438 
439     //now delete view221
440     delete area->removeView(view221);
441 
442     checkAreaViewsDisplay(&mw, area, QStringLiteral("\n\
443 [ vertical splitter ]\n\
444     [ vertical splitter ]\n\
445         [ view2.1.1 view2.1.2 ]\n\
446         [ view2.4.1 ]\n\
447     [ horizontal splitter ]\n\
448         [ view2.5.1 ]\n\
449         [ view2.3.1 ]\n\
450 "), 4, 6+1);
451 
452     //remove one more view, this time the one inside non-empty container
453     View *view211 = findNamedView(area, QStringLiteral("view2.1.1"));
454     delete m_area2->removeView(view211);
455 
456     checkAreaViewsDisplay(&mw, area, QStringLiteral("\n\
457 [ vertical splitter ]\n\
458     [ vertical splitter ]\n\
459         [ view2.1.2 ]\n\
460         [ view2.4.1 ]\n\
461     [ horizontal splitter ]\n\
462         [ view2.5.1 ]\n\
463         [ view2.3.1 ]\n\
464 "), 4, 6+1);
465 
466     //and now remove all remaining views one by one
467     delete m_area2->removeView(findNamedView(area, QStringLiteral("view2.1.2")));
468     checkAreaViewsDisplay(&mw, area, QStringLiteral("\n\
469 [ vertical splitter ]\n\
470     [ view2.4.1 ]\n\
471     [ horizontal splitter ]\n\
472         [ view2.5.1 ]\n\
473         [ view2.3.1 ]\n\
474 "), 3, 4+1);
475 
476     delete m_area2->removeView(findNamedView(area, QStringLiteral("view2.4.1")));
477     checkAreaViewsDisplay(&mw, area, QStringLiteral("\n\
478 [ horizontal splitter ]\n\
479     [ view2.5.1 ]\n\
480     [ view2.3.1 ]\n\
481 "), 2, 2+1);
482 
483     delete m_area2->removeView(findNamedView(area, QStringLiteral("view2.5.1")));
484     checkAreaViewsDisplay(&mw, area, QStringLiteral("\n\
485 [ view2.3.1 ]\n\
486 "), 1, 1);
487 
488     delete m_area2->removeView(findNamedView(area, QStringLiteral("view2.3.1")));
489     checkAreaViewsDisplay(&mw, area, QStringLiteral("\n\
490 [ horizontal splitter ]\n\
491 "), 0, 1);
492 }
493 
toolViewAdditionAndDeletion()494 void TestAreaOperation::toolViewAdditionAndDeletion()
495 {
496     MainWindow mw(m_controller);
497     m_controller->showArea(m_area1, &mw);
498     checkArea1(&mw);
499 
500     Document *tool4 = new ToolDocument(QStringLiteral("tool4"), m_controller, new SimpleToolWidgetFactory<QTextEdit>(QStringLiteral("tool4")));
501     View *view = tool4->createView();
502     view->setObjectName(QStringLiteral("toolview1.4.1"));
503     m_area1->addToolView(view, Sublime::Right);
504 
505     //check that area is in valid state
506     AreaToolViewsPrinter toolViewsPrinter1;
507     m_area1->walkToolViews(toolViewsPrinter1, Sublime::AllPositions);
508     QCOMPARE(toolViewsPrinter1.result, QStringLiteral("\n\
509 toolview1.1.1 [ left ]\n\
510 toolview1.2.1 [ bottom ]\n\
511 toolview1.2.2 [ bottom ]\n\
512 toolview1.4.1 [ right ]\n\
513 "));
514 
515     //check that mainwindow has newly added tool view
516     {
517     const auto toolDocks = mw.toolDocks();
518     for (View* dock : toolDocks) {
519         QVERIFY(dock->widget() != nullptr);
520     }
521     QCOMPARE(toolDocks.count(), m_area1->toolViews().count());
522     }
523 
524     //now remove tool view
525     m_area1->removeToolView(view);
526 
527     AreaToolViewsPrinter toolViewsPrinter2;
528     //check that area doesn't have it anymore
529     m_area1->walkToolViews(toolViewsPrinter2, Sublime::AllPositions);
530     QCOMPARE(toolViewsPrinter2.result, QStringLiteral("\n\
531 toolview1.1.1 [ left ]\n\
532 toolview1.2.1 [ bottom ]\n\
533 toolview1.2.2 [ bottom ]\n\
534 "));
535 
536     //check that mainwindow has newly added tool view
537     {
538     const auto toolDocks = mw.toolDocks();
539     for (View* dock : toolDocks) {
540         QVERIFY(dock->widget() != nullptr);
541     }
542     QCOMPARE(toolDocks.count(), m_area1->toolViews().count());
543     }
544 }
545 
546 
547 
testAddingViewAfter()548 void TestAreaOperation::testAddingViewAfter()
549 {
550 
551     const QList<View*> list(m_area3->views());
552     for (View* view : list) {
553         qDebug() << "name of view : " << view->objectName() << " , it's index : " << m_area3->views().indexOf(view);
554     }
555 
556 }
557 
558 ////////////////////////////////////////////////////////////////////////////////
559 ////////////////////////////////////////////////////////////////////////////////
splitViewActiveTabsTest()560 void TestAreaOperation::splitViewActiveTabsTest()
561 {
562     MainWindow mw(m_controller);
563     m_controller->showArea(m_area1, &mw);
564     checkArea1(&mw);
565 
566     // at first show of the area, the active view should be m_pView111
567     QCOMPARE(mw.activeView(), m_pView111);
568 
569     // Try to get to the main container :
570     // get the central widget
571     QWidget *pCentral = mw.centralWidget();
572     QVERIFY(pCentral);
573     QVERIFY(pCentral->inherits("QWidget"));
574 
575     // get its first splitter
576     QWidget *pSplitter = pCentral->findChild<QSplitter*>();
577     QVERIFY(pSplitter);
578     QVERIFY(pSplitter->inherits("QSplitter"));
579 
580     // finally, get the splitter's container
581     auto *pContainer = pSplitter->findChild<Sublime::Container*>();
582     QVERIFY(pContainer);
583 
584     // verify that the current active widget in the container is the one in activeview (m_pView111)
585     QCOMPARE(pContainer->currentWidget(), mw.activeView()->widget());
586 
587     // activate the second tab of the area (view212)
588     mw.activateView(m_pView121);
589 
590     // verify that the active view was correctly updated to m_pView121
591     QCOMPARE(mw.activeView(), m_pView121);
592 
593     // check if the container's current widget was updated to the active view's
594     QCOMPARE(pContainer->currentWidget(), mw.activeView()->widget());
595 
596     // now, create a split view of the active view (m_pView121)
597     Sublime::View *pNewView = mw.activeView()->document()->createView();
598     pNewView->setObjectName("splitOf" + mw.activeView()->objectName());
599     m_area1->addView(pNewView, mw.activeView(), Qt::Vertical);
600 
601     // verify that creating a new view did not break the central widget
602     QCOMPARE(pCentral, mw.centralWidget());
603 
604     // verify that creating a new view did not break the main splitter
605     QCOMPARE(pSplitter, pCentral->findChild<QSplitter*>());
606 
607     // creating a new view created two new children splitters, get them
608     QVERIFY(pSplitter->findChildren<QSplitter*>().size() == 2);
609     QWidget *pFirstSplitter = pSplitter->findChildren<QSplitter*>().at(0);
610     QVERIFY(pFirstSplitter);
611     QWidget *pSecondSplitter = pSplitter->findChildren<QSplitter*>().at(1);
612     QVERIFY(pSecondSplitter);
613 
614     // for each splitter, get the corresponding container
615     auto *pFirstContainer = pFirstSplitter->findChild<Sublime::Container*>();
616     QVERIFY(pFirstContainer);
617     auto *pSecondContainer = pSecondSplitter->findChild<Sublime::Container*>();
618     QVERIFY(pSecondContainer);
619 
620     // the active view should have remained view121
621     QCOMPARE(mw.activeView(), m_pView121);
622 
623     // pFirstContainer should contain the newView's widget
624     QVERIFY(pFirstContainer->hasWidget(pNewView->widget()));
625 
626     // the new view's widget should be the current widget of the new container
627     QCOMPARE(pFirstContainer->currentWidget(), pNewView->widget());
628 
629     // pSecondContainer should contain all the old views widgets
630     QVERIFY(pSecondContainer->hasWidget(m_pView111->widget()));
631     QVERIFY(pSecondContainer->hasWidget(m_pView121->widget()));
632     QVERIFY(pSecondContainer->hasWidget(m_pView122->widget()));
633     QVERIFY(pSecondContainer->hasWidget(m_pView131->widget()));
634 
635     // the active widget should be the current widget of the second container
636     QCOMPARE(pSecondContainer->currentWidget(), mw.activeView()->widget());
637 
638     ////////////////////////////////////////////////////////////////////////////
639     // now, activate the new view and check if all went well
640     mw.activateView(pNewView);
641 
642     // active view should now be newView
643     QCOMPARE(mw.activeView(), pNewView);
644 
645     // the active widget should be the current widget of the new container
646     QCOMPARE(pFirstContainer->currentWidget(), mw.activeView()->widget());
647 
648     // the current widget of the old container should have remained view121's
649     QCOMPARE(pSecondContainer->currentWidget(), m_pView121->widget());
650 
651     ////////////////////////////////////////////////////////////////////////////
652     // now delete newView and check area state
653     delete m_area1->removeView(pNewView);
654 
655     // verify that deleting the view did not broke the central widget
656     QCOMPARE(pCentral, mw.centralWidget());
657 
658     // removing the view should have destroyed the sub splitters and containers,
659     // so get the main one and verify that deleting the view did not break it
660     QCOMPARE(pSplitter, pCentral->findChild<QSplitter*>());
661 
662     // get the new container inside the main splitter
663     pContainer = pSplitter->findChild<Sublime::Container*>();
664     QVERIFY(pContainer);
665 
666     // active view should now be back to m_pView121 again
667     QCOMPARE(mw.activeView(), m_pView121);
668 
669     // check also the container current widget
670     QCOMPARE(pContainer->currentWidget(), mw.activeView()->widget());
671 }
672 
checkAreaViewsDisplay(MainWindow * mw,Area * area,const QString & printedAreas,int containerCount,int splitterCount,const QString & location)673 void TestAreaOperation::checkAreaViewsDisplay(MainWindow *mw, Area *area,
674     const QString &printedAreas, int containerCount, int splitterCount, const QString& location)
675 {
676     //check area
677     AreaViewsPrinter viewsPrinter;
678     area->walkViews(viewsPrinter, area->rootIndex());
679     QCOMPARE(viewsPrinter.result, printedAreas);
680 
681     //check mainwindow
682     QWidget *central = mw->centralWidget();
683     QVERIFY(central != nullptr);
684     QVERIFY(central->inherits("QWidget"));
685 
686     QWidget *splitter = central->findChild<QSplitter*>();
687     QVERIFY(splitter);
688     QVERIFY(splitter->inherits("QSplitter"));
689 
690     //check containers
691     const QList<Container*> containers = splitter->findChildren<Sublime::Container*>();
692     QString failMsg = QStringLiteral("\nFailure while checking area contents @ %1\n"
693                               "Expected %2 containers in central splitter but got %3 \n").
694                       arg(location).arg(containerCount).arg(containers.count());
695     QVERIFY2(containers.count() == containerCount, failMsg.toLatin1().data());
696 
697     int widgetCount = 0;
698     for (Container* c : containers) {
699         for (int i = 0; i < c->count(); ++i)
700         {
701             QVERIFY(c->widget(i) != nullptr);
702             QVERIFY(c->widget(i)->parentWidget() != nullptr);
703         }
704         widgetCount += c->count();
705     }
706 
707     ViewCounter c;
708     area->walkViews(c, area->rootIndex());
709     QCOMPARE(widgetCount, c.count);
710 
711     QList<QSplitter*> splitters = splitter->findChildren<QSplitter*>();
712     splitters.append(qobject_cast<QSplitter*>(splitter));
713     QCOMPARE(splitters.count(), splitterCount);
714 }
715 
findNamedView(Area * area,const QString & name)716 View *TestAreaOperation::findNamedView(Area *area, const QString &name)
717 {
718     const auto views = area->views();
719     for (View* view : views) {
720         if (view->objectName() == name)
721             return view;
722     }
723     return nullptr;
724 }
725 
726 ///////////
727 QTEST_MAIN(TestAreaOperation)
728