From 16558ac71509fe51a4cf18f238e4f61b37323fe4 Mon Sep 17 00:00:00 2001 From: Jan Arve Saether <jan-arve.saether@digia.com> Date: Wed, 8 May 2013 17:02:40 +0200 Subject: [PATCH] Return infinity instead of -1 as a default value for max sizes This was a bit inconsistent, because in the case of a Rectangle its Layout.maximumWidth would return -1 by default (which was supposed to be interpreted as infinity) However, since the maximumWidth propagated up to the layout, the layout.Layout.maximumWidth would return 1000000000. Adding two Rectangles to the layout would make layout.Layout.maximumWidth return 2000000000, and adding a third item with Layout.maximumWidth:1 would make layout.Layout.maximumWidth return 2000000001 With this change, since infinity + number = infinity, everything that can grow to infinity will just return infinity. In addition a developer can now more intuitively do comparisons like this: if (value > Layout.minimumWidth && value < Layout.maximumWidth) instead of if ((value == -1 || value > Layout.minimumWidth) && (value != -1 && value < Layout.maximumWidth)) Now, as a bonus, it becomes less consistent to set an attached (min,max) property to -1 in order to reset it to its implicit value. This also fixes a documentation issue with regards to the attached Layout.{min|max}imum{Width|Height} properties. It only told the story correct if the item was not a layout, and updates the docs for the max sizes to mention that it returns Number.POSITIVE_INFINITY Change-Id: Ia638064fd3ed5614d7e496a9b5e4aa8fcb7307f7 Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@digia.com> --- src/layouts/qquickgridlayoutengine.cpp | 5 +- src/layouts/qquicklayout.cpp | 58 +++++++++++++++++----- src/layouts/qquicklayout_p.h | 13 ++--- src/layouts/qquicklinearlayout.cpp | 12 +++-- src/layouts/qquicklinearlayout_p.h | 1 + tests/auto/controls/data/tst_rowlayout.qml | 33 ++++++++---- 6 files changed, 86 insertions(+), 36 deletions(-) diff --git a/src/layouts/qquickgridlayoutengine.cpp b/src/layouts/qquickgridlayoutengine.cpp index e734e9fef..bacfd965b 100644 --- a/src/layouts/qquickgridlayoutengine.cpp +++ b/src/layouts/qquickgridlayoutengine.cpp @@ -204,9 +204,8 @@ Fixed | Layout.fillWidth | Expanding if layout, Fixed if item | } } //--- GATHER MAXIMUM SIZE HINTS --- - // They are always q_declarativeLayoutMaxSize - combineHints(cachedSizeHints[Qt::MaximumSize].rwidth(), q_declarativeLayoutMaxSize); - combineHints(cachedSizeHints[Qt::MaximumSize].rheight(), q_declarativeLayoutMaxSize); + combineHints(cachedSizeHints[Qt::MaximumSize].rwidth(), std::numeric_limits<qreal>::infinity()); + combineHints(cachedSizeHints[Qt::MaximumSize].rheight(), std::numeric_limits<qreal>::infinity()); //--- GATHER DESCENT // ### Not implemented diff --git a/src/layouts/qquicklayout.cpp b/src/layouts/qquicklayout.cpp index 6d36a92e6..d26737e2d 100644 --- a/src/layouts/qquicklayout.cpp +++ b/src/layouts/qquicklayout.cpp @@ -43,6 +43,7 @@ #include <QEvent> #include <QtCore/qcoreapplication.h> #include <QtCore/qnumeric.h> +#include <limits> /*! \qmltype Layout @@ -78,8 +79,8 @@ QQuickLayoutAttached::QQuickLayoutAttached(QObject *parent) m_minimumHeight(0), m_preferredWidth(-1), m_preferredHeight(-1), - m_maximumWidth(-1), - m_maximumHeight(-1), + m_maximumWidth(std::numeric_limits<qreal>::infinity()), + m_maximumHeight(std::numeric_limits<qreal>::infinity()), m_row(-1), m_column(-1), m_rowSpan(1), @@ -101,8 +102,15 @@ QQuickLayoutAttached::QQuickLayoutAttached(QObject *parent) /*! \qmlproperty real Layout::minimumWidth - This property holds the minimum width of an item in a layout. - The default is \c 0. + This property holds the maximum width of an item in a layout. + The default value is the items implicit minimum width. + + If the item is a layout, the implicit minimum width will be the minimum width the layout can + have without any of its items shrink beyond their minimum width. + The implicit minimum width for any other item is \c 0. + + Setting this value to -1 will reset the width back to its implicit minimum width. + \sa preferredWidth \sa maximumWidth @@ -123,8 +131,13 @@ void QQuickLayoutAttached::setMinimumWidth(qreal width) /*! \qmlproperty real Layout::minimumHeight - This property holds the minimum height of an item in a layout. - The default is \c 0. + The default value is the items implicit minimum height. + + If the item is a layout, the implicit minimum height will be the minimum height the layout can + have without any of its items shrink beyond their minimum height. + The implicit minimum height for any other item is \c 0. + + Setting this value to -1 will reset the height back to its implicit minimum height. \sa preferredHeight \sa maximumHeight @@ -188,10 +201,13 @@ void QQuickLayoutAttached::setPreferredHeight(qreal height) \qmlproperty real Layout::maximumWidth This property holds the maximum width of an item in a layout. - The default is \c -1, which means it there is no limit on the maxiumum width. + The default value is the items implicit maximum width. + + If the item is a layout, the implicit maximum width will be the maximum width the layout can + have without any of its items grow beyond their maximum width. + The implicit maximum width for any other item is \c Number.POSITIVE_INFINITE. - \note There is actually a limit on the maximum width, but it's set to such a - large number that the arrangement is virtually the same as if it didn't have a limit. + Setting this value to -1 will reset the width back to its implicit maximum width. \sa minimumWidth \sa preferredWidth @@ -212,11 +228,13 @@ void QQuickLayoutAttached::setMaximumWidth(qreal width) /*! \qmlproperty real Layout::maximumHeight - This property holds the maximum height of an item in a layout. - The default is \c -1, which means it there is no limit on the maxiumum height. + The default value is the items implicit maximum height. - \note There is actually a limit on the maximum height, but it's set to such a - large number that the arrangement is virtually the same as if it didn't have a limit. + If the item is a layout, the implicit maximum height will be the maximum height the layout can + have without any of its items grow beyond their maximum height. + The implicit maximum height for any other item is \c Number.POSITIVE_INFINITE. + + Setting this value to -1 will reset the height back to its implicit maximum height. \sa minimumHeight \sa preferredHeight @@ -389,6 +407,20 @@ void QQuickLayoutAttached::setColumn(int column) \sa column */ + +qreal QQuickLayoutAttached::sizeHint(Qt::SizeHint which, Qt::Orientation orientation) const +{ + qreal result = 0; + if (QQuickLayout *layout = qobject_cast<QQuickLayout *>(item())) { + const QSizeF sz = layout->sizeHint(which); + result = (orientation == Qt::Horizontal ? sz.width() : sz.height()); + } else { + if (which == Qt::MaximumSize) + result = std::numeric_limits<qreal>::infinity(); + } + return result; +} + void QQuickLayoutAttached::invalidateItem() { if (!m_changesNotificationEnabled) diff --git a/src/layouts/qquicklayout_p.h b/src/layouts/qquicklayout_p.h index 8d9464476..8a334677a 100644 --- a/src/layouts/qquicklayout_p.h +++ b/src/layouts/qquicklayout_p.h @@ -50,8 +50,6 @@ QT_BEGIN_NAMESPACE class QQuickLayoutAttached; -static const qreal q_declarativeLayoutMaxSize = 10e8; - #if 0 && !defined(QT_NO_DEBUG) && !defined(QT_NO_DEBUG_OUTPUT) # define quickLayoutDebug QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO).debug #else @@ -77,6 +75,7 @@ public: void componentComplete(); + virtual QSizeF sizeHint(Qt::SizeHint whichSizeHint) const = 0; virtual void invalidate(QQuickItem * childItem = 0); protected: bool event(QEvent *e); @@ -123,10 +122,10 @@ class QQuickLayoutAttached : public QObject public: QQuickLayoutAttached(QObject *object); - qreal minimumWidth() const { return m_minimumWidth; } + qreal minimumWidth() const { return m_minimumWidth < 0 ? sizeHint(Qt::MinimumSize, Qt::Horizontal) : m_minimumWidth; } void setMinimumWidth(qreal width); - qreal minimumHeight() const { return m_minimumHeight; } + qreal minimumHeight() const { return m_minimumHeight < 0 ? sizeHint(Qt::MinimumSize, Qt::Vertical) : m_minimumHeight; } void setMinimumHeight(qreal height); qreal preferredWidth() const { return m_preferredWidth; } @@ -135,10 +134,10 @@ public: qreal preferredHeight() const { return m_preferredHeight; } void setPreferredHeight(qreal width); - qreal maximumWidth() const { return m_maximumWidth; } + qreal maximumWidth() const { return m_maximumWidth < 0 ? sizeHint(Qt::MaximumSize, Qt::Horizontal) : m_maximumWidth; } void setMaximumWidth(qreal width); - qreal maximumHeight() const { return m_maximumHeight; } + qreal maximumHeight() const { return m_maximumHeight < 0 ? sizeHint(Qt::MaximumSize, Qt::Vertical) : m_maximumHeight; } void setMaximumHeight(qreal height); void setMinimumImplicitSize(const QSizeF &sz); @@ -174,6 +173,8 @@ public: return old; } + qreal sizeHint(Qt::SizeHint which, Qt::Orientation orientation) const; + signals: void minimumWidthChanged(); void minimumHeightChanged(); diff --git a/src/layouts/qquicklinearlayout.cpp b/src/layouts/qquicklinearlayout.cpp index c45310027..d5bd503a7 100644 --- a/src/layouts/qquicklinearlayout.cpp +++ b/src/layouts/qquicklinearlayout.cpp @@ -171,6 +171,12 @@ void QQuickGridLayoutBase::setOrientation(Qt::Orientation orientation) invalidate(); } +QSizeF QQuickGridLayoutBase::sizeHint(Qt::SizeHint whichSizeHint) const +{ + Q_D(const QQuickGridLayoutBase); + return d->engine.sizeHint(whichSizeHint, QSizeF()); +} + void QQuickGridLayoutBase::componentComplete() { Q_D(QQuickGridLayoutBase); @@ -241,9 +247,9 @@ void QQuickGridLayoutBase::invalidate(QQuickItem *childItem) QQuickLayoutAttached *info = attachedLayoutObject(this); - const QSizeF min = d->engine.sizeHint(Qt::MinimumSize, QSizeF()); - const QSizeF pref = d->engine.sizeHint(Qt::PreferredSize, QSizeF()); - const QSizeF max = d->engine.sizeHint(Qt::MaximumSize, QSizeF()); + const QSizeF min = sizeHint(Qt::MinimumSize); + const QSizeF pref = sizeHint(Qt::PreferredSize); + const QSizeF max = sizeHint(Qt::MaximumSize); const bool old = info->setChangesNotificationEnabled(false); info->setMinimumImplicitSize(min); diff --git a/src/layouts/qquicklinearlayout_p.h b/src/layouts/qquicklinearlayout_p.h index f1a9b39f5..76cc206b9 100644 --- a/src/layouts/qquicklinearlayout_p.h +++ b/src/layouts/qquicklinearlayout_p.h @@ -68,6 +68,7 @@ public: void invalidate(QQuickItem *childItem = 0); Qt::Orientation orientation() const; void setOrientation(Qt::Orientation orientation); + QSizeF sizeHint(Qt::SizeHint whichSizeHint) const Q_DECL_OVERRIDE; protected: void updateLayoutItems(); diff --git a/tests/auto/controls/data/tst_rowlayout.qml b/tests/auto/controls/data/tst_rowlayout.qml index 1b9573e0c..6e2d1334a 100644 --- a/tests/auto/controls/data/tst_rowlayout.qml +++ b/tests/auto/controls/data/tst_rowlayout.qml @@ -129,6 +129,8 @@ Item { tmp.width = 30 compare(tmp.r1.width, 10); compare(tmp.r2.width, 20); + compare(tmp.Layout.minimumWidth, 0) + compare(tmp.Layout.maximumWidth, Number.POSITIVE_INFINITY) tmp.destroy() } @@ -393,8 +395,8 @@ Item { function test_sizeHintNormalization_data() { return [ - { tag: "fallbackValues", widthHints: [-1, -1, -1], expected:[0,42,1000000000], implicitWidth: 42}, - { tag: "acceptZeroWidths", widthHints: [0, 0, 0], expected:[0,0,0], implicitWidth: 42}, + { tag: "fallbackValues", widthHints: [-1, -1, -1], implicitWidth: 42, expected:[0,42,Number.POSITIVE_INFINITY]}, + { tag: "acceptZeroWidths", widthHints: [0, 0, 0], implicitWidth: 42, expected:[0,0,0]}, { tag: "123", widthHints: [1,2,3], expected:[1,2,3]}, { tag: "132", widthHints: [1,3,2], expected:[1,2,2]}, { tag: "213", widthHints: [2,1,3], expected:[2,2,3]}, @@ -402,12 +404,12 @@ Item { { tag: "321", widthHints: [3,2,1], expected:[1,1,1]}, { tag: "312", widthHints: [3,1,2], expected:[2,2,2]}, - { tag: "1i3", widthHints: [1,-1,3], expected:[1,2,3], implicitWidth: 2}, - { tag: "1i2", widthHints: [1,-1,2], expected:[1,2,2], implicitWidth: 3}, - { tag: "2i3", widthHints: [2,-1,3], expected:[2,2,3], implicitWidth: 1}, - { tag: "2i1", widthHints: [2,-1,1], expected:[1,1,1], implicitWidth: 3}, - { tag: "3i1", widthHints: [3,-1,1], expected:[1,1,1], implicitWidth: 2}, - { tag: "3i2", widthHints: [3,-1,2], expected:[2,2,2], implicitWidth: 1}, + { tag: "1i3", widthHints: [1,-1,3], implicitWidth: 2, expected:[1,2,3]}, + { tag: "1i2", widthHints: [1,-1,2], implicitWidth: 3, expected:[1,2,2]}, + { tag: "2i3", widthHints: [2,-1,3], implicitWidth: 1, expected:[2,2,3]}, + { tag: "2i1", widthHints: [2,-1,1], implicitWidth: 3, expected:[1,1,1]}, + { tag: "3i1", widthHints: [3,-1,1], implicitWidth: 2, expected:[1,1,1]}, + { tag: "3i2", widthHints: [3,-1,2], implicitWidth: 1, expected:[2,2,2]}, ]; } @@ -495,15 +497,19 @@ Item { child.Layout.preferredWidth = -1 compare(itemSizeHints(layout), [0, 0, 3]) child.Layout.maximumWidth = -1 - compare(itemSizeHints(layout), [0, 0, 1000000000]) + compare(itemSizeHints(layout), [0, 0, Number.POSITIVE_INFINITY]) + layout.Layout.maximumWidth = 1000 + compare(itemSizeHints(layout), [0, 0, 1000]) + layout.Layout.maximumWidth = -1 + compare(itemSizeHints(layout), [0, 0, Number.POSITIVE_INFINITY]) layout.implicitWidthChangedCount = 0 child.Layout.minimumWidth = 10 - compare(itemSizeHints(layout), [10, 10, 1000000000]) + compare(itemSizeHints(layout), [10, 10, Number.POSITIVE_INFINITY]) compare(layout.implicitWidthChangedCount, 1) child.Layout.preferredWidth = 20 - compare(itemSizeHints(layout), [10, 20, 1000000000]) + compare(itemSizeHints(layout), [10, 20, Number.POSITIVE_INFINITY]) compare(layout.implicitWidthChangedCount, 2) child.Layout.maximumWidth = 30 @@ -518,6 +524,11 @@ Item { compare(itemSizeHints(layout), [10, 20, 30]) compare(layout.implicitWidthChangedCount, 4) + layout.Layout.maximumWidth = 29 + compare(layout.Layout.maximumWidth, 29) + layout.Layout.maximumWidth = -1 + compare(layout.Layout.maximumWidth, 30) + layout.destroy() } Component { -- GitLab