diff --git a/CMakeLists.txt b/CMakeLists.txt index 06607fcc..f11517da 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -368,6 +368,9 @@ if(${PROJECT_NAME}_TESTS) if(KDDW_FRONTEND_QTWIDGETS) add_test(NAME tst_qtwidgets COMMAND tst_qtwidgets) endif() + if(KDDW_FRONTEND_QTQUICK) + add_test(NAME tst_qtquick COMMAND tst_qtquick) + endif() endif() endif() diff --git a/src/LayoutSaver.cpp b/src/LayoutSaver.cpp index 58458a5d..b1db3c5b 100644 --- a/src/LayoutSaver.cpp +++ b/src/LayoutSaver.cpp @@ -487,7 +487,7 @@ bool LayoutSaver::restoreLayout(const QByteArray &data) continue; if (!(d->m_restoreOptions & InternalRestoreOption::SkipMainWindowGeometry)) { - auto window = mainWindow->window(); + auto window = mainWindow->view()->rootView(); d->deserializeWindowGeometry(mw, window.get()); // window(), as the MainWindow can be embedded if (mw.windowState != Qt::WindowNoState) { if (auto w = mainWindow->view()->window()) { @@ -590,14 +590,7 @@ void LayoutSaver::Private::deserializeWindowGeometry(const T &saved, View *topLe Controllers::FloatingWindow::ensureRectIsOnScreen(geometry); - if (topLevel->isRootView()) { - topLevel->setGeometry(geometry); - } else { - // TODOv2: Have a WindowView abstraction, that will represent QWindow for Qt. - // Then we can ensure we receive WindowView instead of View. Probably even WindowViewWrapper. - topLevel->setGeometry(geometry); - } - + topLevel->setGeometry(geometry); topLevel->setVisible(saved.isVisible); } diff --git a/src/Window.h b/src/Window.h index 43ba09aa..d6358314 100644 --- a/src/Window.h +++ b/src/Window.h @@ -34,6 +34,7 @@ public: virtual ~Window(); virtual void setWindowState(Qt::WindowState) = 0; virtual QRect geometry() const = 0; + virtual void setGeometry(QRect) const = 0; virtual void setProperty(const char *name, const QVariant &value) = 0; virtual QVariant property(const char *name) const = 0; virtual bool isVisible() const = 0; diff --git a/src/qtcommon/Window_qt.cpp b/src/qtcommon/Window_qt.cpp index 4cdbbbe5..bb9f83b3 100644 --- a/src/qtcommon/Window_qt.cpp +++ b/src/qtcommon/Window_qt.cpp @@ -23,6 +23,7 @@ using namespace KDDockWidgets; Window_qt::Window_qt(QWindow *window) : m_window(window) { + Q_ASSERT(window); m_connection = QObject::connect(window, &QWindow::screenChanged, [this] { screenChanged.emit(); }); @@ -50,6 +51,7 @@ QRect Window_qt::geometry() const void Window_qt::setProperty(const char *name, const QVariant &value) { + Q_ASSERT(m_window); m_window->setProperty(name, value); } @@ -151,3 +153,8 @@ void Window_qt::startSystemMove() { m_window->startSystemMove(); } + +void KDDockWidgets::Window_qt::setGeometry(QRect geo) const +{ + m_window->setGeometry(geo); +} diff --git a/src/qtcommon/Window_qt.h b/src/qtcommon/Window_qt.h index 62c6e8f0..977b9acf 100644 --- a/src/qtcommon/Window_qt.h +++ b/src/qtcommon/Window_qt.h @@ -26,6 +26,7 @@ public: ~Window_qt() override; void setWindowState(Qt::WindowState) override; QRect geometry() const override; + void setGeometry(QRect) const override; bool isVisible() const override; WId handle() const override; diff --git a/src/qtquick/views/View_qtquick.cpp b/src/qtquick/views/View_qtquick.cpp index f2384257..b9b1cb9c 100644 --- a/src/qtquick/views/View_qtquick.cpp +++ b/src/qtquick/views/View_qtquick.cpp @@ -552,9 +552,13 @@ QVariant View_qtquick::property(const char *name) const if (!parent) return true; - if (QQuickView *w = qobject_cast(item->window())) { - if (parent == w->contentItem() || parent == w->rootObject()) + if (auto *w = qobject_cast(item->window())) { + if (parent == w->contentItem() || item == w->contentItem()) return true; + if (auto *qv = qobject_cast(item->window())) { + if (parent == qv->rootObject() || item == qv->rootObject()) + return true; + } } return false; diff --git a/src/qtwidgets/Window_qtwidgets.cpp b/src/qtwidgets/Window_qtwidgets.cpp index 1ec7c17b..0fe969e3 100644 --- a/src/qtwidgets/Window_qtwidgets.cpp +++ b/src/qtwidgets/Window_qtwidgets.cpp @@ -22,8 +22,16 @@ using namespace KDDockWidgets; Window_qtwidgets::~Window_qtwidgets() = default; +inline QWindow *windowForWidget(QWidget *topLevel) +{ + if (!topLevel->windowHandle()) + topLevel->winId(); + + return topLevel->windowHandle(); +} + Window_qtwidgets::Window_qtwidgets(QWidget *topLevel) - : Window_qt(topLevel->windowHandle()) + : Window_qt(windowForWidget(topLevel)) { // QWidgetWindow is private API, we have no way for going from QWindow to the top-level QWidget // So set it as a property diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 3bb06310..e9eec15f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -38,6 +38,12 @@ if (KDDW_FRONTEND_QTWIDGETS) set_compiler_flags(tst_qtwidgets) endif() +if (KDDW_FRONTEND_QTQUICK) + add_executable(tst_qtquick qtquick/tst_qtquick.cpp ${TESTING_SRCS} ${TESTING_RESOURCES}) + target_link_libraries(tst_qtquick kddockwidgets Qt${Qt_VERSION_MAJOR}::Test) + set_compiler_flags(tst_qtquick) +endif() + add_executable(tst_multisplitter tst_multisplitter.cpp) target_link_libraries(tst_multisplitter kddockwidgets Qt${Qt_VERSION_MAJOR}::Test) set_compiler_flags(tst_multisplitter) diff --git a/tests/qtquick/tst_qtquick.cpp b/tests/qtquick/tst_qtquick.cpp new file mode 100644 index 00000000..61f364e7 --- /dev/null +++ b/tests/qtquick/tst_qtquick.cpp @@ -0,0 +1,95 @@ +/* + This file is part of KDDockWidgets. + + SPDX-FileCopyrightText: 2019-2022 Klarälvdalens Datakonsult AB, a KDAB Group company + Author: Sérgio Martins + + SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only + + Contact KDAB at for commercial licensing options. +*/ + +/// @file +/// @brief Here lives the tests that only apply to QtQuick + +#include "Platform.h" +#include "KDDockWidgets.h" + +#include "../utils.h" + +#include +#include + +using namespace KDDockWidgets; +using namespace KDDockWidgets::Tests; +using namespace KDDockWidgets::Controllers; + +class TestQtQuick : public QObject +{ + Q_OBJECT + +public Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); + +private Q_SLOTS: + void tst_restoreRestoresMainWindowPosition(); +}; + + +void TestQtQuick::initTestCase() +{ + KDDockWidgets::Platform::instance()->installMessageHandler(); +} + +void TestQtQuick::cleanupTestCase() +{ + KDDockWidgets::Platform::instance()->uninstallMessageHandler(); +} + +void TestQtQuick::tst_restoreRestoresMainWindowPosition() +{ + // Tests the ApplicationWindow {} case + + QQmlApplicationEngine engine(":/main2.qml"); + + const auto mainWindows = DockRegistry::self()->mainwindows(); + QCOMPARE(mainWindows.size(), 1); + MainWindow *mainWindow = mainWindows.first(); + QVERIFY(mainWindow->isVisible()); + + QCOMPARE(mainWindow->pos(), QPoint(0, 0)); + + Window::Ptr window = mainWindow->view()->window(); + + LayoutSaver saver; + const QByteArray saved = saver.serializeLayout(); + + const QPoint originalPos = window->framePosition(); + + const QPoint newPos = originalPos + QPoint(200, 200); + window->setFramePosition(newPos); + QCOMPARE(window->framePosition(), newPos); + + QVERIFY(saver.restoreLayout(saved)); + + QCOMPARE(window->framePosition(), originalPos); + + delete mainWindow; +} + +int main(int argc, char *argv[]) +{ + KDDockWidgets::Platform::tests_initPlatform(argc, argv, KDDockWidgets::FrontendType::QtQuick); + + if (shouldSkipTests()) + return 0; + + TestQtQuick test; + const int exitCode = QTest::qExec(&test, argc, argv); + KDDockWidgets::Platform::tests_deinitPlatform(); + + return exitCode; +} + +#include "tst_qtquick.moc" diff --git a/tests/tst_docks.cpp b/tests/tst_docks.cpp index d52c86f2..852789eb 100644 --- a/tests/tst_docks.cpp +++ b/tests/tst_docks.cpp @@ -3352,34 +3352,6 @@ void TestDocks::tst_restoreRestoresMainWindowPosition() saver.restoreLayout(saved); QCOMPARE(originalPos, m->pos()); } -#ifdef KDDOCKWIDGETS_QTQUICK - // Tests the ApplicationWindow {} case - { - QQmlApplicationEngine engine(":/main2.qml"); - - const MainWindowBase::List mainWindows = DockRegistry::self()->mainwindows(); - QCOMPARE(mainWindows.size(), 1); - MainWindowBase *mainWindow = mainWindows.first(); - QVERIFY(mainWindow->isVisible()); - - QCOMPARE(mainWindow->pos(), QPoint(0, 0)); - - QWindow *window = mainWindow->window(); - - LayoutSaver saver; - const QByteArray saved = saver.serializeLayout(); - - const QPoint originalPos = window->position(); - window->setPosition(originalPos + QPoint(200, 200)); - QCOMPARE(window->position(), originalPos + QPoint(200, 200)); - - QVERIFY(saver.restoreLayout(saved)); - - QCOMPARE(window->position(), originalPos); - - delete mainWindow; - } -#endif } void TestDocks::tst_resizeViaAnchorsAfterPlaceholderCreation()