summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/layouts/qquickgridlayoutengine.cpp95
-rw-r--r--src/layouts/qquicklayout_p.h16
-rw-r--r--tests/auto/controls/data/tst_rowlayout.qml21
3 files changed, 97 insertions, 35 deletions
diff --git a/src/layouts/qquickgridlayoutengine.cpp b/src/layouts/qquickgridlayoutengine.cpp
index bacfd965..7f65d0d5 100644
--- a/src/layouts/qquickgridlayoutengine.cpp
+++ b/src/layouts/qquickgridlayoutengine.cpp
@@ -98,14 +98,62 @@ static inline void combineHints(qreal &current, qreal fallbackHint)
current = fallbackHint;
}
+static inline void combineSize(QSizeF &result, const QSizeF &fallbackSize)
+{
+ combineHints(result.rwidth(), fallbackSize.width());
+ combineHints(result.rheight(), fallbackSize.height());
+}
+
+static inline void combineImplicitHints(QQuickLayoutAttached *info, Qt::SizeHint which, QSizeF *size)
+{
+ if (!info) return;
+
+ Q_ASSERT(which == Qt::MinimumSize || which == Qt::MaximumSize);
+
+ const QSizeF constraint(which == Qt::MinimumSize
+ ? QSizeF(info->minimumWidth(), info->minimumHeight())
+ : QSizeF(info->maximumWidth(), info->maximumHeight()));
+
+ if (!info->isExtentExplicitlySet(Qt::Horizontal, which))
+ combineHints(size->rwidth(), constraint.width());
+ if (!info->isExtentExplicitlySet(Qt::Vertical, which))
+ combineHints(size->rheight(), constraint.height());
+}
+
/*!
\internal
Note: Can potentially return the attached QQuickLayoutAttached object through \a attachedInfo.
It is like this is because it enables it to be reused.
+
+ The goal of this function is to return the effective minimum, preferred and maximum size hints
+ that the layout will use for this item.
+ This function takes care of gathering all explicitly set size hints, normalizes them so
+ that min < pref < max.
+ Further, the hints _not_explicitly_ set will then be initialized with the implicit size hints,
+ which is usually derived from the content of the layouts (or items).
+
+ The following table illustrates the preference of the properties used for measuring layout
+ items. If present, the USER properties will be preferred. If USER properties are not present,
+ the HINT properties will be preferred. Finally, the FALLBACK properties will be used as an
+ ultimate fallback.
+
+ Note that one can query if the value of Layout.minimumWidth or Layout.maximumWidth has been
+ explicitly or implicitly set with QQuickLayoutAttached::isExtentExplicitlySet(). This
+ determines if it should be used as a USER or as a HINT value.
+
+
+ | *Minimum* | *Preferred* | *Maximum* |
++----------------+----------------------+-----------------------+--------------------------+
+|USER (explicit) | Layout.minimumWidth | Layout.preferredWidth | Layout.maximumWidth |
+|HINT (implicit) | Layout.minimumWidth | implicitWidth | Layout.maximumWidth |
+|FALLBACK | 0 | width | Number.POSITIVE_INFINITY |
++----------------+----------------------+-----------------------+--------------------------+
*/
void QQuickGridLayoutItem::effectiveSizeHints_helper(QQuickItem *item, QSizeF *cachedSizeHints, QQuickLayoutAttached **attachedInfo, bool useFallbackToWidthOrHeight)
{
+ for (int i = 0; i < Qt::NSizeHints; ++i)
+ cachedSizeHints[i] = QSizeF();
QQuickLayoutAttached *info = attachedLayoutObject(item, false);
// First, retrieve the user-specified hints from the attached "Layout." properties
if (info) {
@@ -123,16 +171,16 @@ void QQuickGridLayoutItem::effectiveSizeHints_helper(QQuickItem *item, QSizeF *c
for (int i = 0; i < NSizes; ++i) {
SizeGetter getter = horGetters.call[i];
Q_ASSERT(getter);
- cachedSizeHints[i].setWidth((info->*getter)());
+
+ if (info->isExtentExplicitlySet(Qt::Horizontal, (Qt::SizeHint)i))
+ cachedSizeHints[i].setWidth((info->*getter)());
+
getter = verGetters.call[i];
Q_ASSERT(getter);
- cachedSizeHints[i].setHeight((info->*getter)());
+ if (info->isExtentExplicitlySet(Qt::Vertical, (Qt::SizeHint)i))
+ cachedSizeHints[i].setHeight((info->*getter)());
}
- } else {
- for (int i = 0; i < NSizes; ++i)
- cachedSizeHints[i] = QSize();
}
- cachedSizeHints[Qt::MinimumDescent] = QSize(); //### FIXME when baseline support is added
QSizeF &minS = cachedSizeHints[Qt::MinimumSize];
QSizeF &prefS = cachedSizeHints[Qt::PreferredSize];
@@ -144,23 +192,21 @@ void QQuickGridLayoutItem::effectiveSizeHints_helper(QQuickItem *item, QSizeF *c
// to: [10, 10, 60]
normalizeHints(minS.rwidth(), prefS.rwidth(), maxS.rwidth(), descentS.rwidth());
normalizeHints(minS.rheight(), prefS.rheight(), maxS.rheight(), descentS.rheight());
-/*
- The following table illustrates the preference of the properties used for measuring layout
- items. If present, the USER properties will be preferred. If USER properties are not present,
- the HINT 1 properties will be preferred. Finally, the HINT 2 properties will be used as an
- ultimate fallback.
-
- | USER | HINT 1 | HINT 2
- -----+--------------------------------+-------------------+-------
- MIN | Layout.minimumWidth | | 0
- PREF | Layout.preferredWidth | implicitWidth | width
- MAX | Layout.maximumWidth | | 1000000000 (-1)
- -----+--------------------------------+-------------------+--------
-Fixed | Layout.fillWidth | Expanding if layout, Fixed if item |
-
-*/
+
+ // All explicit values gathered, now continue to gather the implicit sizes
+
+ //--- GATHER MAXIMUM SIZE HINTS ---
+ combineImplicitHints(info, Qt::MaximumSize, &maxS);
+ combineSize(maxS, QSizeF(std::numeric_limits<qreal>::infinity(), std::numeric_limits<qreal>::infinity()));
+ // implicit max or min sizes should not limit an explicitly set preferred size
+ expandSize(maxS, prefS);
+ expandSize(maxS, minS);
+
//--- GATHER MINIMUM SIZE HINTS ---
- // They are always 0
+ combineImplicitHints(info, Qt::MinimumSize, &minS);
+ expandSize(minS, QSizeF(0,0));
+ boundSize(minS, prefS);
+ boundSize(minS, maxS);
//--- GATHER PREFERRED SIZE HINTS ---
// First, from implicitWidth/Height
@@ -203,17 +249,12 @@ Fixed | Layout.fillWidth | Expanding if layout, Fixed if item |
item->blockSignals(false);
}
}
- //--- GATHER MAXIMUM SIZE HINTS ---
- combineHints(cachedSizeHints[Qt::MaximumSize].rwidth(), std::numeric_limits<qreal>::infinity());
- combineHints(cachedSizeHints[Qt::MaximumSize].rheight(), std::numeric_limits<qreal>::infinity());
//--- GATHER DESCENT
// ### Not implemented
// Normalize again after the implicit hints have been gathered
- expandSize(minS, QSizeF(0,0));
- boundSize(minS, maxS);
expandSize(prefS, minS);
boundSize(prefS, maxS);
diff --git a/src/layouts/qquicklayout_p.h b/src/layouts/qquicklayout_p.h
index 8a334677..0239739a 100644
--- a/src/layouts/qquicklayout_p.h
+++ b/src/layouts/qquicklayout_p.h
@@ -175,6 +175,22 @@ public:
qreal sizeHint(Qt::SizeHint which, Qt::Orientation orientation) const;
+ bool isExtentExplicitlySet(Qt::Orientation o, Qt::SizeHint whichSize) const
+ {
+ switch (whichSize) {
+ case Qt::MinimumSize:
+ return o == Qt::Horizontal ? m_isMinimumWidthSet : m_isMinimumHeightSet;
+ case Qt::MaximumSize:
+ return o == Qt::Horizontal ? m_isMaximumWidthSet : m_isMaximumHeightSet;
+ case Qt::PreferredSize:
+ return true; // Layout.preferredWidth is always explicitly set
+ case Qt::MinimumDescent: // Not supported
+ case Qt::NSizeHints:
+ return false;
+ }
+ return false;
+ }
+
signals:
void minimumWidthChanged();
void minimumHeightChanged();
diff --git a/tests/auto/controls/data/tst_rowlayout.qml b/tests/auto/controls/data/tst_rowlayout.qml
index 458a2885..e92dad47 100644
--- a/tests/auto/controls/data/tst_rowlayout.qml
+++ b/tests/auto/controls/data/tst_rowlayout.qml
@@ -459,6 +459,12 @@ Item {
{ tag: "propagateMaximumWidth", layoutHints: [10, 20, -1], childHints: [11, 21, 30], expected:[10, 20, 30]},
{ tag: "propagateAll", layoutHints: [-1, -1, -1], childHints: [10, 20, 30], expected:[10, 20, 30]},
{ tag: "propagateCrazy", layoutHints: [-1, -1, -1], childHints: [40, 21, 30], expected:[30, 30, 30]},
+ { tag: "expandMinToExplicitPref", layoutHints: [-1, 1, -1], childHints: [11, 21, 31], expected:[ 1, 1, 31]},
+ { tag: "expandMaxToExplicitPref", layoutHints: [-1, 99, -1], childHints: [11, 21, 31], expected:[11, 99, 99]},
+ { tag: "expandAllToExplicitMin", layoutHints: [99, -1, -1], childHints: [11, 21, 31], expected:[99, 99, 99]},
+ { tag: "expandPrefToExplicitMin", layoutHints: [24, -1, -1], childHints: [11, 21, 31], expected:[24, 24, 31]},
+ { tag: "boundPrefToExplicitMax", layoutHints: [-1, -1, 19], childHints: [11, 21, 31], expected:[11, 19, 19]},
+ { tag: "boundAllToExplicitMax", layoutHints: [-1, -1, 9], childHints: [11, 21, 31], expected:[ 9, 9, 9]},
];
}
@@ -468,22 +474,21 @@ Item {
function test_sizeHint(data) {
var layout = layout_sizeHint_Component.createObject(container)
- layout.Layout.minimumWidth = data.layoutHints[0]
- layout.Layout.preferredWidth = data.layoutHints[1]
- layout.Layout.maximumWidth = data.layoutHints[2]
- var child = layout.children[0].children[0]
+ var grid = layout.children[0]
+ grid.Layout.minimumWidth = data.layoutHints[0]
+ grid.Layout.preferredWidth = data.layoutHints[1]
+ grid.Layout.maximumWidth = data.layoutHints[2]
+
+ var child = grid.children[0]
if (data.implicitWidth !== undefined) {
child.implicitWidth = data.implicitWidth
}
-
child.Layout.minimumWidth = data.childHints[0]
child.Layout.preferredWidth = data.childHints[1]
child.Layout.maximumWidth = data.childHints[2]
- var grid = layout.children[0]
- var preferredWidth = layout.Layout.preferredWidth >= 0 ? layout.Layout.preferredWidth : layout.implicitWidth
- var effectiveSizeHintResult = [layout.Layout.minimumWidth, preferredWidth, layout.Layout.maximumWidth]
+ var effectiveSizeHintResult = [layout.Layout.minimumWidth, layout.implicitWidth, layout.Layout.maximumWidth]
compare(effectiveSizeHintResult, data.expected)
layout.destroy()
}