diff --git a/examples/dockwidgets/main.cpp b/examples/dockwidgets/main.cpp index be3f94d3..3558fef6 100644 --- a/examples/dockwidgets/main.cpp +++ b/examples/dockwidgets/main.cpp @@ -82,16 +82,18 @@ int main(int argc, char **argv) QCommandLineOption maximizeButton("b", QCoreApplication::translate("main", "DockWidgets have maximize/restore buttons instead of float/dock button")); parser.addOption(maximizeButton); - QCommandLineOption dockableMainWindows("j", QCoreApplication::translate("main", "Allow main windows to be docked inside other main windows (this feature is work in progress)")); +#ifdef KDDOCKWIDGETS_SUPPORTS_NESTED_MAINWINDOWS + QCommandLineOption dockableMainWindows("j", QCoreApplication::translate("main", "Allow main windows to be docked inside other main windows")); + parser.addOption(dockableMainWindows); +#endif + QCommandLineOption maxSizeOption("g", QCoreApplication::translate("main", "Make dock #8 have a max-size of 200x200. (this feature is work in progress)")); QCommandLineOption centralFrame("f", QCoreApplication::translate("main", "Persistent central frame")); #if defined(DOCKS_DEVELOPER_MODE) parser.addOption(centralFrame); - parser.addOption(dockableMainWindows); parser.addOption(maxSizeOption); #else - Q_UNUSED(dockableMainWindows) Q_UNUSED(maxSizeOption) Q_UNUSED(centralFrame) #endif @@ -142,9 +144,14 @@ int main(int argc, char **argv) const bool restoreIsRelative = parser.isSet(relativeRestore); const bool nonDockableDockWidget9 = parser.isSet(nonDockable); const bool maxSizeForDockWidget8 = parser.isSet(maxSizeOption); - const bool usesDockableMainWindows = parser.isSet(dockableMainWindows); const bool usesMainWindowsWithAffinity = parser.isSet(multipleMainWindows); +#ifdef KDDOCKWIDGETS_SUPPORTS_NESTED_MAINWINDOWS + const bool usesDockableMainWindows = parser.isSet(dockableMainWindows); +#else + const bool usesDockableMainWindows = false; +#endif + MyMainWindow mainWindow(QStringLiteral("MyMainWindow"), options, nonClosableDockWidget0, nonDockableDockWidget9, restoreIsRelative, maxSizeForDockWidget8); mainWindow.setWindowTitle("Main Window 1"); @@ -172,12 +179,22 @@ int main(int argc, char **argv) mainWindow2->resize(1200, 1200); mainWindow2->show(); - } else if (parser.isSet(dockableMainWindows)) { + } else if (usesDockableMainWindows) { + auto mainWindowDockWidget = new DockWidget(QStringLiteral("MyMainWindow-2-DW")); + const QString affinity = QStringLiteral("Inner-DockWidgets-2"); auto dockableMainWindow = new MyMainWindow(QStringLiteral("MyMainWindow-2"), options, - false, false, restoreIsRelative, false); + false, false, restoreIsRelative, false, affinity); + + dockableMainWindow->setAffinities({ affinity }); + + dockableMainWindow->setStyleSheet(QStringLiteral("background: yellow")); + dockableMainWindow->setWindowTitle("Dockable Main Window"); dockableMainWindow->show(); + mainWindowDockWidget->setWidget(dockableMainWindow); + mainWindowDockWidget->show(); + mainWindowDockWidget->resize(800, 800); } return app.exec(); diff --git a/src/KDDockWidgets.h b/src/KDDockWidgets.h index 3143143e..30f87af2 100644 --- a/src/KDDockWidgets.h +++ b/src/KDDockWidgets.h @@ -30,6 +30,13 @@ #include +#ifdef Q_OS_WIN +// Only on Windows, where this is popular. On linux it the Qt::Tool windows need reparenting. Untested on macOS. +# define KDDOCKWIDGETS_SUPPORTS_NESTED_MAINWINDOWS +#endif + + + namespace KDDockWidgets { enum Location { diff --git a/tests/tst_docks.cpp b/tests/tst_docks.cpp index 915675ad..a2b4a656 100644 --- a/tests/tst_docks.cpp +++ b/tests/tst_docks.cpp @@ -51,6 +51,7 @@ #include #include #include +#include #include #ifdef Q_OS_WIN @@ -5133,16 +5134,64 @@ void TestDocks::tst_dockableMainWindows() m1->addDockWidget(dock1, Location_OnTop); auto m2 = new KDDockWidgets::MainWindow("mainwindow-dockable"); - auto dock2 = createDockWidget("mainwindow-dw", m2); - dock2->show(); + auto m2Container = createDockWidget("mainwindow-dw", m2); + auto menubar = m2->menuBar(); + menubar->addMenu("File"); + menubar->addMenu("View"); + menubar->addMenu("Help"); + m2Container->show(); - auto fw = qobject_cast(dock2->window()); - TitleBar *titleBar = fw->titleBar(); + 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 = qobject_cast(m2Container->window()); + 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 = titleBar->mapToGlobal(QPoint(5, 5)); + const QPoint startPoint = fwTitleBar->mapToGlobal(QPoint(5, 5)); const QPoint destination = startPoint + QPoint(20, 20); - drag(titleBar, startPoint, destination); + + // 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_lastFloatingPositionIsRestored()