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-27 21:32:17 +0000
commit7ade61593424910a63085cef8203feb4bae4ec06 (patch)
treefad2b8420e7f61c86069e365fbe7321f1f8dac04
parent74e7f9ccc5a16103ac0c667ce4b49503b55d377b (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 701a83de42..80fea6923a 100644
--- a/src/quicklayouts/qquicklayout.cpp
+++ b/src/quicklayouts/qquicklayout.cpp
@@ -790,6 +790,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);
@@ -864,7 +876,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;
@@ -872,7 +884,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 921be97f44..2eb1c2c362 100644
--- a/src/quicklayouts/qquicklayout_p.h
+++ b/src/quicklayouts/qquicklayout_p.h
@@ -121,6 +121,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 c7b0e66e04..1a8cc4e7ae 100644
--- a/src/quicklayouts/qquicklinearlayout.cpp
+++ b/src/quicklayouts/qquicklinearlayout.cpp
@@ -318,6 +318,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 1df04a11e8..52ad3b478d 100644
--- a/tests/auto/quick/qquicklayouts/data/tst_gridlayout.qml
+++ b/tests/auto/quick/qquicklayouts/data/tst_gridlayout.qml
@@ -586,6 +586,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