aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMitch Curtis <mitch.curtis@qt.io>2018-12-06 10:59:45 +0100
committerMitch Curtis <mitch.curtis@qt.io>2019-01-08 13:15:00 +0000
commitce9940ca550d70931248a98fc4d47f10959a9a9e (patch)
treebac7721f3b0dd7d2e7309b1c6efa087937f3d9e4
parent8bf2dacabf0a9e5d37df6a202ef0a337995fc8ed (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.cpp70
-rw-r--r--src/quicktemplates2/qquicksplitview_p_p.h5
-rw-r--r--tests/auto/controls/data/tst_splitview.qml49
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)