summaryrefslogtreecommitdiffstats
path: root/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp')
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp1168
1 files changed, 651 insertions, 517 deletions
diff --git a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp
index e9ba24f4fc..f14b7299b5 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp
@@ -1,38 +1,18 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QTest>
#include <QtGui>
#include <QtWidgets>
+#include <QSignalSpy>
#include <private/qgraphicsproxywidget_p.h>
#include <private/qlayoutengine_p.h> // qSmartMin functions...
+#include <QtWidgets/private/qapplication_p.h>
+
+Q_LOGGING_CATEGORY(lcTests, "qt.widgets.tests")
+
/*
Notes:
@@ -60,7 +40,7 @@ public:
QMap<QEvent::Type, int> counts;
protected:
- bool eventFilter(QObject *, QEvent *event)
+ bool eventFilter(QObject *, QEvent *event) override
{
++counts[event->type()];
return false;
@@ -74,7 +54,6 @@ class tst_QGraphicsProxyWidget : public QObject
private slots:
void initTestCase();
void cleanup();
- void qgraphicsproxywidget_data();
void qgraphicsproxywidget();
void paint();
void paint_2();
@@ -92,13 +71,10 @@ private slots:
void focusProxy_QTBUG_51856();
void hoverEnterLeaveEvent_data();
void hoverEnterLeaveEvent();
- void hoverMoveEvent_data();
- void hoverMoveEvent();
void keyPressEvent_data();
void keyPressEvent();
void keyReleaseEvent_data();
void keyReleaseEvent();
- void mouseDoubleClickEvent_data();
void mouseDoubleClickEvent();
void mousePressReleaseEvent_data();
void mousePressReleaseEvent();
@@ -108,8 +84,6 @@ private slots:
#if QT_CONFIG(wheelevent)
void wheelEvent();
#endif
- void sizeHint_data();
- void sizeHint();
void sizePolicy();
void minimumSize();
void maximumSize();
@@ -162,88 +136,39 @@ private slots:
void mapToGlobal();
void mapToGlobalWithoutScene();
void QTBUG_43780_visibility();
+#if QT_CONFIG(wheelevent)
+ void wheelEventPropagation();
+#endif
void forwardTouchEvent();
+ void touchEventPropagation();
};
// Subclass that exposes the protected functions.
class SubQGraphicsProxyWidget : public QGraphicsProxyWidget
{
-
+ friend tst_QGraphicsProxyWidget;
public:
- SubQGraphicsProxyWidget(QGraphicsItem *parent = nullptr) : QGraphicsProxyWidget(parent),
- paintCount(0), keyPress(0), focusOut(0)
- {}
-
- bool call_eventFilter(QObject* object, QEvent* event)
- { return SubQGraphicsProxyWidget::eventFilter(object, event); }
-
- void call_focusInEvent(QFocusEvent* event)
- { return SubQGraphicsProxyWidget::focusInEvent(event); }
-
- bool call_focusNextPrevChild(bool next)
- { return SubQGraphicsProxyWidget::focusNextPrevChild(next); }
-
- void call_focusOutEvent(QFocusEvent* event)
- { return SubQGraphicsProxyWidget::focusOutEvent(event); }
-
- void call_hideEvent(QHideEvent* event)
- { return SubQGraphicsProxyWidget::hideEvent(event); }
-
- void call_hoverEnterEvent(QGraphicsSceneHoverEvent* event)
- { return SubQGraphicsProxyWidget::hoverEnterEvent(event); }
-
- void call_hoverLeaveEvent(QGraphicsSceneHoverEvent* event)
- { return SubQGraphicsProxyWidget::hoverLeaveEvent(event); }
-
- void call_hoverMoveEvent(QGraphicsSceneHoverEvent* event)
- { return SubQGraphicsProxyWidget::hoverMoveEvent(event); }
-
- void call_keyPressEvent(QKeyEvent* event)
- { return SubQGraphicsProxyWidget::keyPressEvent(event); }
-
- void call_keyReleaseEvent(QKeyEvent* event)
- { return SubQGraphicsProxyWidget::keyReleaseEvent(event); }
-
- void call_mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event)
- { return SubQGraphicsProxyWidget::mouseDoubleClickEvent(event); }
-
- void call_mouseMoveEvent(QGraphicsSceneMouseEvent* event)
- { return SubQGraphicsProxyWidget::mouseMoveEvent(event); }
+ using QGraphicsProxyWidget::QGraphicsProxyWidget;
- void call_mousePressEvent(QGraphicsSceneMouseEvent* event)
- { return SubQGraphicsProxyWidget::mousePressEvent(event); }
-
- void call_mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
- { return SubQGraphicsProxyWidget::mouseReleaseEvent(event); }
-
- void call_resizeEvent(QGraphicsSceneResizeEvent* event)
- { return SubQGraphicsProxyWidget::resizeEvent(event); }
-
- QSizeF call_sizeHint(Qt::SizeHint which, QSizeF const& constraint = QSizeF()) const
- { return SubQGraphicsProxyWidget::sizeHint(which, constraint); }
-
- void call_showEvent(QShowEvent* event)
- { return SubQGraphicsProxyWidget::showEvent(event); }
-
- void paint (QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) {
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override {
paintCount++;
QGraphicsProxyWidget::paint(painter, option, widget);
}
- void focusOutEvent(QFocusEvent *event)
+ void focusOutEvent(QFocusEvent *event) override
{
focusOut++;
QGraphicsProxyWidget::focusOutEvent(event);
}
- bool eventFilter(QObject *object, QEvent *event) {
+ bool eventFilter(QObject *object, QEvent *event) override {
if (event->type() == QEvent::KeyPress && object == widget())
keyPress++;
return QGraphicsProxyWidget::eventFilter(object, event);
}
- int paintCount;
- int keyPress;
- int focusOut;
+ int paintCount = 0;
+ int keyPress = 0;
+ int focusOut = 0;
};
#if QT_CONFIG(wheelevent)
@@ -252,7 +177,7 @@ class WheelWidget : public QWidget
public:
WheelWidget() : wheelEventCalled(false) { setFocusPolicy(Qt::WheelFocus); }
- virtual void wheelEvent(QWheelEvent *event) { event->accept(); wheelEventCalled = true; }
+ virtual void wheelEvent(QWheelEvent *event) override { event->accept(); wheelEventCalled = true; }
bool wheelEventCalled;
};
@@ -276,10 +201,6 @@ void tst_QGraphicsProxyWidget::cleanup()
QTRY_VERIFY(QApplication::topLevelWidgets().isEmpty());
}
-void tst_QGraphicsProxyWidget::qgraphicsproxywidget_data()
-{
-}
-
void tst_QGraphicsProxyWidget::qgraphicsproxywidget()
{
SubQGraphicsProxyWidget proxy;
@@ -288,46 +209,47 @@ void tst_QGraphicsProxyWidget::qgraphicsproxywidget()
QCOMPARE(proxy.type(), int(QGraphicsProxyWidget::Type));
QVERIFY(!proxy.widget());
QEvent event(QEvent::None);
- proxy.call_eventFilter(0, &event);
+ proxy.eventFilter(0, &event);
QFocusEvent focusEvent(QEvent::FocusIn);
focusEvent.ignore();
- proxy.call_focusInEvent(&focusEvent);
+ proxy.focusInEvent(&focusEvent);
QCOMPARE(focusEvent.isAccepted(), false);
- QCOMPARE(proxy.call_focusNextPrevChild(false), false);
- QCOMPARE(proxy.call_focusNextPrevChild(true), false);
- proxy.call_focusOutEvent(&focusEvent);
+ QCOMPARE(proxy.focusNextPrevChild(false), false);
+ QCOMPARE(proxy.focusNextPrevChild(true), false);
+ proxy.focusOutEvent(&focusEvent);
QHideEvent hideEvent;
- proxy.call_hideEvent(&hideEvent);
+ proxy.hideEvent(&hideEvent);
QGraphicsSceneHoverEvent hoverEvent;
- proxy.call_hoverEnterEvent(&hoverEvent);
- proxy.call_hoverLeaveEvent(&hoverEvent);
- proxy.call_hoverMoveEvent(&hoverEvent);
+ proxy.hoverEnterEvent(&hoverEvent);
+ proxy.hoverLeaveEvent(&hoverEvent);
+ proxy.hoverMoveEvent(&hoverEvent);
QKeyEvent keyEvent(QEvent::KeyPress, 0, Qt::NoModifier);
- proxy.call_keyPressEvent(&keyEvent);
- proxy.call_keyReleaseEvent(&keyEvent);
+ proxy.keyPressEvent(&keyEvent);
+ proxy.keyReleaseEvent(&keyEvent);
QGraphicsSceneMouseEvent mouseEvent;
- proxy.call_mouseDoubleClickEvent(&mouseEvent);
- proxy.call_mouseMoveEvent(&mouseEvent);
- proxy.call_mousePressEvent(&mouseEvent);
- proxy.call_mouseReleaseEvent(&mouseEvent);
+ proxy.mouseDoubleClickEvent(&mouseEvent);
+ proxy.mouseMoveEvent(&mouseEvent);
+ proxy.mousePressEvent(&mouseEvent);
+ proxy.mouseReleaseEvent(&mouseEvent);
QGraphicsSceneResizeEvent resizeEvent;
- proxy.call_resizeEvent(&resizeEvent);
+ proxy.resizeEvent(&resizeEvent);
QShowEvent showEvent;
- proxy.call_showEvent(&showEvent);
- proxy.call_sizeHint(Qt::PreferredSize, QSizeF());
+ proxy.showEvent(&showEvent);
+ proxy.sizeHint(Qt::PreferredSize, QSizeF());
}
// public void paint(QPainter* painter, QStyleOptionGraphicsItem const* option, QWidget* widget)
void tst_QGraphicsProxyWidget::paint()
{
SubQGraphicsProxyWidget proxy;
+
proxy.paint(0, 0, 0);
}
class MyProxyWidget : public QGraphicsProxyWidget
{
public:
- void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override
{
// Make sure QGraphicsProxyWidget::paint does not modify the render hints set on the painter.
painter->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform
@@ -386,6 +308,8 @@ void tst_QGraphicsProxyWidget::setWidget()
QGraphicsView view(&scene);
view.show();
QScopedPointer<QStyle> style(QStyleFactory::create(QLatin1String("Fusion")));
+ if (style.isNull())
+ QSKIP("This test requires the Fusion style");
QVERIFY(QTest::qWaitForWindowExposed(&view));
QPointer<SubQGraphicsProxyWidget> proxy = new SubQGraphicsProxyWidget;
SubQGraphicsProxyWidget parentProxy;
@@ -411,7 +335,7 @@ void tst_QGraphicsProxyWidget::setWidget()
widget->setStyle(style.data());
widget->setFont(QFont("Times"));
widget->setVisible(true);
- QApplication::setActiveWindow(widget);
+ QApplicationPrivate::setActiveWindow(widget);
widget->activateWindow();
widget->setEnabled(true);
widget->resize(325, 241);
@@ -433,6 +357,10 @@ void tst_QGraphicsProxyWidget::setWidget()
if (shouldBeInsertable)
subWidget->setAttribute(Qt::WA_QuitOnClose, true);
+ if (hasParent) {
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression(
+ "QGraphicsProxyWidget::setWidget: cannot embed widget .* which is not a toplevel widget, and is not a child of an embedded widget"));
+ }
proxy->setWidget(subWidget);
if (shouldBeInsertable) {
@@ -548,7 +476,7 @@ void tst_QGraphicsProxyWidget::testEventFilter()
switch (eventType) {
case QEvent::None: {
QEvent event(QEvent::None);
- proxy->call_eventFilter(widget, &event);
+ proxy->eventFilter(widget, &event);
break;
}
case QEvent::Resize: {
@@ -580,7 +508,7 @@ void tst_QGraphicsProxyWidget::testEventFilter()
widget->hide();
} else {
QHideEvent event;
- proxy->call_eventFilter(widget, &event);
+ proxy->eventFilter(widget, &event);
}
QCOMPARE(proxy->isVisible(), false);
break;
@@ -592,7 +520,7 @@ void tst_QGraphicsProxyWidget::testEventFilter()
widget->show();
} else {
QShowEvent event;
- proxy->call_eventFilter(widget, &event);
+ proxy->eventFilter(widget, &event);
}
QCOMPARE(proxy->isVisible(), true);
break;
@@ -607,7 +535,7 @@ void tst_QGraphicsProxyWidget::testEventFilter()
QCOMPARE(proxy->isEnabled(), false);
} else {
QEvent event(QEvent::EnabledChange);
- proxy->call_eventFilter(widget, &event);
+ proxy->eventFilter(widget, &event);
// match the widget not the event
QCOMPARE(proxy->isEnabled(), false);
}
@@ -635,7 +563,7 @@ void tst_QGraphicsProxyWidget::testEventFilter()
QTest::keyPress(widget, Qt::Key_A, Qt::NoModifier);
} else {
QKeyEvent event(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier);
- proxy->call_eventFilter(widget, &event);
+ proxy->eventFilter(widget, &event);
}
QCOMPARE(proxy->keyPress, 1);
break;
@@ -695,7 +623,7 @@ void tst_QGraphicsProxyWidget::focusInEvent()
QFocusEvent event(QEvent::FocusIn, Qt::TabFocusReason);
event.ignore();
- proxy->call_focusInEvent(&event);
+ proxy->focusInEvent(&event);
QTRY_COMPARE(widget->hasFocus(), widgetCanHaveFocus);
}
@@ -712,7 +640,7 @@ void tst_QGraphicsProxyWidget::focusInEventNoWidget()
QFocusEvent event(QEvent::FocusIn, Qt::TabFocusReason);
event.ignore();
//should not crash
- proxy->call_focusInEvent(&event);
+ proxy->focusInEvent(&event);
}
void tst_QGraphicsProxyWidget::focusNextPrevChild_data()
@@ -750,23 +678,40 @@ void tst_QGraphicsProxyWidget::focusNextPrevChild()
// otherwise respect the scene
// Respect the widget over the scene!
- SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
-
- QLabel *widget = new QLabel;
- // I can't believe designer adds this much junk!
- widget->setText("<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\"> p, li { white-space: pre-wrap; } </style></head><body style=\" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;\"> <p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><a href=\"http://www.slashdot.org\"><span style=\" text-decoration: underline; color:#0000ff;\">old</span></a> foo <a href=\"http://www.reddit.org\"><span style=\" text-decoration: underline; color:#0000ff;\">new</span></a></p></body></html>");
- widget->setTextInteractionFlags(Qt::TextBrowserInteraction);
+ std::unique_ptr<SubQGraphicsProxyWidget> proxyGuard(new SubQGraphicsProxyWidget);
+ auto *proxy = proxyGuard.get();
- if (hasWidget)
+ if (hasWidget) {
+ QLabel *widget = new QLabel;
+ widget->setText(R"(
+ <html>
+ <head>
+ <meta name=\"qrichtext\" content=\"1\" />
+ <style type=\"text/css\">
+ p, li { white-space: pre-wrap; }
+ </style>
+ </head>
+ <body>
+ <p>
+ <a href=\"http://www.slashdot.org\">
+ <span style=\" text-decoration: underline; color:#0000ff;\">old</span>
+ </a> foo
+ <a href=\"http://www.reddit.org\">
+ <span style=\" text-decoration: underline; color:#0000ff;\">new</span>
+ </a>
+ </p>
+ </body>
+ </html>)");
+ widget->setTextInteractionFlags(Qt::TextBrowserInteraction);
proxy->setWidget(widget);
+ }
QGraphicsScene scene;
QGraphicsView view(&scene);
view.show();
- QApplication::setActiveWindow(&view);
QVERIFY(QTest::qWaitForWindowActive(&view));
if (hasScene) {
- scene.addItem(proxy);
+ scene.addItem(proxyGuard.release());
proxy->show();
// widget should take precedence over scene so make scene.focusNextPrevChild return false
@@ -781,12 +726,7 @@ void tst_QGraphicsProxyWidget::focusNextPrevChild()
QVERIFY(proxy->hasFocus());
}
- QCOMPARE(proxy->call_focusNextPrevChild(next), focusNextPrevChild);
-
- if (!hasScene)
- delete proxy;
- if (!hasWidget)
- delete widget;
+ QCOMPARE(proxy->focusNextPrevChild(next), focusNextPrevChild);
}
void tst_QGraphicsProxyWidget::focusOutEvent_data()
@@ -810,18 +750,17 @@ void tst_QGraphicsProxyWidget::focusOutEvent()
SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
scene.addItem(proxy);
view.show();
- QApplication::setActiveWindow(&view);
view.activateWindow();
view.setFocus();
QVERIFY(QTest::qWaitForWindowActive(&view));
QTRY_VERIFY(view.isVisible());
QTRY_COMPARE(QApplication::activeWindow(), (QWidget*)&view);
- QScopedPointer<QWidget> widgetGuard(new QWidget);
- QWidget *widget = widgetGuard.data();
- widget->setFocusPolicy(Qt::WheelFocus);
+ std::unique_ptr<QWidget> widgetGuard(new QWidget);
+ QWidget *widget = widgetGuard.get();
+ widgetGuard->setFocusPolicy(Qt::WheelFocus);
if (hasWidget)
- proxy->setWidget(widgetGuard.take());
+ proxy->setWidget(widgetGuard.release());
proxy->show();
proxy->setFocus();
QVERIFY(proxy->hasFocus());
@@ -832,41 +771,20 @@ void tst_QGraphicsProxyWidget::focusOutEvent()
if (!call) {
QWidget *other = new QLineEdit(&view);
other->show();
- QApplication::processEvents();
QTRY_VERIFY(other->isVisible());
other->setFocus();
QTRY_VERIFY(other->hasFocus());
- qApp->processEvents();
QTRY_COMPARE(proxy->hasFocus(), false);
QVERIFY(proxy->focusOut);
QCOMPARE(widget->hasFocus(), false);
- } else {
- {
- /*
- ### Test doesn't make sense
- QFocusEvent focusEvent(QEvent::FocusOut);
- proxy->call_focusOutEvent(&focusEvent);
- QCOMPARE(focusEvent.isAccepted(), hasWidget);
- qApp->processEvents();
- QCOMPARE(proxy->paintCount, hasWidget ? 1 : 0);
- */
- }
- {
- /*
- ### Test doesn't make sense
- proxy->setFlag(QGraphicsItem::ItemIsFocusable, false);
- QFocusEvent focusEvent(QEvent::FocusOut);
- proxy->call_focusOutEvent(&focusEvent);
- QCOMPARE(focusEvent.isAccepted(), hasWidget);
- qApp->processEvents();
- QCOMPARE(proxy->paintCount, 0);
- */
- }
}
}
void tst_QGraphicsProxyWidget::focusProxy_QTBUG_51856()
{
+#ifdef ANDROID
+ QSKIP("This test leads to failures on subsequent test cases, QTBUG-119574");
+#endif
// QSpinBox has an internal QLineEdit; this QLineEdit has the spinbox
// as its focus proxy.
struct FocusedSpinBox : QSpinBox
@@ -889,6 +807,9 @@ void tst_QGraphicsProxyWidget::focusProxy_QTBUG_51856()
}
};
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
+ QSKIP("QWindow::requestActivate() is not supported.");
+
QGraphicsScene scene;
QGraphicsView view(&scene);
SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
@@ -943,19 +864,19 @@ public:
installEventFilter(this);
}
- void enterEvent(QEnterEvent *event)
+ void enterEvent(QEnterEvent *event) override
{
enterCount++;
QWidget::enterEvent(event);
}
- void leaveEvent(QEvent *event )
+ void leaveEvent(QEvent *event ) override
{
leaveCount++;
QWidget::leaveEvent(event);
}
- void mouseMoveEvent(QMouseEvent *event)
+ void mouseMoveEvent(QMouseEvent *event) override
{
event->setAccepted(true);
moveCount++;
@@ -970,7 +891,7 @@ public:
int hoverLeave;
int hoverMove;
protected:
- bool eventFilter(QObject *object, QEvent *event)
+ bool eventFilter(QObject *object, QEvent *event) override
{
switch (event->type()) {
case QEvent::HoverEnter:
@@ -1010,22 +931,21 @@ void tst_QGraphicsProxyWidget::hoverEnterLeaveEvent()
QGraphicsScene scene;
QGraphicsView view(&scene);
view.show();
- QApplication::setActiveWindow(&view);
QVERIFY(QTest::qWaitForWindowActive(&view));
SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
- QScopedPointer<EventLogger> widgetGuard(new EventLogger);
- EventLogger *widget = widgetGuard.data();
+ std::unique_ptr<EventLogger> widgetGuard(new EventLogger);
+ EventLogger *widget = widgetGuard.get();
widget->resize(50, 50);
widget->setAttribute(Qt::WA_Hover, hoverEnabled);
widget->setMouseTracking(true);
view.resize(100, 100);
if (hasWidget)
- proxy->setWidget(widgetGuard.take());
+ proxy->setWidget(widgetGuard.release());
proxy->setPos(50, 0);
QSignalSpy sceneChangedSpy(&scene, &QGraphicsScene::changed);
scene.addItem(proxy);
- QTRY_VERIFY(sceneChangedSpy.count() > 0);
+ QTRY_VERIFY(sceneChangedSpy.size() > 0);
// outside graphics item
QTest::mouseMove(&view, QPoint(10, 10));
@@ -1048,75 +968,6 @@ void tst_QGraphicsProxyWidget::hoverEnterLeaveEvent()
QTRY_COMPARE(widget->hoverLeave, (hasWidget && hoverEnabled) ? 1 : 0);
}
-void tst_QGraphicsProxyWidget::hoverMoveEvent_data()
-{
- QTest::addColumn<bool>("hasWidget");
- QTest::addColumn<bool>("hoverEnabled");
- QTest::addColumn<bool>("mouseTracking");
- QTest::addColumn<bool>("mouseDown");
- for (int i = 0; i < 2; ++i) {
- for (int j = 0; j < 2; ++j) {
- for (int k = 0; k < 2; ++k) {
- for (int l = 0; l < 2; ++l) {
- bool hasWidget = (i == 0);
- bool hoverEnabled = (j == 0);
- bool mouseTracking = (k == 0);
- bool mouseDown = (l == 0);
- QByteArray name = QByteArrayLiteral("hasWidget:") + (hasWidget ? '1' : '0') + ", hover:"
- + (hoverEnabled ? '1' : '0') + ", mouseTracking:"
- + (mouseTracking ? '1' : '0') + ", mouseDown: " + (mouseDown ? '1' : '0');
- QTest::newRow(name.constData()) << hasWidget << hoverEnabled << mouseTracking << mouseDown;
- }
- }
- }
- }
-}
-
-// protected void hoverMoveEvent(QGraphicsSceneHoverEvent* event)
-void tst_QGraphicsProxyWidget::hoverMoveEvent()
-{
- QFETCH(bool, hasWidget);
- QFETCH(bool, hoverEnabled);
- QFETCH(bool, mouseTracking);
- QFETCH(bool, mouseDown);
-
- QSKIP("Ambiguous test...");
-
- // proxy should translate the move events to what the widget would expect
-
- QGraphicsScene scene;
- QGraphicsView view(&scene);
- view.show();
-
- SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
- proxy->setFlag(QGraphicsItem::ItemIsFocusable, true); // ### remove me!!!
- EventLogger *widget = new EventLogger;
- widget->resize(50, 50);
- widget->setAttribute(Qt::WA_Hover, hoverEnabled);
- if (mouseTracking)
- widget->setMouseTracking(true);
- view.resize(100, 100);
- if (hasWidget)
- proxy->setWidget(widget);
- proxy->setPos(50, 0);
- scene.addItem(proxy);
-
- // in
- QTest::mouseMove(&view, QPoint(50, 50));
- QTest::qWait(12);
-
- if (mouseDown)
- QTest::mousePress(view.viewport(), Qt::LeftButton);
-
- // move a little bit
- QTest::mouseMove(&view, QPoint(60, 60));
- QTRY_COMPARE(widget->hoverEnter, (hasWidget && hoverEnabled) ? 1 : 0);
- QCOMPARE(widget->moveCount, (hasWidget && mouseTracking) || (hasWidget && mouseDown) ? 1 : 0);
-
- if (!hasWidget)
- delete widget;
-}
-
void tst_QGraphicsProxyWidget::keyPressEvent_data()
{
QTest::addColumn<bool>("hasWidget");
@@ -1133,30 +984,27 @@ void tst_QGraphicsProxyWidget::keyPressEvent()
QGraphicsView view(&scene);
view.show();
view.viewport()->setFocus();
- QApplication::setActiveWindow(&view);
QVERIFY(QTest::qWaitForWindowActive(&view));
QCOMPARE(QApplication::activeWindow(), (QWidget*)&view);
SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
proxy->setFlag(QGraphicsItem::ItemIsFocusable, true); // ### remove me!!!
- QLineEdit *widget = new QLineEdit;
+ std::unique_ptr<QLineEdit> widgetGuard(new QLineEdit);
+ QLineEdit *widget = widgetGuard.get();
widget->resize(50, 50);
view.resize(100, 100);
- if (hasWidget) {
- proxy->setWidget(widget);
- proxy->show();
- }
- proxy->setPos(50, 0);
+ if (hasWidget)
+ proxy->setWidget(widgetGuard.release());
+
scene.addItem(proxy);
+ proxy->show();
+ proxy->setPos(50, 0);
proxy->setFocus();
QTest::keyPress(view.viewport(), 'x');
QTRY_COMPARE(widget->text(), hasWidget ? QString("x") : QString());
-
- if (!hasWidget)
- delete widget;
}
void tst_QGraphicsProxyWidget::keyReleaseEvent_data()
@@ -1174,19 +1022,18 @@ void tst_QGraphicsProxyWidget::keyReleaseEvent()
QGraphicsScene scene;
QGraphicsView view(&scene);
view.show();
- QApplication::setActiveWindow(&view);
QVERIFY(QTest::qWaitForWindowActive(&view));
QCOMPARE(QApplication::activeWindow(), (QWidget*)&view);
SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
proxy->setFlag(QGraphicsItem::ItemIsFocusable, true); // ### remove me!!!
- QPushButton *widget = new QPushButton;
- QSignalSpy spy(widget, SIGNAL(clicked()));
- widget->resize(50, 50);
+ std::unique_ptr<QPushButton> widgetGuard(new QPushButton);
+ QSignalSpy spy(widgetGuard.get(), SIGNAL(clicked()));
+ widgetGuard->resize(50, 50);
view.resize(100, 100);
if (hasWidget) {
- proxy->setWidget(widget);
+ proxy->setWidget(widgetGuard.release());
proxy->show();
}
proxy->setPos(50, 0);
@@ -1194,59 +1041,43 @@ void tst_QGraphicsProxyWidget::keyReleaseEvent()
proxy->setFocus();
QTest::keyPress(view.viewport(), Qt::Key_Space);
- QTRY_COMPARE(spy.count(), 0);
+ QTRY_COMPARE(spy.size(), 0);
QTest::keyRelease(view.viewport(), Qt::Key_Space);
- QTRY_COMPARE(spy.count(), (hasWidget) ? 1 : 0);
-
- if (!hasWidget)
- delete widget;
-}
-
-void tst_QGraphicsProxyWidget::mouseDoubleClickEvent_data()
-{
- QTest::addColumn<bool>("hasWidget");
- QTest::newRow("widget") << true;
- QTest::newRow("no widget") << false;
+ QTRY_COMPARE(spy.size(), hasWidget ? 1 : 0);
}
// protected void mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event)
void tst_QGraphicsProxyWidget::mouseDoubleClickEvent()
{
- QFETCH(bool, hasWidget);
-
QGraphicsScene scene;
QGraphicsView view(&scene);
- view.show();
-
- QApplication::setActiveWindow(&view);
- QVERIFY(QTest::qWaitForWindowActive(&view));
- QCOMPARE(QApplication::activeWindow(), (QWidget*)&view);
SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
proxy->setFlag(QGraphicsItem::ItemIsFocusable, true); // ### remove me!!!
QLineEdit *widget = new QLineEdit;
widget->setText("foo");
widget->resize(50, 50);
- view.resize(100, 100);
- if (hasWidget)
- proxy->setWidget(widget);
+ proxy->setWidget(widget);
+
proxy->setPos(50, 0);
QSignalSpy sceneChangedSpy(&scene, &QGraphicsScene::changed);
scene.addItem(proxy);
proxy->setFocus();
+ view.resize(100, 100);
+ view.show();
+
+ QVERIFY(QTest::qWaitForWindowActive(&view));
+ QCOMPARE(QApplication::activeWindow(), (QWidget*)&view);
// wait for scene to be updated before doing any coordinate mappings on it
- QTRY_VERIFY(sceneChangedSpy.count() > 0);
+ QTRY_VERIFY(sceneChangedSpy.size() > 0);
QPoint pointInLineEdit = view.mapFromScene(proxy->mapToScene(15, proxy->boundingRect().center().y()));
- QTest::mousePress(view.viewport(), Qt::LeftButton, 0, pointInLineEdit);
- QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0, pointInLineEdit);
- QTest::mouseDClick(view.viewport(), Qt::LeftButton, 0, pointInLineEdit);
+ QTest::mousePress(view.viewport(), Qt::LeftButton, {}, pointInLineEdit);
+ QTest::mouseRelease(view.viewport(), Qt::LeftButton, {}, pointInLineEdit);
+ QTest::mouseDClick(view.viewport(), Qt::LeftButton, {}, pointInLineEdit);
- QTRY_COMPARE(widget->selectedText(), hasWidget ? QString("foo") : QString());
-
- if (!hasWidget)
- delete widget;
+ QTRY_COMPARE(widget->selectedText(), QString("foo"));
}
void tst_QGraphicsProxyWidget::mousePressReleaseEvent_data()
@@ -1269,27 +1100,24 @@ void tst_QGraphicsProxyWidget::mousePressReleaseEvent()
SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
proxy->setFlag(QGraphicsItem::ItemIsFocusable, true); // ### remove me!!!
- QPushButton *widget = new QPushButton;
- QSignalSpy spy(widget, SIGNAL(clicked()));
- widget->resize(50, 50);
+ std::unique_ptr<QPushButton> widgetGuard(new QPushButton);
+ QSignalSpy spy(widgetGuard.get(), SIGNAL(clicked()));
+ widgetGuard->resize(50, 50);
if (hasWidget)
- proxy->setWidget(widget);
+ proxy->setWidget(widgetGuard.release());
proxy->setPos(50, 0);
QSignalSpy sceneChangedSpy(&scene, &QGraphicsScene::changed);
scene.addItem(proxy);
proxy->setFocus();
// wait for scene to be updated before doing any coordinate mappings on it
- QTRY_VERIFY(sceneChangedSpy.count() > 0);
+ QTRY_VERIFY(sceneChangedSpy.size() > 0);
QPoint buttonCenter = view.mapFromScene(proxy->mapToScene(proxy->boundingRect().center()));
- QTest::mousePress(view.viewport(), Qt::LeftButton, 0, buttonCenter);
- QTRY_COMPARE(spy.count(), 0);
- QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0, buttonCenter);
- QTRY_COMPARE(spy.count(), (hasWidget) ? 1 : 0);
-
- if (!hasWidget)
- delete widget;
+ QTest::mousePress(view.viewport(), Qt::LeftButton, {}, buttonCenter);
+ QTRY_COMPARE(spy.size(), 0);
+ QTest::mouseRelease(view.viewport(), Qt::LeftButton, {}, buttonCenter);
+ QTRY_COMPARE(spy.size(), hasWidget ? 1 : 0);
}
void tst_QGraphicsProxyWidget::resizeEvent_data()
@@ -1305,19 +1133,17 @@ void tst_QGraphicsProxyWidget::resizeEvent()
QFETCH(bool, hasWidget);
SubQGraphicsProxyWidget proxy;
- QWidget *widget = new QWidget;
+
if (hasWidget)
- proxy.setWidget(widget);
+ proxy.setWidget(new QWidget);
QSize newSize(100, 100);
QGraphicsSceneResizeEvent event;
event.setOldSize(QSize(10, 10));
event.setNewSize(newSize);
- proxy.call_resizeEvent(&event);
+ proxy.resizeEvent(&event);
if (hasWidget)
- QCOMPARE(widget->size(), newSize);
- if (!hasWidget)
- delete widget;
+ QCOMPARE(proxy.widget()->size(), newSize);
}
void tst_QGraphicsProxyWidget::paintEvent()
@@ -1326,7 +1152,6 @@ void tst_QGraphicsProxyWidget::paintEvent()
QGraphicsScene scene;
QGraphicsView view(&scene);
view.show();
- QApplication::setActiveWindow(&view);
QVERIFY(QTest::qWaitForWindowActive(&view));
QVERIFY(view.isActiveWindow());
@@ -1342,7 +1167,7 @@ void tst_QGraphicsProxyWidget::paintEvent()
QSignalSpy sceneChangedSpy(&scene, &QGraphicsScene::changed);
scene.addItem(&proxy);
- QTRY_VERIFY(sceneChangedSpy.count() > 0); // make sure the scene is ready
+ QTRY_VERIFY(sceneChangedSpy.size() > 0); // make sure the scene is ready
proxy.paintCount = 0;
w->update();
@@ -1376,48 +1201,13 @@ void tst_QGraphicsProxyWidget::wheelEvent()
}
#endif // QT_CONFIG(wheelevent)
-Q_DECLARE_METATYPE(Qt::SizeHint)
-void tst_QGraphicsProxyWidget::sizeHint_data()
-{
- QTest::addColumn<Qt::SizeHint>("which");
- QTest::addColumn<QSizeF>("constraint");
- QTest::addColumn<QSizeF>("sizeHint");
- QTest::addColumn<bool>("hasWidget");
-
- for (int i = 0; i < 2; ++i) {
- bool hasWidget = (i == 0);
- // ### What should these do?
- QTest::newRow("min") << Qt::MinimumSize << QSizeF() << QSizeF() << hasWidget;
- QTest::newRow("pre") << Qt::PreferredSize << QSizeF() << QSizeF() << hasWidget;
- QTest::newRow("max") << Qt::MaximumSize << QSizeF() << QSizeF() << hasWidget;
- QTest::newRow("mindes") << Qt::MinimumDescent << QSizeF() << QSizeF() << hasWidget;
- QTest::newRow("nsize") << Qt::NSizeHints << QSizeF() << QSizeF() << hasWidget;
- }
-}
-
-// protected QSizeF sizeHint(Qt::SizeHint which, QSizeF const& constraint = QSizeF()) const
-void tst_QGraphicsProxyWidget::sizeHint()
-{
- QFETCH(Qt::SizeHint, which);
- QFETCH(QSizeF, constraint);
- QFETCH(QSizeF, sizeHint);
- QFETCH(bool, hasWidget);
- QSKIP("Broken test");
- SubQGraphicsProxyWidget proxy;
- QWidget *widget = new QWidget;
- if (hasWidget)
- proxy.setWidget(widget);
- QCOMPARE(proxy.call_sizeHint(which, constraint), sizeHint);
- if (!hasWidget)
- delete widget;
-}
-
void tst_QGraphicsProxyWidget::sizePolicy()
{
for (int p = 0; p < 2; ++p) {
bool hasWidget = (p == 0);
- SubQGraphicsProxyWidget proxy;
- QWidget *widget = new QWidget;
+ QGraphicsProxyWidget proxy;
+ std::unique_ptr<QWidget> widgetGuard(new QWidget);
+ QWidget *widget = widgetGuard.get();
QSizePolicy proxyPol(QSizePolicy::Maximum, QSizePolicy::Expanding);
proxy.setSizePolicy(proxyPol);
QSizePolicy widgetPol(QSizePolicy::Fixed, QSizePolicy::Minimum);
@@ -1426,7 +1216,7 @@ void tst_QGraphicsProxyWidget::sizePolicy()
QCOMPARE(proxy.sizePolicy(), proxyPol);
QCOMPARE(widget->sizePolicy(), widgetPol);
if (hasWidget) {
- proxy.setWidget(widget);
+ proxy.setWidget(widgetGuard.release());
QCOMPARE(proxy.sizePolicy(), widgetPol);
} else {
QCOMPARE(proxy.sizePolicy(), proxyPol);
@@ -1439,42 +1229,39 @@ void tst_QGraphicsProxyWidget::sizePolicy()
QCOMPARE(proxy.sizePolicy(), proxyPol);
else
QCOMPARE(proxy.sizePolicy(), widgetPol);
-
- if (!hasWidget)
- delete widget;
}
}
void tst_QGraphicsProxyWidget::minimumSize()
{
- SubQGraphicsProxyWidget proxy;
- QWidget *widget = new QWidget;
+ QGraphicsProxyWidget proxy;
+ std::unique_ptr<QWidget> widgetGuard(new QWidget);
QSize minSize(50, 50);
- widget->setMinimumSize(minSize);
+ widgetGuard->setMinimumSize(minSize);
proxy.resize(30, 30);
- widget->resize(30,30);
+ widgetGuard->resize(30,30);
QCOMPARE(proxy.size(), QSizeF(30, 30));
- proxy.setWidget(widget);
+ proxy.setWidget(widgetGuard.release());
QCOMPARE(proxy.size().toSize(), minSize);
QCOMPARE(proxy.minimumSize().toSize(), minSize);
- widget->setMinimumSize(70, 70);
+ proxy.widget()->setMinimumSize(70, 70);
QCOMPARE(proxy.minimumSize(), QSizeF(70, 70));
QCOMPARE(proxy.size(), QSizeF(70, 70));
}
void tst_QGraphicsProxyWidget::maximumSize()
{
- SubQGraphicsProxyWidget proxy;
- QWidget *widget = new QWidget;
+ QGraphicsProxyWidget proxy;
+ std::unique_ptr<QWidget> widgetGuard(new QWidget);
QSize maxSize(150, 150);
- widget->setMaximumSize(maxSize);
+ widgetGuard->setMaximumSize(maxSize);
proxy.resize(200, 200);
- widget->resize(200,200);
+ widgetGuard->resize(200,200);
QCOMPARE(proxy.size(), QSizeF(200, 200));
- proxy.setWidget(widget);
+ proxy.setWidget(widgetGuard.release());
QCOMPARE(proxy.size().toSize(), maxSize);
QCOMPARE(proxy.maximumSize().toSize(), maxSize);
- widget->setMaximumSize(70, 70);
+ proxy.widget()->setMaximumSize(70, 70);
QCOMPARE(proxy.maximumSize(), QSizeF(70, 70));
QCOMPARE(proxy.size(), QSizeF(70, 70));
}
@@ -1488,7 +1275,7 @@ public:
QRegion paintEventRegion;
int npaints;
protected:
- void paintEvent(QPaintEvent *event)
+ void paintEvent(QPaintEvent *event) override
{
++npaints;
paintEventRegion += event->region();
@@ -1515,7 +1302,7 @@ public slots:
}
protected:
- void paintEvent(QPaintEvent *event)
+ void paintEvent(QPaintEvent *event) override
{
++npaints;
paintEventRegion += event->region();
@@ -1535,6 +1322,9 @@ static QList<QRect> rects(const QRegion &region)
void tst_QGraphicsProxyWidget::scrollUpdate()
{
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
+ QSKIP("QWindow::requestActivate() is not supported.");
+
ScrollWidget *widget = new ScrollWidget;
QGraphicsScene scene;
@@ -1544,7 +1334,7 @@ void tst_QGraphicsProxyWidget::scrollUpdate()
view.show();
QVERIFY(QTest::qWaitForWindowActive(&view));
QTRY_VERIFY(view.npaints >= 1);
- QTest::qWait(20);
+ QTest::qWait(150);
widget->paintEventRegion = QRegion();
widget->npaints = 0;
view.paintEventRegion = QRegion();
@@ -1748,7 +1538,6 @@ void tst_QGraphicsProxyWidget::tabFocus_simpleWidget()
window.setLayout(layout);
window.show();
- QApplication::setActiveWindow(&window);
window.activateWindow();
QVERIFY(QTest::qWaitForWindowActive(&window));
@@ -1832,7 +1621,6 @@ void tst_QGraphicsProxyWidget::tabFocus_simpleTwoWidgets()
window.setLayout(layout);
window.show();
- QApplication::setActiveWindow(&window);
window.activateWindow();
QVERIFY(QTest::qWaitForWindowActive(&window));
@@ -1965,7 +1753,6 @@ void tst_QGraphicsProxyWidget::tabFocus_complexWidget()
window.setLayout(layout);
window.show();
- QApplication::setActiveWindow(&window);
window.activateWindow();
QVERIFY(QTest::qWaitForWindowActive(&window));
@@ -2102,7 +1889,6 @@ void tst_QGraphicsProxyWidget::tabFocus_complexTwoWidgets()
window.setLayout(layout);
window.show();
- QApplication::setActiveWindow(&window);
window.activateWindow();
QVERIFY(QTest::qWaitForWindowActive(&window));
@@ -2276,7 +2062,7 @@ void tst_QGraphicsProxyWidget::setFocus_simpleWidget()
window.setLayout(layout);
window.show();
- QApplication::setActiveWindow(&window);
+ QApplicationPrivate::setActiveWindow(&window);
window.activateWindow();
QVERIFY(QTest::qWaitForWindowActive(&window));
QCOMPARE(QApplication::activeWindow(), &window);
@@ -2348,7 +2134,6 @@ void tst_QGraphicsProxyWidget::setFocus_simpleTwoWidgets()
window.setLayout(layout);
window.show();
- QApplication::setActiveWindow(&window);
window.activateWindow();
QVERIFY(QTest::qWaitForWindowActive(&window));
QCOMPARE(QApplication::activeWindow(), &window);
@@ -2427,7 +2212,6 @@ void tst_QGraphicsProxyWidget::setFocus_complexTwoWidgets()
window.setLayout(layout);
window.show();
- QApplication::setActiveWindow(&window);
window.activateWindow();
QVERIFY(QTest::qWaitForWindowActive(&window));
QCOMPARE(QApplication::activeWindow(), &window);
@@ -2500,28 +2284,29 @@ void tst_QGraphicsProxyWidget::setFocus_complexTwoWidgets()
void tst_QGraphicsProxyWidget::popup_basic()
{
- QScopedPointer<QComboBox> box(new QComboBox);
+ std::unique_ptr<QComboBox> boxGuard(new QComboBox);
QStyleOptionComboBox opt;
- opt.initFrom(box.data());
- opt.editable = box->isEditable();
- if (box->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt))
+ opt.initFrom(boxGuard.get());
+ opt.editable = boxGuard->isEditable();
+ if (boxGuard->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt))
QSKIP("Does not work due to SH_Combobox_Popup");
// ProxyWidget should automatically create proxy's when the widget creates a child
- QGraphicsScene *scene = new QGraphicsScene;
- QGraphicsView view(scene);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
view.setAlignment(Qt::AlignLeft | Qt::AlignTop);
view.setGeometry(0, 100, 480, 500);
view.show();
- SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
+ QComboBox *box = boxGuard.get();
+ QGraphicsProxyWidget *proxy = new QGraphicsProxyWidget;
box->setGeometry(0, 0, 320, 40);
box->addItems(QStringList() << "monday" << "tuesday" << "wednesday"
<< "thursday" << "saturday" << "sunday");
- QCOMPARE(proxy->childItems().count(), 0);
- proxy->setWidget(box.data());
+ QCOMPARE(proxy->childItems().size(), 0);
+ proxy->setWidget(boxGuard.release());
proxy->show();
- scene->addItem(proxy);
+ scene.addItem(proxy);
QCOMPARE(box->pos(), QPoint());
QCOMPARE(proxy->pos(), QPointF());
@@ -2530,16 +2315,16 @@ void tst_QGraphicsProxyWidget::popup_basic()
QTest::qWait(125);
QApplication::processEvents();
- QTest::mousePress(view.viewport(), Qt::LeftButton, 0,
+ QTest::mousePress(view.viewport(), Qt::LeftButton, {},
view.mapFromScene(proxy->mapToScene(proxy->boundingRect().center())));
QTRY_COMPARE(box->pos(), QPoint());
- QCOMPARE(proxy->childItems().count(), 1);
+ QCOMPARE(proxy->childItems().size(), 1);
QGraphicsProxyWidget *child = (QGraphicsProxyWidget*)(proxy->childItems())[0];
QVERIFY(child->isWidget());
QVERIFY(child->widget());
- QCOMPARE(child->widget()->parent(), static_cast<QObject*>(box.data()));
+ QCOMPARE(child->widget()->parent(), box);
QTRY_COMPARE(proxy->pos(), QPointF(box->pos()));
QCOMPARE(child->x(), qreal(box->x()));
@@ -2610,12 +2395,12 @@ void tst_QGraphicsProxyWidget::changingCursor_basic()
view.show();
QVERIFY(QTest::qWaitForWindowActive(&view));
- SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
+ QGraphicsProxyWidget *proxy = new QGraphicsProxyWidget;
QLineEdit *widget = new QLineEdit;
proxy->setWidget(widget);
QSignalSpy sceneChangedSpy(&scene, &QGraphicsScene::changed);
scene.addItem(proxy);
- QTRY_VERIFY(sceneChangedSpy.count() > 0); // make sure the scene is ready
+ QTRY_VERIFY(sceneChangedSpy.size() > 0); // make sure the scene is ready
// in
QTest::mouseMove(view.viewport(), view.mapFromScene(proxy->mapToScene(proxy->boundingRect().center())));
@@ -2671,7 +2456,7 @@ void tst_QGraphicsProxyWidget::tooltip_basic()
QGraphicsView view(&scene);
view.setFixedSize(200, 200);
view.show();
- QApplication::setActiveWindow(&view);
+ QApplicationPrivate::setActiveWindow(&view);
QVERIFY(QTest::qWaitForWindowActive(&view));
{
QHelpEvent helpEvent(QEvent::ToolTip, view.viewport()->rect().topLeft(),
@@ -2681,7 +2466,8 @@ void tst_QGraphicsProxyWidget::tooltip_basic()
bool foundView = false;
bool foundTipLabel = false;
- foreach (QWidget *widget, QApplication::topLevelWidgets()) {
+ const auto widgets = QApplication::topLevelWidgets();
+ for (QWidget *widget : widgets) {
if (widget == &view)
foundView = true;
if (widget->inherits("QTipLabel"))
@@ -2733,56 +2519,46 @@ void tst_QGraphicsProxyWidget::childPos()
QGraphicsScene scene;
- QComboBox *box = new QComboBox;
- box->addItem("Item 1");
- box->addItem("Item 2");
- box->addItem("Item 3");
- box->addItem("Item 4");
+ QComboBox box;
+ box.addItem("Item 1");
+ box.addItem("Item 2");
+ box.addItem("Item 3");
+ box.addItem("Item 4");
if (moveCombo)
- box->move(comboPos);
+ box.move(comboPos);
- QGraphicsProxyWidget *proxy = scene.addWidget(box);
+ QGraphicsProxyWidget *proxy = scene.addWidget(&box);
proxy->show();
QVERIFY(proxy->isVisible());
- QVERIFY(box->isVisible());
+ QVERIFY(box.isVisible());
if (!moveCombo)
proxy->setPos(proxyPos);
QCOMPARE(proxy->pos(), proxyPos);
- QCOMPARE(box->pos(), comboPos);
+ QCOMPARE(box.pos(), comboPos);
for (int i = 0; i < 2; ++i) {
- box->showPopup();
- QApplication::processEvents();
- QApplication::processEvents();
-
- QWidget *menu = nullptr;
- foreach (QObject *child, box->children()) {
- if ((menu = qobject_cast<QWidget *>(child)))
- break;
- }
+ box.showPopup();
+ QWidget *menu = box.findChild<QWidget *>();
QVERIFY(menu);
- QVERIFY(menu->isVisible());
+ QTRY_VERIFY(menu->isVisible());
QVERIFY(menu->testAttribute(Qt::WA_DontShowOnScreen));
QCOMPARE(proxy->childItems().size(), 1);
- QGraphicsProxyWidget *proxyChild = 0;
- foreach (QGraphicsItem *child, proxy->childItems()) {
- if (child->isWidget() && (proxyChild = qobject_cast<QGraphicsProxyWidget *>(static_cast<QGraphicsWidget *>(child))))
- break;
- }
+ QGraphicsProxyWidget *proxyChild = qobject_cast<QGraphicsProxyWidget *>(
+ static_cast<QGraphicsWidget *>(proxy->childItems().first()));
QVERIFY(proxyChild);
QVERIFY(proxyChild->isVisible());
qreal expectedXPosition = 0.0;
-#if defined(Q_OS_MAC) && !defined(QT_NO_STYLE_MAC)
+
// The Mac style wants the popup to show up at QPoint(4 - 11, 1).
// See QMacStyle::subControlRect SC_ComboBoxListBoxPopup.
if (QApplication::style()->inherits("QMacStyle"))
expectedXPosition = qreal(4 - 11);
-#endif
- QCOMPARE(proxyChild->pos().x(), expectedXPosition);
+
+ QTRY_COMPARE(proxyChild->pos().x(), expectedXPosition);
menu->hide();
}
}
@@ -2818,7 +2594,7 @@ void tst_QGraphicsProxyWidget::windowOpacity()
QGraphicsProxyWidget *proxy = scene.addWidget(widget);
proxy->setCacheMode(QGraphicsItem::ItemCoordinateCache);
- QApplication::setActiveWindow(&view);
+ QApplicationPrivate::setActiveWindow(&view);
view.show();
QVERIFY(QTest::qWaitForWindowActive(&view));
QVERIFY(view.isActiveWindow());
@@ -2830,18 +2606,20 @@ void tst_QGraphicsProxyWidget::windowOpacity()
QVERIFY(widget->isVisible());
widget->setWindowOpacity(0.5);
- QApplication::processEvents();
// Make sure setWindowOpacity triggers an update on the scene,
// and not on the widget or the proxy itself. The entire proxy needs an update
// in case it has a window decoration. Update: QGraphicsItem::CacheMode is
// disabled on platforms without alpha channel support in QPixmap (e.g.,
- // X11 without XRender).
+ // X11 without XRender). On macOS, we always get a paint event.
int paints = 0;
+#ifdef Q_OS_MACOS
+ paints = 1;
+#endif
QTRY_COMPARE(eventSpy.counts[QEvent::UpdateRequest], 0);
QTRY_COMPARE(eventSpy.counts[QEvent::Paint], paints);
- QCOMPARE(signalSpy.count(), 1);
+ QTRY_COMPARE(signalSpy.size(), 1);
const QList<QVariant> arguments = signalSpy.takeFirst();
const QList<QRectF> updateRects = qvariant_cast<QList<QRectF> >(arguments.at(0));
QCOMPARE(updateRects.size(), 1);
@@ -2922,6 +2700,8 @@ void tst_QGraphicsProxyWidget::palettePropagation()
QCOMPARE(editSpy.counts[QEvent::PaletteChange], 3);
QCOMPARE(proxySpy.counts[QEvent::PaletteChange], 1);
QVERIFY(!edit->testAttribute(Qt::WA_SetPalette));
+ if (edit->palette() != palette)
+ QEXPECT_FAIL("", "Test case fails unless run alone", Abort);
QCOMPARE(edit->palette(), palette);
QCOMPARE(edit->palette(), proxy.palette());
QCOMPARE(edit->palette().color(QPalette::Text), QColor(Qt::red));
@@ -3112,12 +2892,12 @@ void tst_QGraphicsProxyWidget::createProxyForChildWidget()
QSignalSpy spy(checkbox, SIGNAL(clicked()));
- QTest::mousePress(view.viewport(), Qt::LeftButton, 0,
+ QTest::mousePress(view.viewport(), Qt::LeftButton, {},
view.mapFromScene(checkboxProxy->mapToScene(QPointF(8,8))));
- QTRY_COMPARE(spy.count(), 0);
- QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0,
+ QTRY_COMPARE(spy.size(), 0);
+ QTest::mouseRelease(view.viewport(), Qt::LeftButton, {},
view.mapFromScene(checkboxProxy->mapToScene(QPointF(8,8))));
- QTRY_COMPARE(spy.count(), 1);
+ QTRY_COMPARE(spy.size(), 1);
@@ -3145,7 +2925,7 @@ public:
bool embeddedPopup;
bool gotContextMenuEvent;
protected:
- bool event(QEvent *event)
+ bool event(QEvent *event) override
{
if (event->type() == QEvent::ContextMenu) {
if (!m_timer) {
@@ -3157,7 +2937,7 @@ protected:
}
return QWidget::event(event);
}
- void contextMenuEvent(QContextMenuEvent *)
+ void contextMenuEvent(QContextMenuEvent *) override
{
gotContextMenuEvent = true;
}
@@ -3212,7 +2992,7 @@ void tst_QGraphicsProxyWidget::actionsContextMenu()
view.resize(200, 200);
view.move(QGuiApplication::primaryScreen()->geometry().center() - QPoint(100, 100));
view.show();
- QApplication::setActiveWindow(&view);
+ QApplicationPrivate::setActiveWindow(&view);
QVERIFY(QTest::qWaitForWindowActive(&view));
view.setFocus();
QTRY_VERIFY(view.hasFocus());
@@ -3282,9 +3062,13 @@ void tst_QGraphicsProxyWidget::bypassGraphicsProxyWidget_data()
void tst_QGraphicsProxyWidget::bypassGraphicsProxyWidget()
{
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
+ QSKIP("QWindow::requestActivate() is not supported.");
+
QFETCH(bool, bypass);
- QWidget *widget = new QWidget;
+ std::unique_ptr<QWidget> widgetGuard(new QWidget);
+ QWidget *widget = widgetGuard.get();
widget->resize(100, 100);
QGraphicsScene scene;
@@ -3292,7 +3076,7 @@ void tst_QGraphicsProxyWidget::bypassGraphicsProxyWidget()
view.show();
QVERIFY(QTest::qWaitForWindowActive(&view));
- QGraphicsProxyWidget *proxy = scene.addWidget(widget);
+ QGraphicsProxyWidget *proxy = scene.addWidget(widgetGuard.release());
QCOMPARE(proxy->widget(), widget);
QVERIFY(proxy->childItems().isEmpty());
@@ -3312,8 +3096,6 @@ void tst_QGraphicsProxyWidget::bypassGraphicsProxyWidget()
dialog->hide();
QApplication::processEvents();
- delete dialog;
- delete widget;
}
static void makeDndEvent(QGraphicsSceneDragDropEvent *event, QGraphicsView *view, const QPointF &pos)
@@ -3321,7 +3103,7 @@ static void makeDndEvent(QGraphicsSceneDragDropEvent *event, QGraphicsView *view
event->setScenePos(pos);
event->setScreenPos(view->mapToGlobal(view->mapFromScene(pos)));
event->setButtons(Qt::LeftButton);
- event->setModifiers(0);
+ event->setModifiers({});
event->setPossibleActions(Qt::CopyAction);
event->setProposedAction(Qt::CopyAction);
event->setDropAction(Qt::CopyAction);
@@ -3483,7 +3265,7 @@ void tst_QGraphicsProxyWidget::updateAndDelete()
class InputMethod_LineEdit : public QLineEdit
{
- bool event(QEvent *e)
+ bool event(QEvent *e) override
{
if (e->type() == QEvent::InputMethod)
++inputMethodEvents;
@@ -3495,6 +3277,9 @@ public:
void tst_QGraphicsProxyWidget::inputMethod()
{
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
+ QSKIP("QWindow::requestActivate() is not supported.");
+
QGraphicsScene scene;
// check that the proxy is initialized with the correct input method sensitivity
@@ -3554,7 +3339,6 @@ void tst_QGraphicsProxyWidget::clickFocus()
view.setFrameStyle(0);
view.resize(300, 300);
view.show();
- QApplication::setActiveWindow(&view);
QVERIFY(QTest::qWaitForWindowActive(&view));
QVERIFY(!proxy->hasFocus());
@@ -3568,7 +3352,7 @@ void tst_QGraphicsProxyWidget::clickFocus()
QPointF lineEditCenter = proxy->mapToScene(proxy->boundingRect().center());
// Spontaneous mouse click sets focus on a clickable widget.
for (int retry = 0; retry < 50 && !proxy->hasFocus(); retry++)
- QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(lineEditCenter));
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, {}, view.mapFromScene(lineEditCenter));
QVERIFY(proxy->hasFocus());
QVERIFY(proxy->widget()->hasFocus());
QCOMPARE(proxySpy.counts[QEvent::FocusIn], 1);
@@ -3626,7 +3410,7 @@ void tst_QGraphicsProxyWidget::clickFocus()
// Spontaneous click on non-clickable widget does not give focus.
proxy->widget()->setFocusPolicy(Qt::NoFocus);
- QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(lineEditCenter));
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, {}, view.mapFromScene(lineEditCenter));
QVERIFY(!proxy->hasFocus());
QVERIFY(!proxy->widget()->hasFocus());
@@ -3635,8 +3419,8 @@ void tst_QGraphicsProxyWidget::clickFocus()
scene.setFocusItem(0);
QVERIFY(!proxy->hasFocus());
QVERIFY(!proxy->widget()->hasFocus());
- QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(lineEditCenter));
- QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(lineEditCenter));
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, {}, view.mapFromScene(lineEditCenter));
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, {}, view.mapFromScene(lineEditCenter));
QVERIFY(proxy->hasFocus());
QVERIFY(proxy->widget()->hasFocus());
QCOMPARE(widgetSpy.counts[QEvent::FocusIn], 1);
@@ -3647,7 +3431,7 @@ void tst_QGraphicsProxyWidget::clickFocus()
void tst_QGraphicsProxyWidget::windowFrameMargins()
{
// Make sure the top margin is non-zero when passing Qt::Window.
- QGraphicsProxyWidget *proxy = new QGraphicsProxyWidget(0, Qt::Window);
+ QGraphicsProxyWidget *proxy = new QGraphicsProxyWidget(nullptr, Qt::Window);
qreal left, top, right, bottom;
proxy->getWindowFrameMargins(&left, &top, &right, &bottom);
@@ -3667,67 +3451,50 @@ void tst_QGraphicsProxyWidget::windowFrameMargins()
QVERIFY(top > 0);
}
-class HoverButton : public QPushButton
+void tst_QGraphicsProxyWidget::QTBUG_6986_sendMouseEventToAlienWidget()
{
-public:
- HoverButton(QWidget *parent = nullptr) : QPushButton(parent), hoverLeaveReceived(false)
- {}
-
- bool hoverLeaveReceived;
-
- bool event(QEvent* e)
+ struct HoverButton : public QPushButton
{
- if(QEvent::HoverLeave == e->type())
- hoverLeaveReceived = true;
- return QPushButton::event(e);
- }
-};
+ using QPushButton::QPushButton;
+ bool hoverLeaveReceived = false;
-class Scene : public QGraphicsScene
-{
-Q_OBJECT
-public:
- Scene() {
- QWidget *background = new QWidget;
- background->setGeometry(0, 0, 500, 500);
- hoverButton = new HoverButton;
- hoverButton->setParent(background);
- hoverButton->setText("Second button");
- hoverButton->setGeometry(10, 10, 200, 50);
- addWidget(background);
-
- QPushButton *hideButton = new QPushButton("I'm a button with a very very long text");
- hideButton->setGeometry(10, 10, 400, 50);
- topButton = addWidget(hideButton);
- connect(hideButton, &QPushButton::clicked, this, [&]() { topButton->hide(); });
- topButton->setFocus();
- }
-
- QGraphicsProxyWidget *topButton;
- HoverButton *hoverButton;
-};
+ bool event(QEvent* e) override
+ {
+ if (QEvent::HoverLeave == e->type())
+ hoverLeaveReceived = true;
+ return QPushButton::event(e);
+ }
+ };
-void tst_QGraphicsProxyWidget::QTBUG_6986_sendMouseEventToAlienWidget()
-{
- if (QGuiApplication::platformName() == QLatin1String("cocoa")) {
- // The "Second button" does not receive QEvent::HoverLeave
- QSKIP("This test fails only on Cocoa. Investigate why. See QTBUG-69219");
- }
+ QGraphicsScene scene;
+ QWidget *background = new QWidget;
+ background->setGeometry(0, 0, 500, 500);
+ HoverButton *hoverButton = new HoverButton(background);
+ hoverButton->setText("Second button");
+ hoverButton->setGeometry(10, 10, 200, 50);
+ scene.addWidget(background);
+
+ QPushButton *hideButton = new QPushButton("I'm a button with a very very long text");
+ hideButton->setGeometry(10, 10, 400, 50);
+ QGraphicsProxyWidget *topButton = scene.addWidget(hideButton);
+ connect(hideButton, &QPushButton::clicked, &scene, [&]() { topButton->hide(); });
+ topButton->setFocus();
- QGraphicsView view;
- Scene scene;
- view.setScene(&scene);
+ QGraphicsView view(&scene);
view.resize(600, 600);
- QApplication::setActiveWindow(&view);
view.show();
QVERIFY(QTest::qWaitForWindowActive(&view));
- QPoint topButtonTopLeftCorner = view.mapFromScene(scene.topButton->scenePos());
- QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, topButtonTopLeftCorner);
+ QPoint topButtonTopLeftCorner = view.mapFromScene(topButton->scenePos());
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, {}, topButtonTopLeftCorner);
// move to the bottom right corner (buttons are placed in the top left corner)
- QCOMPARE(scene.hoverButton->hoverLeaveReceived, false);
+ QCOMPARE(hoverButton->hoverLeaveReceived, false);
QTest::mouseMove(view.viewport(), view.viewport()->rect().bottomRight());
- QTRY_COMPARE(scene.hoverButton->hoverLeaveReceived, true);
+ if (QGuiApplication::platformName() == QLatin1String("cocoa")) {
+ // The "Second button" does not receive QEvent::HoverLeave
+ QEXPECT_FAIL("", "This test fails only on Cocoa. Investigate why. See QTBUG-69219", Continue);
+ }
+ QTRY_COMPARE(hoverButton->hoverLeaveReceived, true);
}
static QByteArray msgPointMismatch(const QPoint &actual, const QPoint &expected)
@@ -3758,7 +3525,6 @@ void tst_QGraphicsProxyWidget::mapToGlobal() // QTBUG-41135
childWidget->resize(embeddedWidget->size() / 2);
childWidget->move(embeddedWidget->width() / 4, embeddedWidget->height() / 4); // center in embeddedWidget
scene.addWidget(embeddedWidget);
- QApplication::setActiveWindow(&view);
view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
const QPoint embeddedCenter = embeddedWidget->rect().center();
@@ -3766,8 +3532,9 @@ void tst_QGraphicsProxyWidget::mapToGlobal() // QTBUG-41135
QCOMPARE(embeddedWidget->mapFromGlobal(embeddedCenterGlobal), embeddedCenter);
// This should be equivalent to the view center give or take rounding
// errors due to odd window margins
+ const int Tolerance = qCeil(4 * view.devicePixelRatio());
const QPoint viewCenter = view.geometry().center();
- QVERIFY2((viewCenter - embeddedCenterGlobal).manhattanLength() <= 3,
+ QVERIFY2((viewCenter - embeddedCenterGlobal).manhattanLength() <= Tolerance,
msgPointMismatch(embeddedCenterGlobal, viewCenter).constData());
// Same test with child centered on embeddedWidget. Also make sure
@@ -3777,7 +3544,7 @@ void tst_QGraphicsProxyWidget::mapToGlobal() // QTBUG-41135
const QPoint childCenter = childWidget->rect().center();
const QPoint childCenterGlobal = childWidget->mapToGlobal(childCenter);
QCOMPARE(childWidget->mapFromGlobal(childCenterGlobal), childCenter);
- QVERIFY2((viewCenter - childCenterGlobal).manhattanLength() <= 4,
+ QVERIFY2((viewCenter - childCenterGlobal).manhattanLength() <= Tolerance,
msgPointMismatch(childCenterGlobal, viewCenter).constData());
}
@@ -3832,7 +3599,7 @@ class TouchWidget : public QWidget
public:
TouchWidget(QWidget *parent = nullptr) : QWidget(parent) {}
- bool event(QEvent *event)
+ bool event(QEvent *event) override
{
switch (event->type()) {
case QEvent::TouchBegin:
@@ -3840,7 +3607,6 @@ public:
case QEvent::TouchEnd:
event->accept();
return true;
- break;
default:
break;
}
@@ -3849,48 +3615,416 @@ public:
}
};
+#if QT_CONFIG(wheelevent)
+/*!
+ QGraphicsProxyWidget receives wheel events from QGraphicsScene, and then
+ generates a new event that is sent spontaneously in order to enable event
+ propagation. This requires extra handling of the wheel grabbing we do for
+ high-precision wheel event streams.
+
+ Test that this doesn't trigger infinite recursion, while still resulting in
+ event propagation within the embedded widget hierarchy, and back to the
+ QGraphicsView if the event is not accepted.
+
+ See tst_QApplication::wheelEventPropagation for a similar test.
+*/
+void tst_QGraphicsProxyWidget::wheelEventPropagation()
+{
+ QGraphicsScene scene(0, 0, 600, 600);
+
+ QWidget *label = new QLabel("Direct");
+ label->setFixedSize(300, 30);
+ QGraphicsProxyWidget *labelProxy = scene.addWidget(label);
+ labelProxy->setPos(0, 50);
+ labelProxy->show();
+
+ class NestedWidget : public QWidget
+ {
+ public:
+ NestedWidget(const QString &text)
+ {
+ setObjectName("Nested Label");
+ QLabel *nested = new QLabel(text);
+ QHBoxLayout *hbox = new QHBoxLayout;
+ hbox->addWidget(nested);
+ setLayout(hbox);
+ }
+
+ int wheelEventCount = 0;
+ protected:
+ void wheelEvent(QWheelEvent *) override
+ {
+ ++wheelEventCount;
+ }
+ };
+ NestedWidget *nestedWidget = new NestedWidget("Nested");
+ nestedWidget->setFixedSize(300, 60);
+ QGraphicsProxyWidget *nestedProxy = scene.addWidget(nestedWidget);
+ nestedProxy->setPos(0, 120);
+ nestedProxy->show();
+
+ QGraphicsView view(&scene);
+ view.setFixedHeight(200);
+ view.show();
+
+ QVERIFY(QTest::qWaitForWindowActive(&view));
+ QVERIFY(view.verticalScrollBar()->isVisible());
+
+ view.verticalScrollBar()->setValue(0);
+ QSignalSpy scrollSpy(view.verticalScrollBar(), &QScrollBar::valueChanged);
+
+ const QPoint wheelPosition(50, 25);
+ auto wheelUp = [&view, wheelPosition](Qt::ScrollPhase phase) {
+ const QPoint global = view.mapToGlobal(wheelPosition);
+ const QPoint pixelDelta(0, -25);
+ const QPoint angleDelta(0, -120);
+ QWindowSystemInterface::handleWheelEvent(view.windowHandle(), wheelPosition, global,
+ pixelDelta, angleDelta, Qt::NoModifier,
+ phase);
+ QCoreApplication::processEvents();
+ };
+
+ int scrollCount = 0;
+ // test non-kinetic events; they are not grabbed, and should scroll the view unless
+ // accepted by the embedded widget
+ QCOMPARE(view.itemAt(wheelPosition), nullptr);
+ wheelUp(Qt::NoScrollPhase);
+ QCOMPARE(scrollSpy.size(), ++scrollCount);
+
+ // wheeling on the label, which ignores the event, should scroll the view
+ QCOMPARE(view.itemAt(wheelPosition), labelProxy);
+ wheelUp(Qt::NoScrollPhase);
+ QCOMPARE(scrollSpy.size(), ++scrollCount);
+ QCOMPARE(view.itemAt(wheelPosition), labelProxy);
+ wheelUp(Qt::NoScrollPhase);
+ QCOMPARE(scrollSpy.size(), ++scrollCount);
+
+ // left the widget
+ QCOMPARE(view.itemAt(wheelPosition), nullptr);
+ wheelUp(Qt::NoScrollPhase);
+ QCOMPARE(scrollSpy.size(), ++scrollCount);
+
+ // reached the nested widget, which accepts the wheel event, so no more scrolling
+ QCOMPARE(view.itemAt(wheelPosition), nestedProxy);
+ // remember this position for later
+ const int scrollBarValueOnNestedProxy = view.verticalScrollBar()->value();
+ wheelUp(Qt::NoScrollPhase);
+ QCOMPARE(scrollSpy.size(), scrollCount);
+ QCOMPARE(nestedWidget->wheelEventCount, 1);
+
+ // reset, try with kinetic events
+ view.verticalScrollBar()->setValue(0);
+ ++scrollCount;
+
+ // starting a scroll outside any widget and scrolling through the widgets should work,
+ // no matter if the widget accepts wheel events - the view has the grab
+ QCOMPARE(view.itemAt(wheelPosition), nullptr);
+ wheelUp(Qt::ScrollBegin);
+ QCOMPARE(scrollSpy.size(), ++scrollCount);
+ for (int i = 0; i < 5; ++i) {
+ wheelUp(Qt::ScrollUpdate);
+ QCOMPARE(scrollSpy.size(), ++scrollCount);
+ }
+ wheelUp(Qt::ScrollEnd);
+ QCOMPARE(scrollSpy.size(), ++scrollCount);
+
+ // reset
+ view.verticalScrollBar()->setValue(0);
+ scrollCount = scrollSpy.size();
+
+ // starting a scroll on a widget that doesn't accept wheel events
+ // should also scroll the view, which still gets the grab
+ wheelUp(Qt::NoScrollPhase);
+ scrollCount = scrollSpy.size();
+
+ QCOMPARE(view.itemAt(wheelPosition), labelProxy);
+ wheelUp(Qt::ScrollBegin);
+ QCOMPARE(scrollSpy.size(), ++scrollCount);
+ for (int i = 0; i < 5; ++i) {
+ wheelUp(Qt::ScrollUpdate);
+ QCOMPARE(scrollSpy.size(), ++scrollCount);
+ }
+ wheelUp(Qt::ScrollEnd);
+ QCOMPARE(scrollSpy.size(), ++scrollCount);
+
+ // starting a scroll on a widget that does accept wheel events
+ // should not scroll the view
+ view.verticalScrollBar()->setValue(scrollBarValueOnNestedProxy);
+ scrollCount = scrollSpy.size();
+
+ QCOMPARE(view.itemAt(wheelPosition), nestedProxy);
+ wheelUp(Qt::ScrollBegin);
+ QCOMPARE(scrollSpy.size(), scrollCount);
+}
+#endif // QT_CONFIG(wheelevent)
+
// QTBUG_45737
void tst_QGraphicsProxyWidget::forwardTouchEvent()
{
- QGraphicsScene *scene = new QGraphicsScene;
+ QGraphicsScene scene;
TouchWidget *widget = new TouchWidget;
-
widget->setAttribute(Qt::WA_AcceptTouchEvents);
- QGraphicsProxyWidget *proxy = new QGraphicsProxyWidget;
-
+ QGraphicsProxyWidget *proxy = scene.addWidget(widget);
proxy->setAcceptTouchEvents(true);
- proxy->setWidget(widget);
-
- scene->addItem(proxy);
- QGraphicsView *view = new QGraphicsView(scene);
-
- view->show();
+ QGraphicsView view(&scene);
+ view.show();
+ QVERIFY(QTest::qWaitForWindowActive(&view));
EventSpy eventSpy(widget);
QPointingDevice *device = QTest::createTouchDevice();
+ QVERIFY(device);
QCOMPARE(eventSpy.counts[QEvent::TouchBegin], 0);
QCOMPARE(eventSpy.counts[QEvent::TouchUpdate], 0);
QCOMPARE(eventSpy.counts[QEvent::TouchEnd], 0);
- QTest::touchEvent(view, device).press(0, QPoint(10, 10), view);
- QTest::touchEvent(view, device).move(0, QPoint(15, 15), view);
- QTest::touchEvent(view, device).move(0, QPoint(16, 16), view);
- QTest::touchEvent(view, device).release(0, QPoint(15, 15), view);
+ QTest::touchEvent(&view, device).press(0, QPoint(10, 10), &view);
+ QTest::touchEvent(&view, device).move(0, QPoint(15, 15), &view);
+ QTest::touchEvent(&view, device).move(0, QPoint(16, 16), &view);
+ QTest::touchEvent(&view, device).release(0, QPoint(15, 15), &view);
QApplication::processEvents();
QCOMPARE(eventSpy.counts[QEvent::TouchBegin], 1);
QCOMPARE(eventSpy.counts[QEvent::TouchUpdate], 2);
QCOMPARE(eventSpy.counts[QEvent::TouchEnd], 1);
+}
- delete view;
- delete proxy;
- delete scene;
+void tst_QGraphicsProxyWidget::touchEventPropagation()
+{
+ QGraphicsScene scene(0, 0, 300, 200);
+ QWidget *simpleWidget = new QWidget;
+ simpleWidget->setObjectName("simpleWidget");
+ simpleWidget->setAttribute(Qt::WA_AcceptTouchEvents, true);
+ QGraphicsProxyWidget *simpleProxy = scene.addWidget(simpleWidget);
+ simpleProxy->setAcceptTouchEvents(true);
+ simpleProxy->setGeometry(QRectF(0, 0, 30, 30));
+
+ QWidget *formWidget = new QWidget;
+ formWidget->setObjectName("formWidget");
+ formWidget->setAttribute(Qt::WA_AcceptTouchEvents, true);
+ QPushButton *pushButton1 = new QPushButton("One");
+ pushButton1->setObjectName("pushButton1");
+ pushButton1->setAttribute(Qt::WA_AcceptTouchEvents, true);
+ QPushButton *pushButton2 = new QPushButton("Two");
+ pushButton2->setObjectName("pushButton2");
+ pushButton2->setAttribute(Qt::WA_AcceptTouchEvents, true);
+ TouchWidget *touchWidget1 = new TouchWidget;
+ touchWidget1->setObjectName("touchWidget1");
+ touchWidget1->setAttribute(Qt::WA_AcceptTouchEvents, true);
+ touchWidget1->setFixedSize(pushButton1->sizeHint());
+ TouchWidget *touchWidget2 = new TouchWidget;
+ touchWidget2->setObjectName("touchWidget2");
+ touchWidget2->setAttribute(Qt::WA_AcceptTouchEvents, true);
+ touchWidget2->setFixedSize(pushButton2->sizeHint());
+ QVBoxLayout *vbox = new QVBoxLayout;
+ vbox->addWidget(pushButton1);
+ vbox->addWidget(pushButton2);
+ vbox->addWidget(touchWidget1);
+ vbox->addWidget(touchWidget2);
+ formWidget->setLayout(vbox);
+ QGraphicsProxyWidget *formProxy = scene.addWidget(formWidget);
+ formProxy->setAcceptTouchEvents(true);
+ formProxy->setGeometry(QRectF(50, 50, 200, 160));
+
+ QGraphicsView view(&scene);
+ view.setFixedSize(scene.width(), scene.height());
+ view.verticalScrollBar()->setValue(0);
+ view.horizontalScrollBar()->setValue(0);
+ view.viewport()->setObjectName("GraphicsView's Viewport");
+ view.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
+
+ class TouchEventSpy : public QObject
+ {
+ public:
+ using QObject::QObject;
+
+ struct TouchRecord {
+ QObject *receiver;
+ QEvent::Type eventType;
+ QPointF position;
+ };
+ QHash<int, QList<TouchRecord>> records;
+ QWidget *mousePressReceiver = nullptr;
+
+ int count(int id = 0) const { return records.value(id).size(); }
+ TouchRecord at(int i, int id = 0) const { return records.value(id).at(i); }
+ void clear()
+ {
+ records.clear();
+ mousePressReceiver = nullptr;
+ }
+ protected:
+ bool eventFilter(QObject *receiver, QEvent *event) override
+ {
+ switch (event->type()) {
+ case QEvent::TouchBegin:
+ case QEvent::TouchUpdate:
+ case QEvent::TouchCancel:
+ case QEvent::TouchEnd: {
+ QTouchEvent *touchEvent = static_cast<QTouchEvent *>(event);
+ // instead of detaching each QEventPoint, just store the relative positions
+ for (const auto &touchPoint : touchEvent->points())
+ records[touchPoint.id()] << TouchRecord{receiver, event->type(), touchPoint.position()};
+ qCDebug(lcTests) << "Recording" << event << receiver;
+ break;
+ }
+ case QEvent::MouseButtonPress:
+ mousePressReceiver = qobject_cast<QWidget*>(receiver);
+ break;
+ default:
+ break;
+ }
+ return QObject::eventFilter(receiver, event);
+ }
+ } eventSpy;
+ qApp->installEventFilter(&eventSpy);
+
+ auto touchDevice = QTest::createTouchDevice();
+ const QPointF simpleCenter = simpleProxy->geometry().center();
+
+ // On systems without double conversion we might get different rounding behavior.
+ // One pixel off in any direction is acceptable for this test.
+ constexpr auto closeEnough = [](QPointF exp, QPointF act) -> bool {
+ const QRectF expArea(exp - QPointF(1., 1.), exp + QPointF(1., 1.));
+ const bool contains = expArea.contains(act);
+ if (!contains)
+ qWarning() << act << "not in" << exp;
+ return contains;
+ };
+
+ // verify that the embedded widget gets the correctly translated event
+ QTest::touchEvent(&view, touchDevice).press(0, simpleCenter.toPoint());
+ // window, viewport, scene, simpleProxy, simpleWidget
+ QCOMPARE(eventSpy.count(), 5);
+ QCOMPARE(eventSpy.at(0).receiver, view.windowHandle());
+ QCOMPARE(eventSpy.at(1).receiver, view.viewport());
+ QCOMPARE(eventSpy.at(2).receiver, &scene);
+ QCOMPARE(eventSpy.at(3).receiver, simpleProxy);
+ auto record = eventSpy.at(4);
+ QCOMPARE(record.receiver, simpleWidget);
+ QCOMPARE(record.eventType, QEvent::TouchBegin);
+ QVERIFY(closeEnough(record.position, simpleCenter));
+ eventSpy.clear();
+
+ // verify that the layout of formWidget is how we expect it to be
+ QCOMPARE(formWidget->childAt(QPoint(5, 5)), nullptr);
+ const QPoint pb1Center = pushButton1->rect().center();
+ QCOMPARE(formWidget->childAt(pushButton1->pos() + pb1Center), pushButton1);
+ const QPoint pb2Center = pushButton2->rect().center();
+ QCOMPARE(formWidget->childAt(pushButton2->pos() + pb2Center), pushButton2);
+ const QPoint tw1Center = touchWidget1->rect().center();
+ QCOMPARE(formWidget->childAt(touchWidget1->pos() + tw1Center), touchWidget1);
+ const QPoint tw2Center = touchWidget2->rect().center();
+ QCOMPARE(formWidget->childAt(touchWidget2->pos() + tw2Center), touchWidget2);
+
+ // touch events are sent to the view, in view coordinates
+ const QPoint formProxyPox = view.mapFromScene(formProxy->pos().toPoint());
+ const QPoint pb1TouchPos = pushButton1->pos() + pb1Center + formProxyPox;
+ const QPoint pb2TouchPos = pushButton2->pos() + pb2Center + formProxyPox;
+ const QPoint tw1TouchPos = touchWidget1->pos() + tw1Center + formProxyPox;
+ const QPoint tw2TouchPos = touchWidget2->pos() + tw2Center + formProxyPox;
+
+ QSignalSpy clickedSpy(pushButton1, &QPushButton::clicked);
+ // Single touch point to nested widget not accepting event.
+ // Event should bubble up and translate correctly, TouchUpdate and TouchEnd events
+ // stop at the window since nobody accepted the TouchBegin. A mouse event will be generated.
+ QTest::touchEvent(&view, touchDevice).press(0, pb1TouchPos);
+ QTest::touchEvent(&view, touchDevice).move(0, pb1TouchPos + QPoint(1, 1));
+ QTest::touchEvent(&view, touchDevice).release(0, pb1TouchPos + QPoint(1, 1));
+ // ..., formProxy, pushButton1, formWidget, window, window
+ QCOMPARE(eventSpy.count(), 8);
+ QCOMPARE(eventSpy.at(3).receiver, formProxy); // formProxy dispatches to the right subwidget
+ record = eventSpy.at(4);
+ QCOMPARE(record.receiver, pushButton1);
+ QVERIFY(closeEnough(record.position, pb1Center));
+ QCOMPARE(record.eventType, QEvent::TouchBegin);
+ // pushButton doesn't accept the point, so the TouchBegin propagates to parent
+ record = eventSpy.at(5);
+ QCOMPARE(record.receiver, formWidget);
+ QVERIFY(closeEnough(record.position, pushButton1->pos() + pb1Center));
+ QCOMPARE(record.eventType, QEvent::TouchBegin);
+ record = eventSpy.at(6);
+ QCOMPARE(record.receiver, view.windowHandle());
+ QCOMPARE(record.eventType, QEvent::TouchUpdate);
+ record = eventSpy.at(7);
+ QCOMPARE(record.receiver, view.windowHandle());
+ QCOMPARE(record.eventType, QEvent::TouchEnd);
+ QCOMPARE(eventSpy.mousePressReceiver, pushButton1);
+ QCOMPARE(clickedSpy.size(), 1);
+ eventSpy.clear();
+ clickedSpy.clear();
+
+ // Single touch point to nested widget accepting event.
+ QTest::touchEvent(&view, touchDevice).press(0, tw1TouchPos);
+ QTest::touchEvent(&view, touchDevice).move(0, tw1TouchPos + QPoint(5, 5));
+ QTest::touchEvent(&view, touchDevice).release(0, tw1TouchPos + QPoint(5, 5));
+ // Press: ..., formProxy, touchWidget1 (5)
+ // Move: window, touchWidget1 (2)
+ // Release: window, touchWidget1 (2)
+ QCOMPARE(eventSpy.count(), 9);
+ QCOMPARE(eventSpy.at(3).receiver, formProxy); // form proxy dispatches TouchBegin to the right widget
+ record = eventSpy.at(4);
+ QCOMPARE(record.receiver, touchWidget1);
+ QVERIFY(closeEnough(record.position, tw1Center));
+ QCOMPARE(record.eventType, QEvent::TouchBegin);
+ QCOMPARE(eventSpy.at(5).receiver, view.windowHandle()); // QWidgetWindow dispatches TouchUpdate
+ record = eventSpy.at(6);
+ QCOMPARE(record.receiver, touchWidget1);
+ QVERIFY(closeEnough(record.position, tw1Center + QPoint(5, 5)));
+ QCOMPARE(record.eventType, QEvent::TouchUpdate);
+ QCOMPARE(eventSpy.at(7).receiver, view.windowHandle()); // QWidgetWindow dispatches TouchEnd
+ record = eventSpy.at(8);
+ QCOMPARE(record.receiver, touchWidget1);
+ QVERIFY(closeEnough(record.position, tw1Center + QPoint(5, 5)));
+ QCOMPARE(record.eventType, QEvent::TouchEnd);
+ eventSpy.clear();
+
+ // to simplify the remaining test, install the event spy explicitly on the target widgets
+ qApp->removeEventFilter(&eventSpy);
+ formWidget->installEventFilter(&eventSpy);
+ pushButton1->installEventFilter(&eventSpy);
+ pushButton2->installEventFilter(&eventSpy);
+ touchWidget1->installEventFilter(&eventSpy);
+ touchWidget2->installEventFilter(&eventSpy);
+
+ // multi-touch to different widgets, some do and some don't accept the event
+ QTest::touchEvent(&view, touchDevice)
+ .press(0, pb1TouchPos)
+ .press(1, tw1TouchPos)
+ .press(2, pb2TouchPos)
+ .press(3, tw2TouchPos);
+ QTest::touchEvent(&view, touchDevice)
+ .move(0, pb1TouchPos + QPoint(1, 1))
+ .move(1, tw1TouchPos + QPoint(1, 1))
+ .move(2, pb2TouchPos + QPoint(1, 1))
+ .move(3, tw2TouchPos + QPoint(1, 1));
+ QTest::touchEvent(&view, touchDevice)
+ .release(0, pb1TouchPos + QPoint(1, 1))
+ .release(1, tw1TouchPos + QPoint(1, 1))
+ .release(2, pb2TouchPos + QPoint(1, 1))
+ .release(3, tw2TouchPos + QPoint(1, 1));
+
+ QCOMPARE(eventSpy.count(0), 2); // Begin never accepted, so move up and then stop
+ QCOMPARE(eventSpy.count(1), 3); // Begin accepted, so not propagated and update/end received
+ QCOMPARE(eventSpy.count(2), 2); // Begin never accepted
+ QCOMPARE(eventSpy.count(3), 3); // Begin accepted
+ QCOMPARE(eventSpy.at(0, 0).receiver, pushButton1);
+ QCOMPARE(eventSpy.at(1, 0).receiver, formWidget);
+ QCOMPARE(eventSpy.at(0, 1).receiver, touchWidget1);
+ QCOMPARE(eventSpy.at(1, 1).receiver, touchWidget1);
+ QCOMPARE(eventSpy.at(2, 1).receiver, touchWidget1);
+ QCOMPARE(eventSpy.at(0, 2).receiver, pushButton2);
+ QCOMPARE(eventSpy.at(1, 2).receiver, formWidget);
+ QCOMPARE(eventSpy.at(0, 3).receiver, touchWidget2);
+ QCOMPARE(eventSpy.at(1, 3).receiver, touchWidget2);
+ QCOMPARE(eventSpy.at(2, 3).receiver, touchWidget2);
+ QCOMPARE(clickedSpy.size(), 0); // multi-touch event does not synthesize a mouse event
}
QTEST_MAIN(tst_QGraphicsProxyWidget)