diff options
author | Mitch Curtis <mitch.curtis@qt.io> | 2018-12-06 10:59:45 +0100 |
---|---|---|
committer | Mitch Curtis <mitch.curtis@qt.io> | 2019-01-08 13:15:00 +0000 |
commit | ce9940ca550d70931248a98fc4d47f10959a9a9e (patch) | |
tree | bac7721f3b0dd7d2e7309b1c6efa087937f3d9e4 | |
parent | 8bf2dacabf0a9e5d37df6a202ef0a337995fc8ed (diff) |
SplitView: batch layout requests via polish()/updatePolish()
This results in less layouts, especially when a bunch of properties change
one after the other.
Change-Id: I8dd76d147bcc20f2ccddb587e59ac3e59f580f21
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
-rw-r--r-- | src/quicktemplates2/qquicksplitview.cpp | 70 | ||||
-rw-r--r-- | src/quicktemplates2/qquicksplitview_p_p.h | 5 | ||||
-rw-r--r-- | tests/auto/controls/data/tst_splitview.qml | 49 |
3 files changed, 94 insertions, 30 deletions
diff --git a/src/quicktemplates2/qquicksplitview.cpp b/src/quicktemplates2/qquicksplitview.cpp index ed86daed..64ccb6c7 100644 --- a/src/quicktemplates2/qquicksplitview.cpp +++ b/src/quicktemplates2/qquicksplitview.cpp @@ -630,6 +630,12 @@ void QQuickSplitViewPrivate::layoutPositionItems(const QQuickItem *fillItem) } } +void QQuickSplitViewPrivate::requestLayout() +{ + Q_Q(QQuickSplitView); + q->polish(); +} + void QQuickSplitViewPrivate::layout() { if (!componentComplete) @@ -648,8 +654,9 @@ void QQuickSplitViewPrivate::layout() Q_ASSERT_X(!m_handle || m_handleItems.size() == count - 1, Q_FUNC_INFO, qPrintable(QString::fromLatin1( "Expected %1 handle items, but there are %2").arg(count - 1).arg(m_handleItems.size()))); - // If a split item is being resized, its preferredWidth/Height will be changed, - // which will in turn call layout(). This flag avoids recursive calls. + // We allow mouse events to instantly trigger layouts, whereas with e.g. + // attached properties being set, we require a delayed layout. + // To prevent recursive calls during mouse events, we need this guard. QBoolBlocker guard(m_layingOut, true); const bool horizontal = isHorizontal(); @@ -953,7 +960,9 @@ void QQuickSplitViewPrivate::handleMove(const QPointF &point) if (m_pressedHandleIndex != -1) { m_mousePos = point; - layout(); + // Don't request layouts for input events because we want + // resizing to be as responsive and smooth as possible. + updatePolish(); } } @@ -1000,16 +1009,21 @@ void QQuickSplitViewPrivate::itemVisibilityChanged(QQuickItem *item) updateHandleVisibilities(); updateFillIndex(); - layout(); + requestLayout(); } void QQuickSplitViewPrivate::itemImplicitWidthChanged(QQuickItem *) { - layout(); + requestLayout(); } void QQuickSplitViewPrivate::itemImplicitHeightChanged(QQuickItem *) { + requestLayout(); +} + +void QQuickSplitViewPrivate::updatePolish() +{ layout(); } @@ -1070,7 +1084,7 @@ void QQuickSplitView::setOrientation(Qt::Orientation orientation) d->m_orientation = orientation; d->resizeHandles(); - d->layout(); + d->requestLayout(); emit orientationChanged(); } @@ -1137,7 +1151,7 @@ void QQuickSplitView::setHandle(QQmlComponent *handle) if (d->m_handle) d->createHandles(); - d->layout(); + d->requestLayout(); emit handleChanged(); } @@ -1286,7 +1300,7 @@ void QQuickSplitView::componentComplete() QQuickControl::componentComplete(); d->resizeHandles(); d->updateFillIndex(); - d->layout(); + d->updatePolish(); } void QQuickSplitView::hoverMoveEvent(QHoverEvent *event) @@ -1348,7 +1362,7 @@ void QQuickSplitView::geometryChanged(const QRectF &newGeometry, const QRectF &o Q_D(QQuickSplitView); QQuickControl::geometryChanged(newGeometry, oldGeometry); d->resizeHandles(); - d->layout(); + d->requestLayout(); } void QQuickSplitView::itemAdded(int index, QQuickItem *item) @@ -1377,7 +1391,7 @@ void QQuickSplitView::itemAdded(int index, QQuickItem *item) d->updateHandleVisibilities(); d->updateFillIndex(); - d->layout(); + d->requestLayout(); } void QQuickSplitView::itemMoved(int index, QQuickItem *item) @@ -1390,7 +1404,7 @@ void QQuickSplitView::itemMoved(int index, QQuickItem *item) d->updateHandleVisibilities(); d->updateFillIndex(); - d->layout(); + d->requestLayout(); } void QQuickSplitView::itemRemoved(int index, QQuickItem *item) @@ -1430,7 +1444,7 @@ void QQuickSplitView::itemRemoved(int index, QQuickItem *item) d->removeExcessHandles(); d->updateHandleVisibilities(); d->updateFillIndex(); - d->layout(); + d->requestLayout(); } #if QT_CONFIG(accessibility) @@ -1507,7 +1521,7 @@ void QQuickSplitViewAttached::setMinimumWidth(qreal width) return; d->m_minimumWidth = width; - d->layoutView(); + d->requestLayoutView(); emit minimumWidthChanged(); } @@ -1523,7 +1537,7 @@ void QQuickSplitViewAttached::resetMinimumWidth() if (qFuzzyCompare(newEffectiveMinimumWidth, oldEffectiveMinimumWidth)) return; - d->layoutView(); + d->requestLayoutView(); emit minimumWidthChanged(); } @@ -1554,7 +1568,7 @@ void QQuickSplitViewAttached::setMinimumHeight(qreal height) return; d->m_minimumHeight = height; - d->layoutView(); + d->requestLayoutView(); emit minimumHeightChanged(); } @@ -1570,7 +1584,7 @@ void QQuickSplitViewAttached::resetMinimumHeight() if (qFuzzyCompare(newEffectiveMinimumHeight, oldEffectiveMinimumHeight)) return; - d->layoutView(); + d->requestLayoutView(); emit minimumHeightChanged(); } @@ -1608,7 +1622,7 @@ void QQuickSplitViewAttached::setPreferredWidth(qreal width) return; d->m_preferredWidth = width; - d->layoutView(); + d->requestLayoutView(); emit preferredWidthChanged(); } @@ -1626,7 +1640,7 @@ void QQuickSplitViewAttached::resetPreferredWidth() if (qFuzzyCompare(newEffectivePreferredWidth, oldEffectivePreferredWidth)) return; - d->layoutView(); + d->requestLayoutView(); emit preferredWidthChanged(); } @@ -1664,7 +1678,7 @@ void QQuickSplitViewAttached::setPreferredHeight(qreal height) return; d->m_preferredHeight = height; - d->layoutView(); + d->requestLayoutView(); emit preferredHeightChanged(); } @@ -1682,7 +1696,7 @@ void QQuickSplitViewAttached::resetPreferredHeight() if (qFuzzyCompare(newEffectivePreferredHeight, oldEffectivePreferredHeight)) return; - d->layoutView(); + d->requestLayoutView(); emit preferredHeightChanged(); } @@ -1713,7 +1727,7 @@ void QQuickSplitViewAttached::setMaximumWidth(qreal width) return; d->m_maximumWidth = width; - d->layoutView(); + d->requestLayoutView(); emit maximumWidthChanged(); } @@ -1729,7 +1743,7 @@ void QQuickSplitViewAttached::resetMaximumWidth() if (qFuzzyCompare(newEffectiveMaximumWidth, oldEffectiveMaximumWidth)) return; - d->layoutView(); + d->requestLayoutView(); emit maximumWidthChanged(); } @@ -1760,7 +1774,7 @@ void QQuickSplitViewAttached::setMaximumHeight(qreal height) return; d->m_maximumHeight = height; - d->layoutView(); + d->requestLayoutView(); emit maximumHeightChanged(); } @@ -1776,7 +1790,7 @@ void QQuickSplitViewAttached::resetMaximumHeight() if (qFuzzyCompare(newEffectiveMaximumHeight, oldEffectiveMaximumHeight)) return; - d->layoutView(); + d->requestLayoutView(); emit maximumHeightChanged(); } @@ -1811,7 +1825,7 @@ void QQuickSplitViewAttached::setFillWidth(bool fill) d->m_fillWidth = fill; if (d->m_splitView && d->m_splitView->orientation() == Qt::Horizontal) QQuickSplitViewPrivate::get(d->m_splitView)->updateFillIndex(); - d->layoutView(); + d->requestLayoutView(); emit fillWidthChanged(); } @@ -1846,7 +1860,7 @@ void QQuickSplitViewAttached::setFillHeight(bool fill) d->m_fillHeight = fill; if (d->m_splitView && d->m_splitView->orientation() == Qt::Vertical) QQuickSplitViewPrivate::get(d->m_splitView)->updateFillIndex(); - d->layoutView(); + d->requestLayoutView(); emit fillHeightChanged(); } @@ -1881,10 +1895,10 @@ void QQuickSplitViewAttachedPrivate::setView(QQuickSplitView *newView) emit q->viewChanged(); } -void QQuickSplitViewAttachedPrivate::layoutView() +void QQuickSplitViewAttachedPrivate::requestLayoutView() { if (m_splitView) - QQuickSplitViewPrivate::get(m_splitView)->layout(); + QQuickSplitViewPrivate::get(m_splitView)->requestLayout(); } QQuickSplitViewAttachedPrivate *QQuickSplitViewAttachedPrivate::get(QQuickSplitViewAttached *attached) diff --git a/src/quicktemplates2/qquicksplitview_p_p.h b/src/quicktemplates2/qquicksplitview_p_p.h index 1e0368d5..560276f0 100644 --- a/src/quicktemplates2/qquicksplitview_p_p.h +++ b/src/quicktemplates2/qquicksplitview_p_p.h @@ -65,6 +65,7 @@ public: void layoutResizeSplitItems(qreal &usedWidth, qreal &usedHeight, int &indexBeingResizedDueToDrag); void layoutResizeFillItem(QQuickItem *fillItem, qreal &usedWidth, qreal &usedHeight, int indexBeingResizedDueToDrag); void layoutPositionItems(const QQuickItem *fillItem); + void requestLayout(); void layout(); void createHandles(); void createHandleItem(int index); @@ -101,6 +102,8 @@ public: void itemImplicitWidthChanged(QQuickItem *item) override; void itemImplicitHeightChanged(QQuickItem *item) override; + void updatePolish() override; + static QQuickSplitViewPrivate *get(QQuickSplitView *splitView); private: @@ -127,7 +130,7 @@ public: QQuickSplitViewAttachedPrivate(); void setView(QQuickSplitView *newView); - void layoutView(); + void requestLayoutView(); static QQuickSplitViewAttachedPrivate *get(QQuickSplitViewAttached *attached); static const QQuickSplitViewAttachedPrivate *get(const QQuickSplitViewAttached *attached); diff --git a/tests/auto/controls/data/tst_splitview.qml b/tests/auto/controls/data/tst_splitview.qml index 8879c849..40e7dda0 100644 --- a/tests/auto/controls/data/tst_splitview.qml +++ b/tests/auto/controls/data/tst_splitview.qml @@ -187,6 +187,8 @@ TestCase { var item0 = rectangleComponent.createObject(control, { implicitWidth: 25, color: "salmon" }) verify(item0) + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) // The last item fills the width by default, and since there is only one item... compare(item0.x, 0) compare(item0.y, 0) @@ -195,6 +197,8 @@ TestCase { var item1 = rectangleComponent.createObject(control, { implicitWidth: 25, color: "steelblue" }) verify(item1) + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) // Now that a second item has been added, the first item goes back to its preferred (implicit) width. compare(item0.x, 0) compare(item0.y, 0) @@ -218,6 +222,8 @@ TestCase { var item0 = rectangleComponent.createObject(control, { color: "salmon" }) verify(item0) + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) compare(item0.x, 0) compare(item0.y, 0) compare(item0.width, testCase.width) @@ -225,6 +231,8 @@ TestCase { var item1 = rectangleComponent.createObject(control, { color: "steelblue" }) verify(item1) + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) compare(item0.x, 0) compare(item0.y, 0) compare(item0.width, 0) @@ -299,6 +307,8 @@ TestCase { compare(item2.height, testCase.height) item0.SplitView.preferredWidth = 25 + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) compare(item0.x, 0) compare(item0.y, 0) compare(item0.width, 25) @@ -321,6 +331,8 @@ TestCase { compare(item2.height, testCase.height) item0.SplitView.minimumWidth = 50 + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) compare(item0.x, 0) compare(item0.y, 0) compare(item0.width, 50) @@ -343,6 +355,8 @@ TestCase { compare(item2.height, testCase.height) item0.SplitView.preferredWidth = 100 + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) compare(item0.x, 0) compare(item0.y, 0) compare(item0.width, 100) @@ -365,6 +379,8 @@ TestCase { compare(item2.height, testCase.height) item0.SplitView.maximumWidth = 75 + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) compare(item0.x, 0) compare(item0.y, 0) compare(item0.width, 75) @@ -387,6 +403,8 @@ TestCase { compare(item2.height, testCase.height) item1.SplitView.fillWidth = true + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) compare(item0.x, 0) compare(item0.y, 0) compare(item0.width, 75) @@ -696,9 +714,13 @@ TestCase { var splitItem = control.itemAt(data.splitItemIndex) splitItem.SplitView[data.propertyName] = data.propertyValue + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) compareSizes(control, data.expectedGeometriesBefore, "after setting attached property") splitItem.SplitView[data.propertyName] = undefined + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) compareSizes(control, data.expectedGeometriesAfter, "after resetting attached property") } @@ -738,6 +760,8 @@ TestCase { compare(item2.height, testCase.height) control.orientation = Qt.Vertical + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) compare(item0.x, 0) compare(item0.y, 0) compare(item0.width, testCase.width) @@ -1076,6 +1100,8 @@ TestCase { fillItem.SplitView.fillHeight = true // Check the sizes of the items before the drag. + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) compareSizes(control, data.expectedGeometriesBeforeDrag, "before drag") // Drag the handle. @@ -1176,6 +1202,8 @@ TestCase { else control.height = testCase.height + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) compareSizes(control, data.expectedGeometries) } @@ -1230,6 +1258,8 @@ TestCase { if (data.hasOwnProperty("splitItemImplicitHeight")) firstItem.implicitHeight = data.splitItemImplicitHeight + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) compareSizes(control, data.expectedGeometries) } @@ -1322,7 +1352,8 @@ TestCase { verify(control) control.handle = data.handleComponent - + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) compareSizes(control, data.expectedGeometries) } @@ -1427,6 +1458,8 @@ TestCase { control.insertItem(data.insertItemAtIndex, itemToAdd) } + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) compareSizes(control, data.expectedGeometries) } @@ -1524,6 +1557,8 @@ TestCase { itemToHide.visible = false } + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) compareSizes(control, data.expectedGeometries) } @@ -1570,6 +1605,8 @@ TestCase { verify(itemToHide) itemToHide.visible = false } + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) compareSizes(control, data.expectedGeometriesAfterHiding, "after hiding") for (i = 0; i < data.showIndices.length; ++i) { @@ -1577,6 +1614,8 @@ TestCase { verify(itemToShow) itemToShow.visible = true } + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) compareSizes(control, data.expectedGeometriesAfterShowing, "after showing") } @@ -1631,6 +1670,8 @@ TestCase { } control.moveItem(data.moveFromIndex, data.moveToIndex) + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) compareSizes(control, data.expectedGeometriesAfterMoving, "after moving") for (i = 0; i < data.showIndices.length; ++i) { @@ -1638,6 +1679,8 @@ TestCase { verify(itemToShow) itemToShow.visible = true } + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) compareSizes(control, data.expectedGeometriesAfterShowing, "after showing") } @@ -1663,6 +1706,8 @@ TestCase { control.height = control.parent.height - 100 flickable.contentWidth = control.width flickable.contentHeight = control.height + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) var contentXSpy = signalSpyComponent.createObject(flickable, { target: flickable, signalName: "contentXChanged" }) @@ -1688,6 +1733,8 @@ TestCase { control.width = control.parent.width - 100 control.height = 400 var firstItemOriginalHeight = firstItem.height + verify(isPolishScheduled(control)) + verify(waitForItemPolished(control)) // Add some horizontal movement in there as well. mouseDrag(firstHandle, firstHandle.width / 2, firstHandle.height / 2, 50, 100) |