diff options
| -rw-r--r-- | src/corelib/kernel/qassociativeiterable.h | 15 | ||||
| -rw-r--r-- | src/corelib/kernel/qsequentialiterable.h | 15 | ||||
| -rw-r--r-- | src/plugins/platforms/windows/qwindowswindow.cpp | 7 | ||||
| -rw-r--r-- | src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp | 10 | ||||
| -rw-r--r-- | src/testlib/qtest.h | 8 | ||||
| -rw-r--r-- | src/widgets/itemviews/qtreeview.cpp | 11 | ||||
| -rw-r--r-- | src/widgets/kernel/qstandardgestures.cpp | 10 | ||||
| -rw-r--r-- | tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp | 23 | ||||
| -rw-r--r-- | tests/auto/widgets/kernel/qgesturerecognizer/tst_qgesturerecognizer.cpp | 108 |
9 files changed, 160 insertions, 47 deletions
diff --git a/src/corelib/kernel/qassociativeiterable.h b/src/corelib/kernel/qassociativeiterable.h index 4f9bbf67bfb..c042fe4a0ec 100644 --- a/src/corelib/kernel/qassociativeiterable.h +++ b/src/corelib/kernel/qassociativeiterable.h @@ -21,9 +21,8 @@ QT_WARNING_DISABLE_DEPRECATED Q_CORE_EXPORT QT_DEPRECATED_VERSION_X_6_15(text) #endif -class -QT_CORE_DEPRECATED_EXPORT_VERSION_X_6_15("Use QMetaAssociation::Iterable::Iterator instead.") -QAssociativeIterator : public QIterator<QMetaAssociation> +// Keep this a single long line, otherwise syncqt doesn't create a class forwarding header +class QT_CORE_DEPRECATED_EXPORT_VERSION_X_6_15("Use QMetaAssociation's iterables and iterators instead.") QAssociativeIterator : public QIterator<QMetaAssociation> { public: using key_type = QVariant; @@ -42,9 +41,8 @@ public: QVariantPointer<QAssociativeIterator> operator->() const; }; -class -QT_CORE_DEPRECATED_EXPORT_VERSION_X_6_15("Use QMetaAssociation::Iterable::ConstIterator instead.") -QAssociativeConstIterator : public QConstIterator<QMetaAssociation> +// Keep this a single long line, otherwise syncqt doesn't create a class forwarding header +class QT_CORE_DEPRECATED_EXPORT_VERSION_X_6_15("Use QMetaAssociation's iterables and iterators instead.") QAssociativeConstIterator : public QConstIterator<QMetaAssociation> { public: using key_type = QVariant; @@ -63,9 +61,8 @@ public: QVariantConstPointer operator->() const; }; -class -QT_CORE_DEPRECATED_EXPORT_VERSION_X_6_15("Use QMetaAssociation::Iterable instead.") -QAssociativeIterable : public QIterable<QMetaAssociation> +// Keep this a single long line, otherwise syncqt doesn't create a class forwarding header +class QT_CORE_DEPRECATED_EXPORT_VERSION_X_6_15("Use QMetaAssociation's iterables and iterators instead.") QAssociativeIterable : public QIterable<QMetaAssociation> { public: using iterator = QTaggedIterator<QAssociativeIterator, void>; diff --git a/src/corelib/kernel/qsequentialiterable.h b/src/corelib/kernel/qsequentialiterable.h index 76908bdae4b..b2e690ea9cf 100644 --- a/src/corelib/kernel/qsequentialiterable.h +++ b/src/corelib/kernel/qsequentialiterable.h @@ -21,9 +21,8 @@ QT_WARNING_DISABLE_DEPRECATED Q_CORE_EXPORT QT_DEPRECATED_VERSION_X_6_15(text) #endif -class -QT_CORE_DEPRECATED_EXPORT_VERSION_X_6_15("Use QMetaSequence::Iterable::Iterator instead.") -QSequentialIterator : public QIterator<QMetaSequence> +// Keep this a single long line, otherwise syncqt doesn't create a class forwarding header +class QT_CORE_DEPRECATED_EXPORT_VERSION_X_6_15("Use QMetaSequence's iterables and iterators instead.") QSequentialIterator : public QIterator<QMetaSequence> { public: using value_type = QVariant; @@ -38,9 +37,8 @@ public: QVariantPointer<QSequentialIterator> operator->() const; }; -class -QT_CORE_DEPRECATED_EXPORT_VERSION_X_6_15("Use QMetaSequence::Iterable::ConstIterator instead.") -QSequentialConstIterator : public QConstIterator<QMetaSequence> +// Keep this a single long line, otherwise syncqt doesn't create a class forwarding header +class QT_CORE_DEPRECATED_EXPORT_VERSION_X_6_15("Use QMetaSequence's iterables and iterators instead.") QSequentialConstIterator : public QConstIterator<QMetaSequence> { public: using value_type = QVariant; @@ -55,9 +53,8 @@ public: QVariantConstPointer operator->() const; }; -class -QT_CORE_DEPRECATED_EXPORT_VERSION_X_6_15("Use QMetaSequence::Iterable instead.") -QSequentialIterable : public QIterable<QMetaSequence> +// Keep this a single long line, otherwise syncqt doesn't create a class forwarding header +class QT_CORE_DEPRECATED_EXPORT_VERSION_X_6_15("Use QMetaSequence's iterables and iterators instead.") QSequentialIterable : public QIterable<QMetaSequence> { public: using iterator = QTaggedIterator<QSequentialIterator, void>; diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 9459e8bdfd3..f96f154f5b1 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -4035,10 +4035,13 @@ void QWindowsWindow::requestUpdate() // the Posted event on the GUI thread. if (m_vsyncUpdatePending.testAndSetAcquire(UpdateState::Requested, UpdateState::Posted)) { QWindowsWindow *oldSelf = this; - QMetaObject::invokeMethod(w, [w, oldSelf] { + qsizetype oldCallbackId = m_vsyncServiceCallbackId; + QMetaObject::invokeMethod(w, [w, oldSelf, oldCallbackId] { // 'oldSelf' is only used for comparison, don't access it directly! auto *self = static_cast<QWindowsWindow *>(w->handle()); - if (self && self == oldSelf) { + // NOTE: In the off chance that the window got destroyed and recreated with the + // same address, we also check that the callback id is the same. + if (self && self == oldSelf && self->m_vsyncServiceCallbackId == oldCallbackId) { // The platform window is still alive self->m_vsyncUpdatePending.storeRelease(UpdateState::Ready); self->deliverUpdateRequest(); diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp index e2f181aa628..2ea3fe38e1c 100644 --- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp @@ -596,6 +596,16 @@ HRESULT QWindowsUiaMainProvider::GetPropertyValue(PROPERTYID idProp, VARIANT *pR *pRetVal = QComVariant{ accessible->text(QAccessible::Help) }.release(); break; case UIA_HasKeyboardFocusPropertyId: + // If the top-level window has no focused child, report the top-level + // widget (window). If it already has a focused widget, it will be + // reported automatically. + if (topLevelWindow) { + QAccessibleInterface *focusacc = accessible->focusChild(); + if (!focusacc) { + *pRetVal = QComVariant{ accessible->state().active ? true : false }.release(); + break; + } + } *pRetVal = QComVariant{ accessible->state().focused ? true : false }.release(); break; case UIA_IsKeyboardFocusablePropertyId: diff --git a/src/testlib/qtest.h b/src/testlib/qtest.h index 431f91d5474..10bb63040c8 100644 --- a/src/testlib/qtest.h +++ b/src/testlib/qtest.h @@ -181,16 +181,16 @@ inline bool qCompare(quint32 const &t1, quint64 const &t2, const char *actual, } namespace Internal { -template <typename T, typename = void> -struct HasInitMain : std::false_type{}; +template <typename T> +using InitMainTest = decltype(&T::initMain); template <typename T> -struct HasInitMain<T, std::void_t<decltype(&T::initMain)>> : std::true_type {}; +constexpr inline bool hasInitMain = qxp::is_detected_v<InitMainTest, T>; template<typename T> void callInitMain() { - if constexpr (HasInitMain<T>::value) + if constexpr (hasInitMain<T>) T::initMain(); } diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp index 570566793dc..0f0496ad04d 100644 --- a/src/widgets/itemviews/qtreeview.cpp +++ b/src/widgets/itemviews/qtreeview.cpp @@ -1622,12 +1622,6 @@ void QTreeViewPrivate::calcLogicalIndices( const auto indicesCount = logicalIndices->size(); itemPositions->resize(indicesCount); for (qsizetype currentLogicalSection = 0; currentLogicalSection < indicesCount; ++currentLogicalSection) { - // shortcut, no need to calc anything more - if (indicesCount == 1 || spanning) { - (*itemPositions)[currentLogicalSection] = QStyleOptionViewItem::OnlyOne; - continue; - } - const int headerSection = logicalIndices->at(currentLogicalSection); // determine the viewItemPosition depending on the position of column 0 int nextLogicalSection = currentLogicalSection + 1 >= indicesCount ? logicalIndexAfterRight @@ -1635,8 +1629,11 @@ void QTreeViewPrivate::calcLogicalIndices( int prevLogicalSection = currentLogicalSection - 1 < 0 ? logicalIndexBeforeLeft : logicalIndices->at(currentLogicalSection - 1); + const int headerSection = logicalIndices->at(currentLogicalSection); QStyleOptionViewItem::ViewItemPosition pos; - if ((nextLogicalSection != 0 && prevLogicalSection == -1) || isTreePosition(headerSection)) + if ((nextLogicalSection == -1 && prevLogicalSection == -1) || spanning) { + pos = QStyleOptionViewItem::OnlyOne; + } else if ((nextLogicalSection != 0 && prevLogicalSection == -1) || isTreePosition(headerSection)) pos = QStyleOptionViewItem::Beginning; else if (nextLogicalSection == 0 || nextLogicalSection == -1) pos = QStyleOptionViewItem::End; diff --git a/src/widgets/kernel/qstandardgestures.cpp b/src/widgets/kernel/qstandardgestures.cpp index e9de82d2357..314d82fd64f 100644 --- a/src/widgets/kernel/qstandardgestures.cpp +++ b/src/widgets/kernel/qstandardgestures.cpp @@ -348,8 +348,14 @@ QGestureRecognizer::Result QSwipeGestureRecognizer::recognize(QGesture *state, result = QGestureRecognizer::Ignore; break; case QSwipeGesturePrivate::ThreePointsReached: - result = (ev->touchPointStates() & QEventPoint::State::Pressed) - ? QGestureRecognizer::CancelGesture : QGestureRecognizer::Ignore; + if (ev->touchPointStates() & QEventPoint::State::Pressed) { + result = QGestureRecognizer::CancelGesture; + } else if (d->verticalDirection != QSwipeGesture::NoDirection || + d->horizontalDirection != QSwipeGesture::NoDirection) { + result = QGestureRecognizer::TriggerGesture; + } else { + result = QGestureRecognizer::Ignore; + } break; } } diff --git a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp index ac50a5cdae7..e42fb4419a8 100644 --- a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp +++ b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp @@ -3518,12 +3518,33 @@ void tst_QTreeView::styleOptionViewItem() model.clear(); model.appendRow({ new QStandardItem("Hidden"), new QStandardItem("OnlyOne Last") }); + view.setModel(&model); view.setColumnHidden(0, true); view.setColumnHidden(1, false); - view.setModel(&model); delegate.count = 0; QTRY_COMPARE_GE(delegate.count, 1); + + // special case, four columns, only one is updated but + // calcLogicalIndices() returns the correct value + { + model.clear(); + model.appendRow({ new QStandardItem("Hidden"), + new QStandardItem("Beginning Last"), + new QStandardItem("Middle Last"), + new QStandardItem("End Last") }); + view.setColumnHidden(0, true); + delegate.count = 0; + QTRY_COMPARE_GE(delegate.count, 4); + + // do not rely on paintEvent() as this might redraw a bigger + // rect than we expect + QList<int> logicalIndices; + QList<QStyleOptionViewItem::ViewItemPosition> itemPositions; + view.d_func()->calcLogicalIndices(&logicalIndices, &itemPositions, 3, 3); + QCOMPARE(itemPositions.size(), 1); + QCOMPARE(itemPositions.at(0), QStyleOptionViewItem::End); + } } class task174627_TreeView : public QTreeView diff --git a/tests/auto/widgets/kernel/qgesturerecognizer/tst_qgesturerecognizer.cpp b/tests/auto/widgets/kernel/qgesturerecognizer/tst_qgesturerecognizer.cpp index febb9e2c9dc..255bcaa5bec 100644 --- a/tests/auto/widgets/kernel/qgesturerecognizer/tst_qgesturerecognizer.cpp +++ b/tests/auto/widgets/kernel/qgesturerecognizer/tst_qgesturerecognizer.cpp @@ -9,11 +9,14 @@ #include <QtGui/QScreen> #include <QtGui/QPointingDevice> #include <QtCore/QList> +#include <QtCore/QLoggingCategory> #include <QtCore/QString> #include <QtCore/QHash> #include <QtCore/QDebug> #include <memory> +Q_LOGGING_CATEGORY(lcTests, "qt.widgets.tests") + class tst_QGestureRecognizer : public QObject { Q_OBJECT @@ -60,14 +63,30 @@ public: bool gestureReceived(Qt::GestureType gestureType) const { return m_receivedGestures.value(gestureType); } -protected: - bool event(QEvent * event) override; + void clearReceivedGestures(); -private: - typedef QHash<Qt::GestureType, bool> GestureTypeHash; - GestureTypeHash m_receivedGestures; + qreal lastSwipeAngle = 0; + QSwipeGesture::SwipeDirection lastHorizontalDirection = QSwipeGesture::NoDirection; + QSwipeGesture::SwipeDirection lastVerticalDirection = QSwipeGesture::NoDirection; + Qt::GestureState lastSwipeState = Qt::NoGesture; + + protected: + bool event(QEvent *event) override; + + private: + typedef QHash<Qt::GestureType, bool> GestureTypeHash; + GestureTypeHash m_receivedGestures; }; +void TestWidget::clearReceivedGestures() +{ + m_receivedGestures.clear(); + lastSwipeAngle = {}; + lastHorizontalDirection = QSwipeGesture::NoDirection; + lastVerticalDirection = QSwipeGesture::NoDirection; + lastSwipeState = Qt::NoGesture; +} + TestWidget::TestWidget(const GestureTypeVector &gestureTypes) { setAttribute(Qt::WA_AcceptTouchEvents); @@ -95,8 +114,22 @@ bool TestWidget::event(QEvent * event) it.value() = true; } } - } + for (const QGesture *gesture : gestureEvent->activeGestures()) { + switch (gesture->gestureType()) { + case Qt::SwipeGesture: { + const auto *swipe = static_cast<const QSwipeGesture *>(gesture); + lastSwipeAngle = swipe->swipeAngle(); + lastHorizontalDirection = swipe->horizontalDirection(); + lastVerticalDirection = swipe->verticalDirection(); + lastSwipeState = gesture->state(); + break; + } + default: + break; + } + } break; + } default: break; } @@ -241,10 +274,26 @@ enum SwipeSubTest { void tst_QGestureRecognizer::swipeGesture_data() { QTest::addColumn<int>("swipeSubTest"); + QTest::addColumn<QPoint>("moveDelta"); QTest::addColumn<bool>("gestureExpected"); - QTest::newRow("Line") << int(SwipeLineSubTest) << true; - QTest::newRow("DirectionChange") << int(SwipeDirectionChangeSubTest) << false; - QTest::newRow("SmallDirectionChange") << int(SwipeSmallDirectionChangeSubTest) << true; + QTest::addColumn<int>("expectedAngle"); + QTest::addColumn<QSwipeGesture::SwipeDirection>("expectedHorizontalDirection"); + QTest::addColumn<QSwipeGesture::SwipeDirection>("expectedVerticalDirection"); + + QTest::newRow("UpRight Line") << int(SwipeLineSubTest) << QPoint(42, -25) + << true << 30 << QSwipeGesture::Right << QSwipeGesture::Up; + QTest::newRow("DownRight Line") << int(SwipeLineSubTest) << QPoint(42, 25) + << true << 329 << QSwipeGesture::Right << QSwipeGesture::Down; + QTest::newRow("OutRight Line") << int(SwipeLineSubTest) << QPoint(42, 0) + << true << 360 << QSwipeGesture::Right << QSwipeGesture::NoDirection; + QTest::newRow("DownLeft Line") << int(SwipeLineSubTest) << QPoint(-42, 25) + << true << 211 << QSwipeGesture::Left << QSwipeGesture::Down; + QTest::newRow("Up Line") << int(SwipeLineSubTest) << QPoint(0, -25) + << true << 90 << QSwipeGesture::NoDirection << QSwipeGesture::Up; + QTest::newRow("DirectionChange") << int(SwipeDirectionChangeSubTest) << QPoint(42, 25) + << false << 0 << QSwipeGesture::NoDirection << QSwipeGesture::NoDirection; + QTest::newRow("SmallDirectionChange") << int(SwipeSmallDirectionChangeSubTest) << QPoint(42, -25) + << true << 359 << QSwipeGesture::Right << QSwipeGesture::Down; } void tst_QGestureRecognizer::swipeGesture() @@ -252,7 +301,11 @@ void tst_QGestureRecognizer::swipeGesture() enum { swipePoints = 3 }; QFETCH(int, swipeSubTest); + QFETCH(QPoint, moveDelta); QFETCH(bool, gestureExpected); + QFETCH(int, expectedAngle); + QFETCH(QSwipeGesture::SwipeDirection, expectedHorizontalDirection); + QFETCH(QSwipeGesture::SwipeDirection, expectedVerticalDirection); const Qt::GestureType gestureType = Qt::SwipeGesture; TestWidget widget(GestureTypeVector(1, gestureType)); @@ -264,20 +317,27 @@ void tst_QGestureRecognizer::swipeGesture() // Start a swipe sequence with 2 points (QTBUG-15768) const QPoint fingerDistance(m_fingerDistance, m_fingerDistance); QList<QPoint> points; - for (int i = 0; i < swipePoints - 1; ++i) + for (int i = 1; i < swipePoints; ++i) points.append(fingerDistance + i * fingerDistance); QTest::QTouchEventWidgetSequence swipeSequence = QTest::touchEvent(&widget, m_touchDevice.get()); pressSequence(swipeSequence, points, &widget); + // Move a little: nothing happens + points[0] += {1, 1}; + points[1] += {1, 1}; + swipeSequence.move(0, points[0], &widget).move(1, points[1], &widget).commit(); + QCoreApplication::processEvents(); + QVERIFY(!widget.gestureReceived(gestureType)); + // Press point #3 points.append(points.last() + fingerDistance); swipeSequence.stationary(0).stationary(1).press(points.size() - 1, points.last(), &widget); swipeSequence.commit(); Q_ASSERT(points.size() == swipePoints); + QCOMPARE(widget.lastSwipeState, Qt::NoGesture); // Move. - const QPoint moveDelta(60, 20); switch (swipeSubTest) { case SwipeLineSubTest: linearSequence(5, moveDelta, swipeSequence, points, &widget); @@ -294,15 +354,37 @@ void tst_QGestureRecognizer::swipeGesture() } break; } + QCOMPARE(widget.lastSwipeState, Qt::GestureUpdated); - releaseSequence(swipeSequence, points, &widget); - + // release any point: the gesture ends + swipeSequence.release(0, points[0], &widget).commit(); if (gestureExpected) { QTRY_VERIFY(widget.gestureReceived(gestureType)); + qCDebug(lcTests) << "started @" << fingerDistance + << "; ended with angle" << widget.lastSwipeAngle + << "expected" << expectedAngle + << "dirns" << widget.lastHorizontalDirection << widget.lastVerticalDirection; + QCOMPARE(qRound(widget.lastSwipeAngle), expectedAngle); + QEXPECT_FAIL("Up Line", "90 degrees (up) should be NoDirection on horizontal axis", Continue); + QCOMPARE(widget.lastHorizontalDirection, expectedHorizontalDirection); + QEXPECT_FAIL("OutRight Line", "0 degrees (to the right) should be NoDirection on the vertical axis", Continue); + QCOMPARE(widget.lastVerticalDirection, expectedVerticalDirection); + QCOMPARE(widget.lastSwipeState, Qt::GestureFinished); } else { QCoreApplication::processEvents(); QVERIFY(!widget.gestureReceived(gestureType)); + QCOMPARE(widget.lastSwipeState, Qt::GestureUpdated); } + + // move the others a little, then release: no further swipe (it needs 3 fingers) + widget.clearReceivedGestures(); + points[1] += {1, 1}; + points[2] += {1, 1}; + swipeSequence.move(1, points[1], &widget).move(2, points[2], &widget).commit(); + swipeSequence.release(1, points[1], &widget).release(2, points[2], &widget).commit(); + QCoreApplication::processEvents(); + QVERIFY(!widget.gestureReceived(gestureType)); + QCOMPARE(widget.lastSwipeState, Qt::NoGesture); } void tst_QGestureRecognizer::touchReplay() |
