diff --git a/src/View.h b/src/View.h index 84a611a7..348922b6 100644 --- a/src/View.h +++ b/src/View.h @@ -184,6 +184,7 @@ public: return false; } + virtual QVariant property(const char *) const = 0; virtual void setObjectName(const QString &) = 0; virtual QString objectName() const = 0; diff --git a/src/qtquick/views/ViewWrapper_qtquick.cpp b/src/qtquick/views/ViewWrapper_qtquick.cpp index a2fe5b4c..53b363a2 100644 --- a/src/qtquick/views/ViewWrapper_qtquick.cpp +++ b/src/qtquick/views/ViewWrapper_qtquick.cpp @@ -203,6 +203,11 @@ QString ViewWrapper_qtquick::objectName() const return {}; } +QVariant ViewWrapper_qtquick::property(const char *) const +{ + return {}; +} + bool ViewWrapper_qtquick::isNull() const { return m_item.data() == nullptr; diff --git a/src/qtquick/views/ViewWrapper_qtquick.h b/src/qtquick/views/ViewWrapper_qtquick.h index fcca174d..3c258be9 100644 --- a/src/qtquick/views/ViewWrapper_qtquick.h +++ b/src/qtquick/views/ViewWrapper_qtquick.h @@ -53,6 +53,7 @@ public: QScreen *screen() const override; void setFocus(Qt::FocusReason) override; QString objectName() const override; + QVariant property(const char *) const override; bool isNull() const override; private: diff --git a/src/qtquick/views/View_qtquick.h b/src/qtquick/views/View_qtquick.h index 8cf9ee14..c2e085fc 100644 --- a/src/qtquick/views/View_qtquick.h +++ b/src/qtquick/views/View_qtquick.h @@ -159,6 +159,11 @@ public: { } + QVariant property(const char *) const override + { + return {}; + } + bool isTopLevel() const override { return {}; diff --git a/src/qtwidgets/views/ViewWrapper_qtwidgets.cpp b/src/qtwidgets/views/ViewWrapper_qtwidgets.cpp index e893f31e..068eef0f 100644 --- a/src/qtwidgets/views/ViewWrapper_qtwidgets.cpp +++ b/src/qtwidgets/views/ViewWrapper_qtwidgets.cpp @@ -290,6 +290,11 @@ QString ViewWrapper_qtwidgets::objectName() const return m_widget->QWidget::objectName(); } +QVariant ViewWrapper_qtwidgets::property(const char *name) const +{ + return m_widget->property(name); +} + bool ViewWrapper_qtwidgets::isNull() const { return m_widget.data() == nullptr; diff --git a/src/qtwidgets/views/ViewWrapper_qtwidgets.h b/src/qtwidgets/views/ViewWrapper_qtwidgets.h index 5b5a86e5..1dfeaa47 100644 --- a/src/qtwidgets/views/ViewWrapper_qtwidgets.h +++ b/src/qtwidgets/views/ViewWrapper_qtwidgets.h @@ -53,6 +53,7 @@ public: QScreen *screen() const override; void setFocus(Qt::FocusReason) override; QString objectName() const override; + QVariant property(const char *) const override; bool isNull() const override; DropArea *asDropArea() const override; diff --git a/src/qtwidgets/views/View_qtwidgets.h b/src/qtwidgets/views/View_qtwidgets.h index 577e9637..43693030 100644 --- a/src/qtwidgets/views/View_qtwidgets.h +++ b/src/qtwidgets/views/View_qtwidgets.h @@ -381,6 +381,11 @@ public: return QWidget::objectName(); } + QVariant property(const char *name) const override + { + return QWidget::property(name); + } + protected: bool event(QEvent *e) override { @@ -427,5 +432,4 @@ inline void setTopLevelGeometry(QRect geometry, const QWidget *widget) topLevel->setGeometry(geometry); } - } // namespace KDDockWidgets::Views \ No newline at end of file diff --git a/tests/tst_docks.cpp b/tests/tst_docks.cpp index 3a92cb72..d79488ea 100644 --- a/tests/tst_docks.cpp +++ b/tests/tst_docks.cpp @@ -4844,7 +4844,7 @@ void TestDocks::tst_titleBarFocusedWhenTabsChange() auto tabBar2 = tb2->tabBar(); const QRect rect0 = tabBar2->rectForTab(0); const QPoint globalPos = tabBar2->view()->mapToGlobal(rect0.topLeft()) + QPoint(5, 5); - Tests::clickOn(globalPos, tabBar2->view()->asQWidget()); + Tests::clickOn(globalPos, tabBar2->view()); QVERIFY(!titleBar1->isFocused()); QVERIFY(dock2->titleBar()->isFocused()); @@ -4856,7 +4856,7 @@ void TestDocks::tst_titleBarFocusedWhenTabsChange() #ifdef KDDOCKWIDGETS_QTWIDGETS // TODO: Not yet ready for QtQuick. The TitleBar.qml is clicked, but we check the C++ TitleBar for focus - Tests::clickOn(globalPos, tabBar2->view()->asQWidget()); + Tests::clickOn(globalPos, tabBar2->view()); QVERIFY(!dock1->titleBar()->isFocused()); QVERIFY(dock2->titleBar()->isFocused()); #endif @@ -4883,8 +4883,8 @@ void TestDocks::tst_tabsNotClickable() const QPoint clickPoint = frame->tabBar()->mapToGlobal(frame->tabBar()->rectForTab(0).center()); QCursor::setPos(clickPoint); // Just for visual debug when needed - pressOn(clickPoint, frame->tabBar()->view()->asQWidget()); - releaseOn(clickPoint, frame->tabBar()->view()->asQWidget()); + pressOn(clickPoint, frame->tabBar()->view()); + releaseOn(clickPoint, frame->tabBar()->view()); // WAIT // Uncomment for MANUAL test. Also test by adding Flag_AlwaysShowTabs @@ -4919,7 +4919,7 @@ void TestDocks::tst_mainWindowAlwaysHasCentralWidget() // Detach tab QPoint globalPressPos = dragPointForWidget(centralFrame.data(), 0); - auto tabBar = qobject_cast(centralFrame->tabBar()->view()->asQWidget()); + auto tabBar = centralFrame->tabBar()->view(); QVERIFY(tabBar); qDebug() << "Detaching tab from dropArea->size=" << dropArea->QWidget::size() << "; dropArea=" << dropArea; drag(tabBar, globalPressPos, m->geometry().bottomRight() + QPoint(30, 30)); @@ -4967,7 +4967,7 @@ void TestDocks::tst_dockableMainWindows() const QPoint destination = startPoint + QPoint(20, 20); // Check that we don't get the "Refusing to itself" warning. not actually dropping anywhere - drag(fwTitleBar->view()->asQWidget(), startPoint, destination); + drag(fwTitleBar->view(), startPoint, destination); // The FloatingWindow has a single DockWidget, so it shows the title bar, while the Frame doesn't QVERIFY(fwTitleBar->isVisible()); @@ -5488,15 +5488,15 @@ void TestDocks::tst_sidebarOverlayGetsHiddenOnClick() QVERIFY(dw1->isOverlayed()); - Tests::clickOn(dw2->mapToGlobal(dw2->rect().bottomLeft() + QPoint(5, -5)), dw2->view()->asQWidget()); + Tests::clickOn(dw2->mapToGlobal(dw2->rect().bottomLeft() + QPoint(5, -5)), dw2->view()); QVERIFY(!dw1->isOverlayed()); auto widget2 = new MyWidget("foo"); dw2->setWidget(widget2); m1->overlayOnSideBar(dw1); QVERIFY(dw1->isOverlayed()); - - Tests::clickOn(widget2->mapToGlobal(widget2->rect().bottomLeft() + QPoint(5, -5)), widget2); + auto wrapper = ViewWrapper::Ptr(new Views::ViewWrapper_qtwidgets(widget2)); + Tests::clickOn(widget2->mapToGlobal(widget2->rect().bottomLeft() + QPoint(5, -5)), wrapper.get()); QVERIFY(!dw1->isOverlayed()); m1.reset(); @@ -5517,7 +5517,7 @@ void TestDocks::tst_sidebarOverlayGetsHiddenOnClick() QVERIFY(dw1->isOverlayed()); const QPoint localPt(100, 250); - Tests::clickOn(m1->mapToGlobal(m1->rect().topLeft() + localPt), m1->view()->asQWidget()->childAt(localPt)); + Tests::clickOn(m1->mapToGlobal(m1->rect().topLeft() + localPt), m1->view()->childViewAt(localPt).get()); QVERIFY(!dw1->isOverlayed()); } } @@ -5602,7 +5602,7 @@ void TestDocks::tst_overlayCrash() auto tb = dw2->titleBar(); QVERIFY(tb->isVisible()); - pressOn(tb->mapToGlobal(QPoint(5, 5)), tb->view()->asQWidget()); + pressOn(tb->mapToGlobal(QPoint(5, 5)), tb->view()); } void TestDocks::tst_embeddedMainWindow() @@ -6657,14 +6657,14 @@ void TestDocks::tst_flagDoubleClick() QVERIFY(!fw2->view()->isMaximized()); Controllers::TitleBar *t2 = dock2->titleBar(); QPoint pos = t2->mapToGlobal(QPoint(5, 5)); - Tests::doubleClickOn(pos, t2->view()->asQWidget()); + Tests::doubleClickOn(pos, t2->view()); QVERIFY(fw2->view()->isMaximized()); delete fw2; Controllers::TitleBar *t1 = dock1->titleBar(); QVERIFY(!t1->isFloating()); pos = t1->mapToGlobal(QPoint(5, 5)); - Tests::doubleClickOn(pos, t1->view()->asQWidget()); + Tests::doubleClickOn(pos, t1->view()); QVERIFY(t1->isFloating()); QVERIFY(!dock1->window()->isMaximized()); } @@ -6679,13 +6679,13 @@ void TestDocks::tst_flagDoubleClick() Controllers::TitleBar *t1 = dock1->titleBar(); QVERIFY(!t1->isFloating()); QPoint pos = t1->mapToGlobal(QPoint(5, 5)); - Tests::doubleClickOn(pos, t1->view()->asQWidget()); + Tests::doubleClickOn(pos, t1->view()); QVERIFY(t1->isFloating()); QVERIFY(dock1->isFloating()); QVERIFY(!dock1->window()->isMaximized()); pos = t1->mapToGlobal(QPoint(5, 5)); - Tests::doubleClickOn(pos, t1->view()->asQWidget()); + Tests::doubleClickOn(pos, t1->view()); QVERIFY(!dock1->isFloating()); } } @@ -7168,7 +7168,7 @@ void TestDocks::tst_dragBySingleTab() Controllers::TabBar *tabBar = frame1->tabWidget()->tabBar(); QVERIFY(tabBar); SetExpectedWarning sew("No window being dragged for"); // because dragging by tab does nothing in this case - drag(tabBar->view()->asQWidget(), globalPressPos, QPoint(0, 0)); + drag(tabBar->view(), globalPressPos, QPoint(0, 0)); delete dock1; Testing::waitForDeleted(frame1); @@ -7243,7 +7243,7 @@ void TestDocks::tst_dock2FloatingWidgetsTabbed() QVERIFY(dock2->isFloating()); QPoint finalPoint = dock2->window()->geometry().center() + QPoint(7, 7); - drag(titlebar1->view()->asQWidget(), titlebar1->mapToGlobal(QPoint(5, 5)), finalPoint, ButtonAction_Press); + drag(titlebar1->view(), titlebar1->mapToGlobal(QPoint(5, 5)), finalPoint, ButtonAction_Press); // It morphed into a FloatingWindow QPointer frame2 = dock2->dptr()->frame(); @@ -7254,7 +7254,7 @@ void TestDocks::tst_dock2FloatingWidgetsTabbed() QVERIFY(frame2); QCOMPARE(frame2->dockWidgetCount(), 1); - releaseOn(finalPoint, titlebar1->view()->asQWidget()); + releaseOn(finalPoint, titlebar1->view()); QCOMPARE(frame2->dockWidgetCount(), 2); // 2.2 Frame has 2 widgets when one is dropped QVERIFY(Testing::waitForDeleted(frame1)); @@ -7262,7 +7262,7 @@ void TestDocks::tst_dock2FloatingWidgetsTabbed() QPoint globalPressPos = dragPointForWidget(frame2.data(), 0); Controllers::TabBar *tabBar = frame2->tabWidget()->tabBar(); QVERIFY(tabBar); - drag(tabBar->view()->asQWidget(), globalPressPos, frame2->view()->windowGeometry().bottomRight() + QPoint(10, 10)); + drag(tabBar->view(), globalPressPos, frame2->view()->windowGeometry().bottomRight() + QPoint(10, 10)); QVERIFY(frame2->dockWidgetCount() == 1); QVERIFY(dock1->floatingWindow()); @@ -7273,7 +7273,7 @@ void TestDocks::tst_dock2FloatingWidgetsTabbed() fw1 = dock1->floatingWindow(); globalPressPos = fw1->titleBar()->mapToGlobal(QPoint(100, 5)); finalPoint = dock2->window()->geometry().center() + QPoint(7, 7); - drag(fw1->titleBar()->view()->asQWidget(), globalPressPos, finalPoint); + drag(fw1->titleBar()->view(), globalPressPos, finalPoint); QCOMPARE(frame2->dockWidgetCount(), 2); @@ -7282,7 +7282,7 @@ void TestDocks::tst_dock2FloatingWidgetsTabbed() tabBar = frame2->tabWidget()->tabBar(); finalPoint = dock2->window()->geometry().center() + QPoint(7, 7); - drag(tabBar->view()->asQWidget(), globalPressPos, finalPoint); + drag(tabBar->view(), globalPressPos, finalPoint); QCOMPARE(frame2->dockWidgetCount(), 2); // 2.6 Drag the tabbed group over a 3rd floating window @@ -7291,7 +7291,7 @@ void TestDocks::tst_dock2FloatingWidgetsTabbed() auto fw2 = dock2->floatingWindow(); finalPoint = dock3->window()->geometry().center() + QPoint(7, 7); - drag(fw2->titleBar()->view()->asQWidget(), frame2->mapToGlobal(QPoint(10, 10)), finalPoint); + drag(fw2->titleBar()->view(), frame2->mapToGlobal(QPoint(10, 10)), finalPoint); QVERIFY(Testing::waitForDeleted(frame1)); QVERIFY(Testing::waitForDeleted(frame2)); @@ -7309,7 +7309,7 @@ void TestDocks::tst_dock2FloatingWidgetsTabbed() m->view()->setGeometry(QRect(500, 300, 300, 300)); QVERIFY(!dock3->isFloating()); auto fw3 = dock3->floatingWindow(); - drag(fw3->titleBar()->view()->asQWidget(), dock3->window()->mapToGlobal(QPoint(10, 10)), m->geometry().center()); + drag(fw3->titleBar()->view(), dock3->window()->mapToGlobal(QPoint(10, 10)), m->geometry().center()); QVERIFY(!dock3->isFloating()); QVERIFY(dock3->window()->asQWidget() == m->view()->asQWidget()); QCOMPARE(dock3->dptr()->frame()->dockWidgetCount(), 3); diff --git a/tests/utils.cpp b/tests/utils.cpp index 457a4e09..8290642d 100644 --- a/tests/utils.cpp +++ b/tests/utils.cpp @@ -14,6 +14,7 @@ #include "Config.h" #include "FrameworkWidgetFactory.h" #include "Platform.h" +#include "ViewGuard.h" #include #include @@ -188,7 +189,7 @@ bool KDDockWidgets::Tests::shouldBlacklistWarning(const QString &msg, const QStr return msg.contains(QLatin1String("QSocketNotifier: Invalid socket")) || msg.contains(QLatin1String("QWindowsWindow::setGeometry")) || msg.contains(QLatin1String("This plugin does not support")) || msg.contains(QLatin1String("Note that Qt no longer ships fonts")) || msg.contains(QLatin1String("Another dock KDDockWidgets::DockWidget")) || msg.contains(QLatin1String("There's multiple MainWindows, not sure what to do about parenting")); } -void KDDockWidgets::Tests::doubleClickOn(QPoint globalPos, WidgetType *receiver) +void KDDockWidgets::Tests::doubleClickOn(QPoint globalPos, View *receiver) { QCursor::setPos(globalPos); pressOn(globalPos, receiver); // double-click involves an initial press @@ -201,7 +202,7 @@ void KDDockWidgets::Tests::doubleClickOn(QPoint globalPos, WidgetType *receiver) qApp->sendEvent(actualReceiver, &ev); } else { // QtWidgets case - qApp->sendEvent(receiver, &ev); + Platform::instance()->tests_sendEvent(receiver, &ev); } } @@ -215,12 +216,12 @@ void KDDockWidgets::Tests::doubleClickOn(QPoint globalPos, Window::Ptr receiver) Platform::instance()->tests_sendEvent(receiver, &ev); } -void KDDockWidgets::Tests::pressOn(QPoint globalPos, WidgetType *receiver) +void KDDockWidgets::Tests::pressOn(QPoint globalPos, View *receiver) { QCursor::setPos(globalPos); QMouseEvent ev(QEvent::MouseButtonPress, receiver->mapFromGlobal(globalPos), receiver->window()->mapFromGlobal(globalPos), globalPos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); - qApp->sendEvent(receiver, &ev); + Platform::instance()->tests_sendEvent(receiver, &ev); } void KDDockWidgets::Tests::pressOn(QPoint globalPos, Window::Ptr receiver) @@ -231,23 +232,23 @@ void KDDockWidgets::Tests::pressOn(QPoint globalPos, Window::Ptr receiver) Platform::instance()->tests_sendEvent(receiver, &ev); } -void KDDockWidgets::Tests::releaseOn(QPoint globalPos, WidgetType *receiver) +void KDDockWidgets::Tests::releaseOn(QPoint globalPos, View *receiver) { QMouseEvent ev(QEvent::MouseButtonRelease, receiver->mapFromGlobal(globalPos), receiver->window()->mapFromGlobal(globalPos), globalPos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); - qApp->sendEvent(receiver, &ev); + Platform::instance()->tests_sendEvent(receiver, &ev); } -void KDDockWidgets::Tests::clickOn(QPoint globalPos, WidgetType *receiver) +void KDDockWidgets::Tests::clickOn(QPoint globalPos, View *receiver) { pressOn(globalPos, receiver); releaseOn(globalPos, receiver); } -void KDDockWidgets::Tests::moveMouseTo(QPoint globalDest, WidgetType *receiver) +void KDDockWidgets::Tests::moveMouseTo(QPoint globalDest, View *receiver) { - QPoint globalSrc = KDDockWidgets::mapToGlobal(receiver, QPoint(5, 5)); - auto receiverP = Tests::make_qpointer(receiver); + QPoint globalSrc = receiver->mapToGlobal(QPoint(5, 5)); + ViewGuard receiverP = receiver; while (globalSrc != globalDest) { if (globalSrc.x() < globalDest.x()) { @@ -270,7 +271,7 @@ void KDDockWidgets::Tests::moveMouseTo(QPoint globalDest, WidgetType *receiver) return; } - qApp->sendEvent(receiver, &ev); + Platform::instance()->tests_sendEvent(receiver, &ev); QTest::qWait(2); } } diff --git a/tests/utils.h b/tests/utils.h index 07e65f71..a170384b 100644 --- a/tests/utils.h +++ b/tests/utils.h @@ -329,13 +329,13 @@ public: #endif -void doubleClickOn(QPoint globalPos, WidgetType *receiver); +void doubleClickOn(QPoint globalPos, View *receiver); void doubleClickOn(QPoint globalPos, Window::Ptr receiver); -void pressOn(QPoint globalPos, WidgetType *receiver); +void pressOn(QPoint globalPos, View *receiver); void pressOn(QPoint globalPos, Window::Ptr receiver); -void releaseOn(QPoint globalPos, WidgetType *receiver); -void clickOn(QPoint globalPos, WidgetType *receiver); -void moveMouseTo(QPoint globalDest, WidgetType *receiver); +void releaseOn(QPoint globalPos, View *receiver); +void clickOn(QPoint globalPos, View *receiver); +void moveMouseTo(QPoint globalDest, View *receiver); inline Controllers::FloatingWindow *createFloatingWindow() { @@ -345,30 +345,30 @@ inline Controllers::FloatingWindow *createFloatingWindow() return dock->d->morphIntoFloatingWindow(); } -inline WidgetType *draggableFor(View *view) +inline View *draggableFor(View *view) { - WidgetType *draggable = nullptr; + View *draggable = nullptr; if (auto dw = view->asDockWidgetController()) { if (auto frame = dw->d->frame()) - draggable = frame->titleBar()->view()->asQWidget(); + draggable = frame->titleBar()->view(); } else if (auto fw = view->asFloatingWindowController()) { Controllers::Frame *frame = fw->hasSingleFrame() ? static_cast(fw->frames().first()) : nullptr; if ((KDDockWidgets::Config::self().flags() & KDDockWidgets::Config::Flag_HideTitleBarWhenTabsVisible) && frame && frame->hasTabsVisible()) { - draggable = frame->tabWidget()->view()->asQWidget(); + draggable = frame->tabWidget()->view(); } else { - draggable = fw->titleBar()->view()->asQWidget(); + draggable = fw->titleBar()->view(); } } else if (view->is(Type::Stack) || view->is(Type::TitleBar)) { - draggable = view->asQWidget(); + draggable = view; } qDebug() << "Draggable is" << draggable << "for" << view; return draggable; } -inline void drag(WidgetType *sourceWidget, QPoint pressGlobalPos, QPoint globalDest, +inline void drag(View *sourceWidget, QPoint pressGlobalPos, QPoint globalDest, ButtonActions buttonActions = ButtonActions(ButtonAction_Press) | ButtonAction_Release) { if (buttonActions & ButtonAction_Press) { @@ -378,7 +378,7 @@ inline void drag(WidgetType *sourceWidget, QPoint pressGlobalPos, QPoint globalD pressOn(pressGlobalPos, sourceWidget); } - activateWindow(sourceWidget->window()); + sourceWidget->activateWindow(); if (s_pauseBeforeMove) QTest::qWait(DEBUGGING_PAUSE_DURATION); @@ -392,7 +392,7 @@ inline void drag(WidgetType *sourceWidget, QPoint pressGlobalPos, QPoint globalD << "; visible=" << sourceWidget->isVisible(); moveMouseTo(globalDest, sourceWidget); qDebug() << "Arrived at" << QCursor::pos(); - pressGlobalPos = KDDockWidgets::mapToGlobal(sourceWidget, QPoint(10, 10)); + pressGlobalPos = sourceWidget->mapToGlobal(QPoint(10, 10)); if (buttonActions & ButtonAction_Release) releaseOn(globalDest, sourceWidget); } @@ -402,10 +402,10 @@ inline void drag(View *sourceView, QPoint globalDest, { Q_ASSERT(sourceView && sourceView->isVisible()); - WidgetType *draggable = draggableFor(sourceView); + View *draggable = draggableFor(sourceView); Q_ASSERT(draggable && draggable->isVisible()); - const QPoint pressGlobalPos = KDDockWidgets::mapToGlobal(draggable, QPoint(15, 15)); + const QPoint pressGlobalPos = draggable->mapToGlobal(QPoint(15, 15)); drag(draggable, pressGlobalPos, globalDest, buttonActions); } @@ -413,10 +413,10 @@ inline void drag(View *sourceView, QPoint globalDest, inline void dragFloatingWindowTo(Controllers::FloatingWindow *fw, QPoint globalDest, ButtonActions buttonActions = ButtonActions(ButtonAction_Press) | ButtonAction_Release) { - auto draggable = draggableFor(fw->view()); + View *draggable = draggableFor(fw->view()); Q_ASSERT(draggable); Q_ASSERT(draggable->isVisible()); - drag(draggable, KDDockWidgets::mapToGlobal(draggable, QPoint(10, 10)), globalDest, buttonActions); + drag(draggable, draggable->mapToGlobal(QPoint(10, 10)), globalDest, buttonActions); } inline void dragFloatingWindowTo(Controllers::FloatingWindow *fw, DropArea *target, DropLocation dropLocation) @@ -425,7 +425,7 @@ inline void dragFloatingWindowTo(Controllers::FloatingWindow *fw, DropArea *targ Q_ASSERT(draggable); // First we drag over it, so the drop indicators appear: - drag(draggable, KDDockWidgets::mapToGlobal(draggable, QPoint(10, 10)), target->window()->mapToGlobal(target->window()->rect().center()), ButtonAction_Press); + drag(draggable, draggable->mapToGlobal(QPoint(10, 10)), target->window()->mapToGlobal(target->window()->rect().center()), ButtonAction_Press); // Now we drag over the drop indicator and only then release mouse: DropIndicatorOverlayInterface *dropIndicatorOverlay = target->dropIndicatorOverlay();