summaryrefslogtreecommitdiff
path: root/src/layouts
diff options
context:
space:
mode:
authorJan Arve Saether <jan-arve.saether@digia.com>2013-05-31 15:38:00 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-06-04 10:03:34 +0200
commit4051e69852cd648942e03cd36e14c2c34124c19f (patch)
treea3e3652d46504adda9fac18e255363014e611322 /src/layouts
parent86df745c940cd54ca9c7b11347ee4a80b7a5577c (diff)
downloadqtquickcontrols-4051e69852cd648942e03cd36e14c2c34124c19f.tar.gz
Fixed some bugs in how effective size hints were calculated
Do not bound explicit preferred size with implicit sizes. This means that if Layout.preferredWidth was *explicitly* set to 50, and Layout.maximumWidth had the implicit value 20, the effective maximum width would be expanded to 50 in order to not disregard the explicitly set preferred width. (covered by the tag "expandMaxToExplicitPref" in test_sizeHint) Note that this doesn't break any autotests, but the row layout autotest was slightly changed to be able to add the new test cases. This should make the behavior match the behavior of QGraphicsGridLayout and QGraphicsLinearLayout Change-Id: Ia23c8ef909827f14349906c003c72bb83689ef9a Reviewed-by: Caroline Chao <caroline.chao@digia.com> Reviewed-by: Jens Bache-Wiig <jens.bache-wiig@digia.com>
Diffstat (limited to 'src/layouts')
-rw-r--r--src/layouts/qquickgridlayoutengine.cpp95
-rw-r--r--src/layouts/qquicklayout_p.h16
2 files changed, 84 insertions, 27 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();