From 1443eff1d903d96ab6d4e5a8e3250db2b826cefb Mon Sep 17 00:00:00 2001 From: Sergio Martins Date: Tue, 10 Nov 2020 18:00:19 +0000 Subject: [PATCH] tests: Port some tests to QtQuick 15 to go --- tests/tst_common.cpp | 361 +++++++++++++++++++++++++++++++++++++++++++ tests/tst_docks.cpp | 360 ------------------------------------------ 2 files changed, 361 insertions(+), 360 deletions(-) diff --git a/tests/tst_common.cpp b/tests/tst_common.cpp index 098a01de..00a3e713 100644 --- a/tests/tst_common.cpp +++ b/tests/tst_common.cpp @@ -43,6 +43,7 @@ # include # include # include +# include #endif #ifdef Q_OS_WIN @@ -223,6 +224,8 @@ private Q_SLOTS: void tst_lastFloatingPositionIsRestored(); void tst_negativeAnchorPositionWhenEmbedded(); void tst_negativeAnchorPositionWhenEmbedded_data(); + void tst_floatingAction(); + void tst_raise(); #ifdef KDDOCKWIDGETS_QTWIDGETS // TODO: Port these to QtQuick @@ -233,6 +236,7 @@ private Q_SLOTS: void tst_dragByTabBar(); void tst_dragBySingleTab(); void tst_mainWindowAlwaysHasCentralWidget(); + void tst_dockableMainWindows(); #endif }; @@ -5017,6 +5021,75 @@ void TestCommon::tst_mainWindowAlwaysHasCentralWidget() delete dock->window(); } +void TestCommon::tst_dockableMainWindows() +{ + EnsureTopLevelsDeleted e; + + auto m1 = createMainWindow(); + auto dock1 = createDockWidget("dock1", new QPushButton("foo")); + m1->addDockWidget(dock1, Location_OnTop); + + auto m2 = new KDDockWidgets::MainWindow("mainwindow-dockable"); + auto m2Container = createDockWidget("mainwindow-dw", m2); + auto menubar = m2->menuBar(); + menubar->addMenu("File"); + menubar->addMenu("View"); + menubar->addMenu("Help"); + m2Container->show(); + + auto dock21 = createDockWidget("dock21", new QPushButton("foo")); + auto dock22 = createDockWidget("dock22", new QPushButton("foo")); + m2->addDockWidget(dock21, Location_OnLeft); + m2->addDockWidget(dock22, Location_OnRight); + + auto fw = m2Container->floatingWindow(); + TitleBar *fwTitleBar = fw->titleBar(); + + QVERIFY(fw->hasSingleFrame()); + QVERIFY(fw->hasSingleDockWidget()); + + // Check that the inner-inner dock widgets have a visible title-bar + QVERIFY(dock21->titleBar()->isVisible()); + QVERIFY(dock22->titleBar()->isVisible()); + QVERIFY(dock21->titleBar() != fwTitleBar); + QVERIFY(dock22->titleBar() != fwTitleBar); + + QTest::qWait(10); // the DND state machine needs the event loop to start, otherwise activeState() is nullptr. (for offscreen QPA) + const QPoint startPoint = fwTitleBar->mapToGlobal(QPoint(5, 5)); + const QPoint destination = startPoint + QPoint(20, 20); + + // Check that we don't get the "Refusing to itself" warning. not actually dropping anywhere + drag(fwTitleBar, startPoint, destination); + + // The FloatingWindow has a single DockWidget, so it shows the title bar, while the Frame doesn't + QVERIFY(fwTitleBar->isVisible()); + QVERIFY(!m2Container->frame()->titleBar()->isVisible()); + + fw->dropArea()->addDockWidget(dock1, Location::Location_OnLeft, nullptr); + // Now the FloatingWindow has two dock widgets, so our main window dock widget also shows the title bar + QVERIFY(fwTitleBar->isVisible()); + QVERIFY(m2Container->frame()->titleBar()->isVisible()); + + // Put it how it was, FloatingWindow is single dock again + auto frame1 = dock1->frame(); + dock1->close(); + Testing::waitForDeleted(frame1); + QVERIFY(fwTitleBar->isVisible()); + QVERIFY(!m2Container->frame()->titleBar()->isVisible()); + + // Repeat, but instead of closing dock1, we float it + fw->dropArea()->addDockWidget(dock1, Location::Location_OnLeft, nullptr); + QVERIFY(fwTitleBar->isVisible()); + QVERIFY(m2Container->frame()->titleBar()->isVisible()); + frame1 = dock1->frame(); + frame1->titleBar()->onFloatClicked(); + QVERIFY(fwTitleBar->isVisible()); + + QVERIFY(!m2Container->frame()->titleBar()->isVisible()); + + fw->dropArea()->addDockWidget(dock1, Location::Location_OnLeft, nullptr); +} + #endif void TestCommon::tst_negativeAnchorPositionWhenEmbedded_data() @@ -5058,4 +5131,292 @@ void TestCommon::tst_negativeAnchorPositionWhenEmbedded() delete m->window(); } +void TestCommon::tst_floatingAction() +{ + // Tests DockWidget::floatAction() + EnsureTopLevelsDeleted e; + + { + // 1. Create a MainWindow with two docked dock-widgets, then float the first one. + auto m = createMainWindow(); + auto dock1 = createDockWidget("dock1", new QPushButton("one")); + auto dock2 = createDockWidget("dock2", new QPushButton("two")); + m->addDockWidget(dock1, KDDockWidgets::Location_OnLeft); + m->addDockWidget(dock2, KDDockWidgets::Location_OnRight); + + auto action = dock1->floatAction(); + QVERIFY(!dock1->isFloating()); + QVERIFY(!action->isChecked()); + QVERIFY(action->isEnabled()); + QCOMPARE(action->toolTip(), tr("Detach")); + + action->toggle(); + QVERIFY(dock1->isFloating()); + QVERIFY(action->isChecked()); + QVERIFY(action->isEnabled()); + QCOMPARE(action->toolTip(), tr("Dock")); + + auto fw = dock1->floatingWindow(); + QVERIFY(fw); + + //2. Put it back, via setFloating(). It should return to its place. + action->toggle(); + + QVERIFY(!dock1->isFloating()); + QVERIFY(!action->isChecked()); + QVERIFY(action->isEnabled()); + QVERIFY(!dock1->isTabbed()); + QCOMPARE(action->toolTip(), tr("Detach"));; + + Testing::waitForDeleted(fw); + } + + { + // 1. Create a MainWindow with one docked dock-widgets, and one floating. + auto m = createMainWindow(); + auto dock1 = createDockWidget("dock1", new QPushButton("one")); + auto dock2 = createDockWidget("dock2", new QPushButton("two")); + m->addDockWidget(dock1, KDDockWidgets::Location_OnLeft); + + //The floating window action should be disabled as it has no previous place + auto action = dock2->floatAction(); + QVERIFY(dock2->isFloating()); + QVERIFY(action->isChecked()); + QVERIFY(!action->isEnabled()); + QCOMPARE(action->toolTip(), tr("Dock")); + + m->addDockWidget(dock2, KDDockWidgets::Location_OnRight); + + QVERIFY(!dock2->isFloating()); + QVERIFY(!action->isChecked()); + QVERIFY(action->isEnabled()); + QCOMPARE(action->toolTip(), tr("Detach")); + + action->toggle(); + QVERIFY(dock2->isFloating()); + QVERIFY(action->isChecked()); + QVERIFY(action->isEnabled()); + QCOMPARE(action->toolTip(), tr("Dock")); + + auto fw = dock2->floatingWindow(); + QVERIFY(fw); + + //2. Put it back, via setFloating(). It should return to its place. + action->toggle(); + + QVERIFY(!dock1->isFloating()); + QVERIFY(!action->isChecked()); + QVERIFY(action->isEnabled()); + QVERIFY(!dock1->isTabbed()); + QCOMPARE(action->toolTip(), tr("Detach")); + + Testing::waitForDeleted(fw); + } + { + // 3. A floating window with two tabs + auto dock1 = createDockWidget("dock1", new QPushButton("one")); + auto dock2 = createDockWidget("dock2", new QPushButton("two")); + + bool dock1IsFloating = dock1->floatAction()->isChecked(); + bool dock2IsFloating = dock2->floatAction()->isChecked(); + + connect(dock1->floatAction(), &QAction::toggled, [&dock1IsFloating] (bool t) { + Q_ASSERT(dock1IsFloating != t); + dock1IsFloating = t; + }); + + connect(dock2->floatAction(), &QAction::toggled, [&dock2IsFloating] (bool t) { + Q_ASSERT(dock2IsFloating != t); + dock2IsFloating = t; + }); + + auto fw2 = dock2->floatingWindow(); + QVERIFY(dock1->isFloating()); + QVERIFY(dock2->isFloating()); + QVERIFY(dock1->floatAction()->isChecked()); + QVERIFY(dock2->floatAction()->isChecked()); + + dock1->addDockWidgetAsTab(dock2); + QVERIFY(!dock1->isFloating()); + QVERIFY(!dock2->isFloating()); + QVERIFY(!dock1->floatAction()->isChecked()); + QVERIFY(!dock2->floatAction()->isChecked()); + + dock2->setFloating(true); + + QVERIFY(dock1->isFloating()); + QVERIFY(dock1->floatAction()->isChecked()); + QVERIFY(dock2->isFloating()); + QVERIFY(dock2->floatAction()->isChecked()); + + QVERIFY(dock1IsFloating); + QVERIFY(dock2IsFloating); + + delete fw2; + delete dock1->window(); + delete dock2->window(); + } + + { + // If the dock widget is alone then it's floating, but we suddenly dock a widget side-by-side + // to it, then both aren't floating anymore. This test tests if the signal was emitted + + auto dock1 = createDockWidget("one", new QPushButton("one")); + auto dock2 = createDockWidget("two", new QPushButton("two")); + + QVERIFY(dock1->isFloating()); + QVERIFY(dock2->isFloating()); + QVERIFY(dock1->floatAction()->isChecked()); + QVERIFY(dock2->floatAction()->isChecked()); + auto oldFw2 = dock2->window(); + + QSignalSpy spy1(dock1->floatAction(), &QAction::toggled); + QSignalSpy spy2(dock2->floatAction(), &QAction::toggled); + + QSignalSpy spy11(dock1, &DockWidgetBase::isFloatingChanged); + QSignalSpy spy21(dock2, &DockWidgetBase::isFloatingChanged); + + dock1->addDockWidgetToContainingWindow(dock2, Location_OnRight); + + QCOMPARE(spy1.count(), 1); + QCOMPARE(spy2.count(), 1); + QCOMPARE(spy11.count(), 1); + QCOMPARE(spy21.count(), 1); + + QVERIFY(!dock1->isFloating()); + QVERIFY(!dock2->isFloating()); + + QVERIFY(!dock2->floatAction()->isChecked()); + QVERIFY(!dock1->floatAction()->isChecked()); + + delete dock1->window(); + delete oldFw2->window(); + } + + { + // Like before, but now we use addMultiSplitter() + + auto dock1 = createDockWidget("one", new QPushButton("one")); + auto dock2 = createDockWidget("two", new QPushButton("two")); + + QVERIFY(dock1->isFloating()); + QVERIFY(dock2->isFloating()); + QVERIFY(dock1->floatAction()->isChecked()); + QVERIFY(dock2->floatAction()->isChecked()); + auto oldFw2 = dock2->floatingWindow(); + + QSignalSpy spy1(dock1->floatAction(), &QAction::toggled); + QSignalSpy spy2(dock2->floatAction(), &QAction::toggled); + + QSignalSpy spy11(dock1, &DockWidgetBase::isFloatingChanged); + QSignalSpy spy21(dock2, &DockWidgetBase::isFloatingChanged); + + auto dropArea1 = dock1->floatingWindow()->dropArea(); + dropArea1->drop(oldFw2, Location_OnRight, nullptr); + + QCOMPARE(spy1.count(), 1); + QCOMPARE(spy2.count(), 1); + QCOMPARE(spy11.count(), 1); + QCOMPARE(spy21.count(), 1); + + QVERIFY(!dock1->isFloating()); + QVERIFY(!dock2->isFloating()); + QVERIFY(!dock2->floatAction()->isChecked()); + QVERIFY(!dock1->floatAction()->isChecked()); + + // Let's now remove dock1, dock2 should be floating + dock1->setFloating(true); + QVERIFY(dock1->isFloating()); + QVERIFY(dock2->isFloating()); + QVERIFY(dock2->floatAction()->isChecked()); + QVERIFY(dock1->floatAction()->isChecked()); + + delete dock1->window(); + delete dock2->window(); + delete oldFw2->window(); + } + + { + // Same test as before, but now tab instead of side-by-side + auto dock1 = createDockWidget("one", new QPushButton("one")); + auto dock2 = createDockWidget("two", new QPushButton("two")); + + QVERIFY(dock1->isFloating()); + QVERIFY(dock2->isFloating()); + QVERIFY(dock1->floatAction()->isChecked()); + QVERIFY(dock2->floatAction()->isChecked()); + auto oldFw2 = dock2->window(); + + QSignalSpy spy1(dock1->floatAction(), &QAction::toggled); + QSignalSpy spy2(dock2->floatAction(), &QAction::toggled); + QSignalSpy spy11(dock1, &DockWidgetBase::isFloatingChanged); + QSignalSpy spy21(dock2, &DockWidgetBase::isFloatingChanged); + dock1->addDockWidgetAsTab(dock2); + + QCOMPARE(spy1.count(), 1); + + // On earlier Qt versions this is flaky, but technically correct. + // Windows can get hidden while being reparented and floating changes momentarily. + QVERIFY(spy2.count() == 1 || spy2.count() == 3); + QVERIFY(spy21.count() == 1 || spy21.count() == 3); + QCOMPARE(spy11.count(), 1); + + QVERIFY(!dock1->isFloating()); + QVERIFY(!dock2->isFloating()); + + QVERIFY(!dock2->floatAction()->isChecked()); + QVERIFY(!dock1->floatAction()->isChecked()); + + delete dock1->window(); + delete oldFw2->window(); + } +} + +void TestCommon::tst_raise() +{ + // Tests DockWidget::raise(); + EnsureTopLevelsDeleted e; + + auto dock1 = createDockWidget("1"); + auto dock2 = createDockWidget("2"); + auto fw2 = Tests::make_qpointer(dock2->window()); + dock1->addDockWidgetAsTab(dock2); + dock1->setAsCurrentTab(); + QVERIFY(dock1->isCurrentTab()); + QVERIFY(!dock2->isCurrentTab()); + dock2->raise(); + QVERIFY(!dock1->isCurrentTab()); + QVERIFY(dock2->isCurrentTab()); + + if (qApp->platformName() != QLatin1String("offscreen")) { // offscreen qpa doesn't seem to keep Window Z. + auto dock3 = createDockWidget("3"); + dock3->window()->setGeometry(dock1->window()->geometry()); + dock3->window()->setObjectName("3"); + dock1->window()->setObjectName("1"); + dock3->raise(); + QTest::qWait(200); + + if (qApp->QGuiApplication::topLevelAt(dock3->window()->geometry().topLeft() + QPoint(50, 50)) != dock3->windowHandle()) { + qDebug() << "Failing before raise" << qApp->widgetAt(dock3->window()->geometry().topLeft() + QPoint(50, 50))->window() << dock3->window() + << dock1->window()->geometry() << dock3->window()->geometry(); + QVERIFY(false); + } + + dock1->raise(); + QTest::qWait(200); + QVERIFY(dock1->isCurrentTab()); + + if (qApp->QGuiApplication::topLevelAt(dock3->window()->geometry().topLeft() + QPoint(50, 50)) != dock1->windowHandle()) { + qDebug() << "Failing after raise" << qApp->widgetAt(dock3->window()->geometry().topLeft() + QPoint(50, 50))->window() << dock1->window() + << dock1->window()->geometry() << dock3->window()->geometry(); + QVERIFY(false); + } + + delete dock3->window(); + } + + delete fw2; + delete dock1->window(); +} + #include "tst_common.moc" diff --git a/tests/tst_docks.cpp b/tests/tst_docks.cpp index ef422392..08f1e551 100644 --- a/tests/tst_docks.cpp +++ b/tests/tst_docks.cpp @@ -173,9 +173,6 @@ private Q_SLOTS: void tst_addingOptionHiddenTabbed(); void tst_flagDoubleClick(); void tst_floatingWindowDeleted(); - void tst_raise(); - void tst_floatingAction(); - void tst_dockableMainWindows(); void tst_maxSizedHonouredAfterRemoved(); void tst_maximumSizePolicy(); @@ -832,363 +829,6 @@ void TestDocks::tst_floatingWindowDeleted() MyMainWindow m; } -void TestDocks::tst_raise() -{ - // Tests DockWidget::raise(); - EnsureTopLevelsDeleted e; - - auto dock1 = createDockWidget("1", new QWidget()); - auto dock2 = createDockWidget("2", new QWidget()); - auto fw2 = Tests::make_qpointer(dock2->window()); - dock1->addDockWidgetAsTab(dock2); - dock1->setAsCurrentTab(); - QVERIFY(dock1->isCurrentTab()); - QVERIFY(!dock2->isCurrentTab()); - dock2->raise(); - QVERIFY(!dock1->isCurrentTab()); - QVERIFY(dock2->isCurrentTab()); - - if (qApp->platformName() != QLatin1String("offscreen")) { // offscreen qpa doesn't seem to keep Window Z. - auto dock3 = createDockWidget("3", new QWidget()); - dock3->window()->setGeometry(dock1->window()->geometry()); - dock3->window()->setObjectName("3"); - dock1->window()->setObjectName("1"); - dock3->raise(); - QTest::qWait(200); - - if (qApp->widgetAt(dock3->window()->geometry().topLeft() + QPoint(50, 50))->window() != dock3->window()) { - qDebug() << "Failing before raise" << qApp->widgetAt(dock3->window()->geometry().topLeft() + QPoint(50, 50))->window() << dock3->window() - << dock1->window()->geometry() << dock3->window()->geometry(); - QVERIFY(false); - } - - dock1->raise(); - QTest::qWait(200); - QVERIFY(dock1->isCurrentTab()); - - if (qApp->widgetAt(dock3->window()->geometry().topLeft() + QPoint(50, 50))->window() != dock1->window()) { - qDebug() << "Failing after raise" << qApp->widgetAt(dock3->window()->geometry().topLeft() + QPoint(50, 50))->window() << dock1->window() - << dock1->window()->geometry() << dock3->window()->geometry(); - QVERIFY(false); - } - - delete dock3->window(); - } - - delete fw2; - delete dock1->window(); -} - -void TestDocks::tst_floatingAction() -{ - // Tests DockWidget::floatAction() - EnsureTopLevelsDeleted e; - - { - // 1. Create a MainWindow with two docked dock-widgets, then float the first one. - auto m = createMainWindow(); - auto dock1 = createDockWidget("dock1", new QPushButton("one")); - auto dock2 = createDockWidget("dock2", new QPushButton("two")); - m->addDockWidget(dock1, KDDockWidgets::Location_OnLeft); - m->addDockWidget(dock2, KDDockWidgets::Location_OnRight); - - auto action = dock1->floatAction(); - QVERIFY(!dock1->isFloating()); - QVERIFY(!action->isChecked()); - QVERIFY(action->isEnabled()); - QCOMPARE(action->toolTip(), tr("Detach")); - - action->toggle(); - QVERIFY(dock1->isFloating()); - QVERIFY(action->isChecked()); - QVERIFY(action->isEnabled()); - QCOMPARE(action->toolTip(), tr("Dock")); - - auto fw = dock1->floatingWindow(); - QVERIFY(fw); - - //2. Put it back, via setFloating(). It should return to its place. - action->toggle(); - - QVERIFY(!dock1->isFloating()); - QVERIFY(!action->isChecked()); - QVERIFY(action->isEnabled()); - QVERIFY(!dock1->isTabbed()); - QCOMPARE(action->toolTip(), tr("Detach"));; - - Testing::waitForDeleted(fw); - } - - { - // 1. Create a MainWindow with one docked dock-widgets, and one floating. - auto m = createMainWindow(); - auto dock1 = createDockWidget("dock1", new QPushButton("one")); - auto dock2 = createDockWidget("dock2", new QPushButton("two")); - m->addDockWidget(dock1, KDDockWidgets::Location_OnLeft); - - //The floating window action should be disabled as it has no previous place - auto action = dock2->floatAction(); - QVERIFY(dock2->isFloating()); - QVERIFY(action->isChecked()); - QVERIFY(!action->isEnabled()); - QCOMPARE(action->toolTip(), tr("Dock")); - - m->addDockWidget(dock2, KDDockWidgets::Location_OnRight); - - QVERIFY(!dock2->isFloating()); - QVERIFY(!action->isChecked()); - QVERIFY(action->isEnabled()); - QCOMPARE(action->toolTip(), tr("Detach")); - - action->toggle(); - QVERIFY(dock2->isFloating()); - QVERIFY(action->isChecked()); - QVERIFY(action->isEnabled()); - QCOMPARE(action->toolTip(), tr("Dock")); - - auto fw = dock2->floatingWindow(); - QVERIFY(fw); - - //2. Put it back, via setFloating(). It should return to its place. - action->toggle(); - - QVERIFY(!dock1->isFloating()); - QVERIFY(!action->isChecked()); - QVERIFY(action->isEnabled()); - QVERIFY(!dock1->isTabbed()); - QCOMPARE(action->toolTip(), tr("Detach")); - - Testing::waitForDeleted(fw); - } - { - // 3. A floating window with two tabs - auto dock1 = createDockWidget("dock1", new QPushButton("one")); - auto dock2 = createDockWidget("dock2", new QPushButton("two")); - - bool dock1IsFloating = dock1->floatAction()->isChecked(); - bool dock2IsFloating = dock2->floatAction()->isChecked(); - - connect(dock1->floatAction(), &QAction::toggled, [&dock1IsFloating] (bool t) { - Q_ASSERT(dock1IsFloating != t); - dock1IsFloating = t; - }); - - connect(dock2->floatAction(), &QAction::toggled, [&dock2IsFloating] (bool t) { - Q_ASSERT(dock2IsFloating != t); - dock2IsFloating = t; - }); - - auto fw2 = dock2->floatingWindow(); - QVERIFY(dock1->isFloating()); - QVERIFY(dock2->isFloating()); - QVERIFY(dock1->floatAction()->isChecked()); - QVERIFY(dock2->floatAction()->isChecked()); - - dock1->addDockWidgetAsTab(dock2); - QVERIFY(!dock1->isFloating()); - QVERIFY(!dock2->isFloating()); - QVERIFY(!dock1->floatAction()->isChecked()); - QVERIFY(!dock2->floatAction()->isChecked()); - - dock2->setFloating(true); - - QVERIFY(dock1->isFloating()); - QVERIFY(dock1->floatAction()->isChecked()); - QVERIFY(dock2->isFloating()); - QVERIFY(dock2->floatAction()->isChecked()); - - QVERIFY(dock1IsFloating); - QVERIFY(dock2IsFloating); - - delete fw2; - delete dock1->window(); - delete dock2->window(); - } - - { - // If the dock widget is alone then it's floating, but we suddenly dock a widget side-by-side - // to it, then both aren't floating anymore. This test tests if the signal was emitted - - auto dock1 = createDockWidget("one", new QPushButton("one")); - auto dock2 = createDockWidget("two", new QPushButton("two")); - - QVERIFY(dock1->isFloating()); - QVERIFY(dock2->isFloating()); - QVERIFY(dock1->floatAction()->isChecked()); - QVERIFY(dock2->floatAction()->isChecked()); - auto oldFw2 = dock2->window(); - - QSignalSpy spy1(dock1->floatAction(), &QAction::toggled); - QSignalSpy spy2(dock2->floatAction(), &QAction::toggled); - - QSignalSpy spy11(dock1, &DockWidgetBase::isFloatingChanged); - QSignalSpy spy21(dock2, &DockWidgetBase::isFloatingChanged); - - dock1->addDockWidgetToContainingWindow(dock2, Location_OnRight); - - QCOMPARE(spy1.count(), 1); - QCOMPARE(spy2.count(), 1); - QCOMPARE(spy11.count(), 1); - QCOMPARE(spy21.count(), 1); - - QVERIFY(!dock1->isFloating()); - QVERIFY(!dock2->isFloating()); - - QVERIFY(!dock2->floatAction()->isChecked()); - QVERIFY(!dock1->floatAction()->isChecked()); - - delete dock1->window(); - delete oldFw2->window(); - } - - { - // Like before, but now we use addMultiSplitter() - - auto dock1 = createDockWidget("one", new QPushButton("one")); - auto dock2 = createDockWidget("two", new QPushButton("two")); - - QVERIFY(dock1->isFloating()); - QVERIFY(dock2->isFloating()); - QVERIFY(dock1->floatAction()->isChecked()); - QVERIFY(dock2->floatAction()->isChecked()); - auto oldFw2 = dock2->floatingWindow(); - - QSignalSpy spy1(dock1->floatAction(), &QAction::toggled); - QSignalSpy spy2(dock2->floatAction(), &QAction::toggled); - - QSignalSpy spy11(dock1, &DockWidgetBase::isFloatingChanged); - QSignalSpy spy21(dock2, &DockWidgetBase::isFloatingChanged); - - auto dropArea1 = dock1->floatingWindow()->dropArea(); - dropArea1->drop(oldFw2, Location_OnRight, nullptr); - - QCOMPARE(spy1.count(), 1); - QCOMPARE(spy2.count(), 1); - QCOMPARE(spy11.count(), 1); - QCOMPARE(spy21.count(), 1); - - QVERIFY(!dock1->isFloating()); - QVERIFY(!dock2->isFloating()); - QVERIFY(!dock2->floatAction()->isChecked()); - QVERIFY(!dock1->floatAction()->isChecked()); - - // Let's now remove dock1, dock2 should be floating - dock1->setFloating(true); - QVERIFY(dock1->isFloating()); - QVERIFY(dock2->isFloating()); - QVERIFY(dock2->floatAction()->isChecked()); - QVERIFY(dock1->floatAction()->isChecked()); - - delete dock1->window(); - delete dock2->window(); - delete oldFw2->window(); - } - - { - // Same test as before, but now tab instead of side-by-side - auto dock1 = createDockWidget("one", new QPushButton("one")); - auto dock2 = createDockWidget("two", new QPushButton("two")); - - QVERIFY(dock1->isFloating()); - QVERIFY(dock2->isFloating()); - QVERIFY(dock1->floatAction()->isChecked()); - QVERIFY(dock2->floatAction()->isChecked()); - auto oldFw2 = dock2->window(); - - QSignalSpy spy1(dock1->floatAction(), &QAction::toggled); - QSignalSpy spy2(dock2->floatAction(), &QAction::toggled); - QSignalSpy spy11(dock1, &DockWidgetBase::isFloatingChanged); - QSignalSpy spy21(dock2, &DockWidgetBase::isFloatingChanged); - dock1->addDockWidgetAsTab(dock2); - - QCOMPARE(spy1.count(), 1); - - // On earlier Qt versions this is flaky, but technically correct. - // Windows can get hidden while being reparented and floating changes momentarily. - QVERIFY(spy2.count() == 1 || spy2.count() == 3); - QVERIFY(spy21.count() == 1 || spy21.count() == 3); - QCOMPARE(spy11.count(), 1); - - QVERIFY(!dock1->isFloating()); - QVERIFY(!dock2->isFloating()); - - QVERIFY(!dock2->floatAction()->isChecked()); - QVERIFY(!dock1->floatAction()->isChecked()); - - delete dock1->window(); - delete oldFw2->window(); - } -} - -void TestDocks::tst_dockableMainWindows() -{ - EnsureTopLevelsDeleted e; - - auto m1 = createMainWindow(); - auto dock1 = createDockWidget("dock1", new QPushButton("foo")); - m1->addDockWidget(dock1, Location_OnTop); - - auto m2 = new KDDockWidgets::MainWindow("mainwindow-dockable"); - auto m2Container = createDockWidget("mainwindow-dw", m2); - auto menubar = m2->menuBar(); - menubar->addMenu("File"); - menubar->addMenu("View"); - menubar->addMenu("Help"); - m2Container->show(); - - auto dock21 = createDockWidget("dock21", new QPushButton("foo")); - auto dock22 = createDockWidget("dock22", new QPushButton("foo")); - m2->addDockWidget(dock21, Location_OnLeft); - m2->addDockWidget(dock22, Location_OnRight); - - auto fw = m2Container->floatingWindow(); - TitleBar *fwTitleBar = fw->titleBar(); - - QVERIFY(fw->hasSingleFrame()); - QVERIFY(fw->hasSingleDockWidget()); - - // Check that the inner-inner dock widgets have a visible title-bar - QVERIFY(dock21->titleBar()->isVisible()); - QVERIFY(dock22->titleBar()->isVisible()); - QVERIFY(dock21->titleBar() != fwTitleBar); - QVERIFY(dock22->titleBar() != fwTitleBar); - - QTest::qWait(10); // the DND state machine needs the event loop to start, otherwise activeState() is nullptr. (for offscreen QPA) - const QPoint startPoint = fwTitleBar->mapToGlobal(QPoint(5, 5)); - const QPoint destination = startPoint + QPoint(20, 20); - - // Check that we don't get the "Refusing to itself" warning. not actually dropping anywhere - drag(fwTitleBar, startPoint, destination); - - // The FloatingWindow has a single DockWidget, so it shows the title bar, while the Frame doesn't - QVERIFY(fwTitleBar->isVisible()); - QVERIFY(!m2Container->frame()->titleBar()->isVisible()); - - fw->dropArea()->addDockWidget(dock1, Location::Location_OnLeft, nullptr); - // Now the FloatingWindow has two dock widgets, so our main window dock widget also shows the title bar - QVERIFY(fwTitleBar->isVisible()); - QVERIFY(m2Container->frame()->titleBar()->isVisible()); - - // Put it how it was, FloatingWindow is single dock again - auto frame1 = dock1->frame(); - dock1->close(); - Testing::waitForDeleted(frame1); - QVERIFY(fwTitleBar->isVisible()); - QVERIFY(!m2Container->frame()->titleBar()->isVisible()); - - // Repeat, but instead of closing dock1, we float it - fw->dropArea()->addDockWidget(dock1, Location::Location_OnLeft, nullptr); - QVERIFY(fwTitleBar->isVisible()); - QVERIFY(m2Container->frame()->titleBar()->isVisible()); - frame1 = dock1->frame(); - frame1->titleBar()->onFloatClicked(); - QVERIFY(fwTitleBar->isVisible()); - - QVERIFY(!m2Container->frame()->titleBar()->isVisible()); - - fw->dropArea()->addDockWidget(dock1, Location::Location_OnLeft, nullptr); -} - void TestDocks::tst_maxSizedHonouredAfterRemoved() { EnsureTopLevelsDeleted e;