diff options
author | Tarja Sundqvist <tarja.sundqvist@qt.io> | 2023-06-09 17:09:07 +0300 |
---|---|---|
committer | Tarja Sundqvist <tarja.sundqvist@qt.io> | 2023-06-09 17:09:07 +0300 |
commit | 1ce461bd1dc713cd2f79fc16c5454d587b45eefa (patch) | |
tree | 88e4849e71abfdd9bc2aa1d439ecd01afb1ca0c7 | |
parent | c433697a686e7a24dc4bfd58f2a46c05ae7b7716 (diff) | |
parent | 56acab014d490951f14e6719b7bd535146646fc7 (diff) |
Merge remote-tracking branch 'origin/tqtc/lts-5.15.11' into tqtc/lts-5.15-opensourcev5.15.11-lts-lgpl
Change-Id: I9a361b46c1ff401d6e58c31b1fd46241ec9ebaea
-rw-r--r-- | .qmake.conf | 2 | ||||
-rw-r--r-- | src/quicktemplates2/qquickcontrol.cpp | 45 | ||||
-rw-r--r-- | src/quicktemplates2/qquickcontrol_p_p.h | 1 | ||||
-rw-r--r-- | src/quicktemplates2/qquickscrollbar.cpp | 13 | ||||
-rw-r--r-- | src/quicktemplates2/qquickscrollbar_p_p.h | 2 | ||||
-rw-r--r-- | tests/auto/controls/data/tst_scrollview.qml | 47 | ||||
-rw-r--r-- | tests/auto/controls/data/tst_slider.qml | 35 |
7 files changed, 139 insertions, 6 deletions
diff --git a/.qmake.conf b/.qmake.conf index edff2782..6279b0c5 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -5,4 +5,4 @@ DEFINES += QT_NO_FOREACH QT_NO_JAVA_STYLE_ITERATORS QT_NO_LINKED_LIST QQC2_SOURCE_TREE = $$PWD -MODULE_VERSION = 5.15.10 +MODULE_VERSION = 5.15.11 diff --git a/src/quicktemplates2/qquickcontrol.cpp b/src/quicktemplates2/qquickcontrol.cpp index 409fb582..a719efd3 100644 --- a/src/quicktemplates2/qquickcontrol.cpp +++ b/src/quicktemplates2/qquickcontrol.cpp @@ -177,12 +177,19 @@ bool QQuickControlPrivate::acceptTouch(const QTouchEvent::TouchPoint &point) return true; } - // If the control is on a Flickable that has a pressDelay, then the press is never - // sent as a touch event, therefore we need to check for this case. - if (touchId == -1 && pressWasTouch && point.state() == Qt::TouchPointReleased) { + // If the control is on a Flickable that has a pressDelay, the press is sent + // as a mouse event rather than touch; so it detect and deal with it. + if (touchId == -1 && pressWasTouch) { const auto delta = QVector2D(point.pos() - previousPressPos); - if (!QQuickWindowPrivate::dragOverThreshold(delta)) + const bool overThreshold = QQuickWindowPrivate::dragOverThreshold(delta); + if (point.state() == Qt::TouchPointReleased && !overThreshold) { + // touchpoint was released near the press position: don't expect any more events, but just handle the release return true; + } else if (point.state() == Qt::TouchPointMoved && overThreshold) { + // touchpoint was dragged over the drag threshold: accept it, and remember to handle all moves from now on + touchId = point.id(); + return true; + } } return false; } @@ -846,6 +853,13 @@ void QQuickControlPrivate::executeBackground(bool complete) quickCompleteDeferred(q, backgroundName(), background); } +/* + \internal + + Hides an item that was replaced by a newer one, rather than + deleting it, as the item is typically created in QML and hence + we don't own it. +*/ void QQuickControlPrivate::hideOldItem(QQuickItem *item) { if (!item) @@ -864,6 +878,29 @@ void QQuickControlPrivate::hideOldItem(QQuickItem *item) #endif } +/* + \internal + + Named "unhide" because it's used for cases where an item + that was previously hidden by \l hideOldItem() wants to be + shown by a control again, such as a ScrollBar in ScrollView. +*/ +void QQuickControlPrivate::unhideOldItem(QQuickControl *control, QQuickItem *item) +{ + Q_ASSERT(item); + qCDebug(lcItemManagement) << "unhiding old item" << item; + + item->setVisible(true); + item->setParentItem(control); + +#if QT_CONFIG(accessibility) + // Add the item back in to the accessibility tree. + QQuickAccessibleAttached *accessible = accessibleAttached(item); + if (accessible) + accessible->setIgnored(false); +#endif +} + void QQuickControlPrivate::updateBaselineOffset() { Q_Q(QQuickControl); diff --git a/src/quicktemplates2/qquickcontrol_p_p.h b/src/quicktemplates2/qquickcontrol_p_p.h index 8e979079..a6e624c9 100644 --- a/src/quicktemplates2/qquickcontrol_p_p.h +++ b/src/quicktemplates2/qquickcontrol_p_p.h @@ -173,6 +173,7 @@ public: virtual void executeBackground(bool complete = false); static void hideOldItem(QQuickItem *item); + static void unhideOldItem(QQuickControl *control, QQuickItem *item); void updateBaselineOffset(); diff --git a/src/quicktemplates2/qquickscrollbar.cpp b/src/quicktemplates2/qquickscrollbar.cpp index 4e2f509d..f0783708 100644 --- a/src/quicktemplates2/qquickscrollbar.cpp +++ b/src/quicktemplates2/qquickscrollbar.cpp @@ -77,7 +77,7 @@ QT_BEGIN_NAMESPACE \list \li \l orientation \li \l position - \li \l size + \li \l {ScrollBar::} {size} \li \l active \endlist @@ -797,6 +797,14 @@ void QQuickScrollBarAttachedPrivate::initHorizontal() if (parent && parent == flickable->parentItem()) horizontal->stackAfter(flickable); + // If a scroll bar was previously hidden (due to e.g. setting a new contentItem + // on a ScrollView), we need to make sure that we un-hide it. + // We don't bother checking if the item is actually the old one, because + // if it's not, all of the things the function does (setting parent, visibility, etc.) + // should be no-ops anyway. + if (auto control = qobject_cast<QQuickControl*>(q_func()->parent())) + QQuickControlPrivate::unhideOldItem(control, horizontal); + layoutHorizontal(); horizontal->setSize(area->property("widthRatio").toReal()); horizontal->setPosition(area->property("xPosition").toReal()); @@ -818,6 +826,9 @@ void QQuickScrollBarAttachedPrivate::initVertical() if (parent && parent == flickable->parentItem()) vertical->stackAfter(flickable); + if (auto control = qobject_cast<QQuickControl*>(q_func()->parent())) + QQuickControlPrivate::unhideOldItem(control, vertical); + layoutVertical(); vertical->setSize(area->property("heightRatio").toReal()); vertical->setPosition(area->property("yPosition").toReal()); diff --git a/src/quicktemplates2/qquickscrollbar_p_p.h b/src/quicktemplates2/qquickscrollbar_p_p.h index 5c7628b9..c58c2ed1 100644 --- a/src/quicktemplates2/qquickscrollbar_p_p.h +++ b/src/quicktemplates2/qquickscrollbar_p_p.h @@ -107,6 +107,8 @@ public: class QQuickScrollBarAttachedPrivate : public QObjectPrivate, public QQuickItemChangeListener { + Q_DECLARE_PUBLIC(QQuickScrollBar) + public: static QQuickScrollBarAttachedPrivate *get(QQuickScrollBarAttached *attached) { diff --git a/tests/auto/controls/data/tst_scrollview.qml b/tests/auto/controls/data/tst_scrollview.qml index 0e8b0835..cd493118 100644 --- a/tests/auto/controls/data/tst_scrollview.qml +++ b/tests/auto/controls/data/tst_scrollview.qml @@ -576,4 +576,51 @@ TestCase { verify(newHorizontalScrollBar.visible) verify(!oldHorizontalScrollBar.visible) } + + Component { + id: bindingToContentItemAndStandaloneFlickable + + Item { + width: 200 + height: 200 + + property alias scrollView: scrollView + + ScrollView { + id: scrollView + anchors.fill: parent + contentItem: listView + + property Item someBinding: contentItem + } + ListView { + id: listView + model: 10 + delegate: ItemDelegate { + text: modelData + width: listView.width + } + } + } + } + + // Tests that scroll bars show up for a ScrollView where + // - its contentItem is declared as a standalone, separate item + // - there is a binding to contentItem (which causes a default Flickable to be created) + function test_bindingToContentItemAndStandaloneFlickable() { + let root = createTemporaryObject(bindingToContentItemAndStandaloneFlickable, testCase) + verify(root) + + let control = root.scrollView + let verticalScrollBar = control.ScrollBar.vertical + let horizontalScrollBar = control.ScrollBar.horizontal + compare(verticalScrollBar.parent, control) + compare(horizontalScrollBar.parent, control) + verify(verticalScrollBar.visible) + verify(horizontalScrollBar.visible) + + mouseDrag(verticalScrollBar, verticalScrollBar.width / 2, verticalScrollBar.height / 2, 0, 50) + verify(verticalScrollBar.active) + verify(horizontalScrollBar.active) + } } diff --git a/tests/auto/controls/data/tst_slider.qml b/tests/auto/controls/data/tst_slider.qml index e1e1ed97..bf65e486 100644 --- a/tests/auto/controls/data/tst_slider.qml +++ b/tests/auto/controls/data/tst_slider.qml @@ -923,4 +923,39 @@ TestCase { touch.release(0, control, x0 + data.dx2, y0 + data.dy2).commit() } + + Component { + id: listViewWithPressDelayAndSliders + ListView { + width: 300 + height: 500 + model: 3 + pressDelay: 150 + delegate: Slider { + width: 300 + height: 150 + } + } + } + + function test_listViewWithPressDelay() { + var listView = createTemporaryObject(listViewWithPressDelayAndSliders, testCase, { width: parent.width, height: parent.height }) + verify(listView) + var control = listView.itemAtIndex(0) + verify(control) + var movedSpy = signalSpy.createObject(control, {target: control, signalName: "moved"}) + verify(movedSpy.valid) + + var touch = touchEvent(control) + var x0 = control.handle.x + control.handle.width * 0.5 + var y0 = control.handle.y + control.handle.height * 0.5 + touch.press(0, control, x0, y0).commit() + tryCompare(control, "pressed", true) + fuzzyCompare(control.value, 0, 0.01) + + touch.move(0, control, x0 + 100, y0).commit() + tryVerify(function() { return (control.value > 0.3); }) // around 0.35, depending on style + tryVerify(function() { return (movedSpy.count > 0); }) // ideally == 1, but in Material and Fusion it's 2 + touch.release(0) + } } |