path: root/src/quicktemplates2
diff options
authorMitch Curtis <mitch.curtis@qt.io>2019-04-12 15:21:42 +0200
committerMitch Curtis <mitch.curtis@qt.io>2019-05-03 11:28:26 +0000
commit0525d640cd11ddced2ec418be182c585204fc45f (patch)
tree8337afced03c909c3411f3ab33719520eaba9b12 /src/quicktemplates2
parent7f1d0976d3ac0c6226bef1947a4eafd44b60e5e9 (diff)
Fix MenuItem width not matching Menu's available width
Short version: There are currently two problems with MenuItems: - Mirrored MenuItems don't fill the Menu's available width. - MenuItem does not fill the Menu's available width when changed after Component completion. This patch fixes both of them by listening to geometry changes in both the contentItem and individual menu items, and setting the explicit width of those menu items when either changes. Longer version: The first problem can be seen whenever the MenuItem's implicitWidth changes: - QQmlEngine::retranslate() is called, causing all bindings to be re-evaluated - The MenuItem's font size changes - The MenuItem's icon size changes - etc. We fix this by making Menu listen to the width of each of its MenuItems and call resizeItem() if it doesn't have an explicit width. The second problem can be seen when e.g. resizing a Menu to account for new items that are wider and hence require more space. This can be fixed by listening to width changes in Menu's contentItem, which was actually done in earlier versions but (probably accidentally) removed in 482ecb0f. I had tried to solve both issues by setting the explicit width of MenuItem to the width of its Menu, or undefined if it has none (which means it reverts to its implicit width). However, this does not account for e.g. MenuSeparator and custom items that can be added to Menu - they should also have their width fill the Menu automatically if they don't have an explicit width set. Change-Id: I95dd0da0919a1e297f2e2030da746ff1f1a17644 Fixes: QTBUG-75051 Fixes: QTBUG-75142 Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
Diffstat (limited to 'src/quicktemplates2')
1 files changed, 20 insertions, 4 deletions
diff --git a/src/quicktemplates2/qquickmenu.cpp b/src/quicktemplates2/qquickmenu.cpp
index f91d15a5..aa44e845 100644
--- a/src/quicktemplates2/qquickmenu.cpp
+++ b/src/quicktemplates2/qquickmenu.cpp
@@ -213,6 +213,7 @@ void QQuickMenuPrivate::insertItem(int index, QQuickItem *item)
if (complete)
QQuickItemPrivate::get(item)->addItemChangeListener(this, QQuickItemPrivate::Destroyed | QQuickItemPrivate::Parent);
+ QQuickItemPrivate::get(item)->updateOrAddGeometryChangeListener(this, QQuickGeometryChange::Width);
contentModel->insert(index, item);
QQuickMenuItem *menuItem = qobject_cast<QQuickMenuItem *>(item);
@@ -237,6 +238,7 @@ void QQuickMenuPrivate::removeItem(int index, QQuickItem *item)
QQuickItemPrivate::get(item)->removeItemChangeListener(this, QQuickItemPrivate::Destroyed | QQuickItemPrivate::Parent);
+ QQuickItemPrivate::get(item)->removeItemChangeListener(this, QQuickItemPrivate::Geometry);
@@ -358,10 +360,20 @@ void QQuickMenuPrivate::itemDestroyed(QQuickItem *item)
removeItem(index, item);
-void QQuickMenuPrivate::itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF &)
+void QQuickMenuPrivate::itemGeometryChanged(QQuickItem *item, QQuickGeometryChange, const QRectF &)
- if (complete)
+ if (!complete)
+ return;
+ if (item == contentItem) {
+ // The contentItem's geometry changed, so resize any items
+ // that don't have explicit widths set so that they fill the width of the menu.
+ } else {
+ // The geometry of an item in the menu changed. If the item
+ // doesn't have an explicit width set, make it fill the width of the menu.
+ resizeItem(item);
+ }
QQuickPopupPositioner *QQuickMenuPrivate::getPositioner()
@@ -1382,10 +1394,14 @@ void QQuickMenu::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem)
QQuickPopup::contentItemChange(newItem, oldItem);
- if (oldItem)
+ if (oldItem) {
QQuickItemPrivate::get(oldItem)->removeItemChangeListener(d, QQuickItemPrivate::Children);
- if (newItem)
+ QQuickItemPrivate::get(oldItem)->removeItemChangeListener(d, QQuickItemPrivate::Geometry);
+ }
+ if (newItem) {
QQuickItemPrivate::get(newItem)->addItemChangeListener(d, QQuickItemPrivate::Children);
+ QQuickItemPrivate::get(newItem)->updateOrAddGeometryChangeListener(d, QQuickGeometryChange::Width);
+ }
d->contentItem = newItem;