aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Arve Sæther <jan-arve.saether@qt.io>2022-09-02 14:24:19 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2022-09-28 21:13:56 +0000
commit210f7655bcb621a1702f755787d1907bb6ab75cc (patch)
tree3fdfe834112efcfe35bba56cd2e888c025737be2
parent84ff843c80e0f0b3445a89ea3bf2469c5b102733 (diff)
Do not listen to baselineOffset changes unless really needed
For some controls, (e.g. TextInput and Text) we can get changes in baseline offset when they change their height. These changes will invalidate the layout and generate a polish event. This means that during a rearrange of a layout with TextInput children, it might change the height of its children. This might change the baselineOffset of these children, which again will cause the layout to have to be invalidated (and rearranged again) This double-loop is unnecessary if the layout is not supposed to align these items by their baselines, so we add some conditions to see if we really need to connect to the baselineOffsetChanged() signal. This also fixes a bug observed in the color dialog, where the semi-recursiveness described above lead to a problem with that the alpha TextField of the RGBA color input was *not* laid out by the parent RowLayout Fixes: QTBUG-105899 Change-Id: If66b4bbde6a37c962b157e166c883ba20ff24c21 Reviewed-by: Oliver Eftevaag <oliver.eftevaag@qt.io> (cherry picked from commit 1fe641c50defed77590e2eba9d33e6c3746fa832) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/quicklayouts/qquicklayout.cpp16
-rw-r--r--src/quicklayouts/qquicklayout_p.h2
-rw-r--r--src/quicklayouts/qquicklinearlayout.cpp1
-rw-r--r--tests/auto/quick/qquicklayouts/data/tst_gridlayout.qml50
4 files changed, 67 insertions, 2 deletions
diff --git a/src/quicklayouts/qquicklayout.cpp b/src/quicklayouts/qquicklayout.cpp
index 7d99c0c37e..74167db3e7 100644
--- a/src/quicklayouts/qquicklayout.cpp
+++ b/src/quicklayouts/qquicklayout.cpp
@@ -730,6 +730,18 @@ void QQuickLayout::componentComplete()
d->m_isReady = true;
}
+void QQuickLayout::maybeSubscribeToBaseLineOffsetChanges(QQuickItem *item)
+{
+ QQuickLayoutAttached *info = attachedLayoutObject(item, false);
+ if (info) {
+ if (info->alignment() == Qt::AlignBaseline && static_cast<QQuickLayout*>(item->parentItem()) == this) {
+ qmlobject_connect(item, QQuickItem, SIGNAL(baselineOffsetChanged(qreal)), this, QQuickLayout, SLOT(invalidateSenderItem()));
+ } else {
+ qmlobject_disconnect(item, QQuickItem, SIGNAL(baselineOffsetChanged(qreal)), this, QQuickLayout, SLOT(invalidateSenderItem()));
+ }
+ }
+}
+
void QQuickLayout::invalidate(QQuickItem * /*childItem*/)
{
Q_D(QQuickLayout);
@@ -811,7 +823,7 @@ void QQuickLayout::itemChange(ItemChange change, const ItemChangeData &value)
if (change == ItemChildAddedChange) {
Q_D(QQuickLayout);
QQuickItem *item = value.item;
- qmlobject_connect(item, QQuickItem, SIGNAL(baselineOffsetChanged(qreal)), this, QQuickLayout, SLOT(invalidateSenderItem()));
+ maybeSubscribeToBaseLineOffsetChanges(item);
QQuickItemPrivate::get(item)->addItemChangeListener(this, changeTypes);
d->m_hasItemChangeListeners = true;
qCDebug(lcQuickLayouts) << "ChildAdded" << item;
@@ -819,7 +831,7 @@ void QQuickLayout::itemChange(ItemChange change, const ItemChangeData &value)
invalidate();
} else if (change == ItemChildRemovedChange) {
QQuickItem *item = value.item;
- qmlobject_disconnect(item, QQuickItem, SIGNAL(baselineOffsetChanged(qreal)), this, QQuickLayout, SLOT(invalidateSenderItem()));
+ maybeSubscribeToBaseLineOffsetChanges(item);
QQuickItemPrivate::get(item)->removeItemChangeListener(this, changeTypes);
qCDebug(lcQuickLayouts) << "ChildRemoved" << item;
if (isReady())
diff --git a/src/quicklayouts/qquicklayout_p.h b/src/quicklayouts/qquicklayout_p.h
index 69ba3a79bf..40ee74614a 100644
--- a/src/quicklayouts/qquicklayout_p.h
+++ b/src/quicklayouts/qquicklayout_p.h
@@ -95,6 +95,8 @@ public:
void itemDestroyed(QQuickItem *item) override;
void itemVisibilityChanged(QQuickItem *item) override;
+ void maybeSubscribeToBaseLineOffsetChanges(QQuickItem *item);
+
Q_INVOKABLE void _q_dumpLayoutTree() const;
void dumpLayoutTreeRecursive(int level, QString &buf) const;
diff --git a/src/quicklayouts/qquicklinearlayout.cpp b/src/quicklayouts/qquicklinearlayout.cpp
index 1ca3499bd9..569d48cf69 100644
--- a/src/quicklayouts/qquicklinearlayout.cpp
+++ b/src/quicklayouts/qquicklinearlayout.cpp
@@ -281,6 +281,7 @@ void QQuickGridLayoutBase::setAlignment(QQuickItem *item, Qt::Alignment alignmen
{
Q_D(QQuickGridLayoutBase);
d->engine.setAlignment(item, alignment);
+ maybeSubscribeToBaseLineOffsetChanges(item);
}
QQuickGridLayoutBase::~QQuickGridLayoutBase()
diff --git a/tests/auto/quick/qquicklayouts/data/tst_gridlayout.qml b/tests/auto/quick/qquicklayouts/data/tst_gridlayout.qml
index 9ecad57ffc..261b8a9a8e 100644
--- a/tests/auto/quick/qquicklayouts/data/tst_gridlayout.qml
+++ b/tests/auto/quick/qquicklayouts/data/tst_gridlayout.qml
@@ -539,6 +539,56 @@ Item {
tryCompare(layout.children[4], "y", 60);
}
+ Component {
+ id: layout_alignBaseline_Component
+ GridLayout {
+ columns: 2
+ columnSpacing: 0
+ rowSpacing: 0
+ TextInput {
+ property var itemRect: [x, y, width, height]
+ text: "red"
+ baselineOffset: 7
+ color: "red"
+ verticalAlignment: TextInput.AlignVCenter
+ Layout.preferredWidth: 50
+ Layout.preferredHeight: 10
+ Layout.fillHeight: true
+ }
+ TextInput {
+ property var itemRect: [x, y, width, height]
+ text: "green"
+ baselineOffset: 7
+ color: "green"
+ verticalAlignment: TextInput.AlignVCenter
+ Layout.preferredWidth: 50
+ Layout.preferredHeight: 10
+ Layout.fillHeight: true
+ }
+
+ }
+ }
+
+ function test_alignBaseline_dont_always_invalidate()
+ {
+ var layout = createTemporaryObject(layout_alignBaseline_Component, container);
+ waitForItemPolished(layout)
+ layout.height = 20
+ // Adjusting height on an item that uses Qt.AlignBaseline might adjust the baseline
+ // Test if we don't get excessive number of polish() events because of baseline changes
+ // (In this case, we don't want to align by the baseline)
+ compare(isPolishScheduled(layout), false)
+ waitForItemPolished(layout)
+ var c0 = layout.children[0]
+ c0.Layout.alignment = Qt.AlignBaseline
+ var c1 = layout.children[1]
+ c1.Layout.alignment = Qt.AlignBaseline
+
+ // We want to align by baseline => expect a polish event
+ compare(isPolishScheduled(layout), true)
+ waitForItemPolished(layout)
+ }
+
Component {
id: layout_rightToLeft_Component