From 52e1044a1a22525b960d9e1d336ac06c4f39e6d5 Mon Sep 17 00:00:00 2001 From: Jan Arve Saether Date: Fri, 2 Jan 2015 15:06:24 +0100 Subject: Add support for Layout margins Currently, the way to achieve this is to make a proxy item in a layout: RowLayout { Item { Text { anchors.fill: parent anchors.margins: 9 } } } using Layout margins you can now skip the proxy item and instead write: RowLayout { Text { Layout.margins: 9 } } Note that this is not the same as margins in the QLayout world, as this only controls the margins between the layout container and its items. This feature adds margins to each individual item inside the layout The real logic is done by the container classes: Layouts has the additional logic to adhere to them. SplitView will be done in a separate commit. Task-number: QTBUG-39724 Task-number: QTBUG-41559 Change-Id: I9c5c2a1e0ee43c1200b62009216c9f64d2875baf Reviewed-by: J-P Nurmi --- src/layouts/doc/src/qtquicklayouts-overview.qdoc | 2 +- src/layouts/doc/src/qtquicklayouts.qdoc | 4 +- src/layouts/doc/src/snippets/windowconstraints.qml | 2 +- src/layouts/layouts.pro | 2 +- src/layouts/plugin.cpp | 4 +- src/layouts/plugins.qmltypes | 11 +- src/layouts/qquickgridlayoutengine.cpp | 8 + src/layouts/qquickgridlayoutengine_p.h | 6 +- src/layouts/qquicklayout.cpp | 178 ++++++++++++++++++++- src/layouts/qquicklayout_p.h | 41 +++++ 10 files changed, 246 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/layouts/doc/src/qtquicklayouts-overview.qdoc b/src/layouts/doc/src/qtquicklayouts-overview.qdoc index c1f43256..7a124701 100644 --- a/src/layouts/doc/src/qtquicklayouts-overview.qdoc +++ b/src/layouts/doc/src/qtquicklayouts-overview.qdoc @@ -38,7 +38,7 @@ The QML types can be imported into your application using the following import statement in your \c {.qml} file. \code - import QtQuick.Layouts 1.1 + import QtQuick.Layouts 1.2 \endcode \section1 Key Features diff --git a/src/layouts/doc/src/qtquicklayouts.qdoc b/src/layouts/doc/src/qtquicklayouts.qdoc index 99d14e86..bda3236a 100644 --- a/src/layouts/doc/src/qtquicklayouts.qdoc +++ b/src/layouts/doc/src/qtquicklayouts.qdoc @@ -26,7 +26,7 @@ ****************************************************************************/ /*! - \qmlmodule QtQuick.Layouts 1.1 + \qmlmodule QtQuick.Layouts 1.2 \title Qt Quick Layouts QML Types \ingroup qmlmodules \brief Provides QML types for arranging QML items in a user interface. @@ -40,7 +40,7 @@ following import statement in your .qml file. \code - import QtQuick.Layouts 1.1 + import QtQuick.Layouts 1.2 \endcode */ diff --git a/src/layouts/doc/src/snippets/windowconstraints.qml b/src/layouts/doc/src/snippets/windowconstraints.qml index 956989a3..e224b54f 100644 --- a/src/layouts/doc/src/snippets/windowconstraints.qml +++ b/src/layouts/doc/src/snippets/windowconstraints.qml @@ -40,7 +40,7 @@ import QtQuick 2.2 import QtQuick.Controls 1.2 -import QtQuick.Layouts 1.0 +import QtQuick.Layouts 1.2 ApplicationWindow { //! [binddefaultsize] diff --git a/src/layouts/layouts.pro b/src/layouts/layouts.pro index 9d21c7a1..3ef18f85 100644 --- a/src/layouts/layouts.pro +++ b/src/layouts/layouts.pro @@ -1,7 +1,7 @@ CXX_MODULE = qml TARGET = qquicklayoutsplugin TARGETPATH = QtQuick/Layouts -IMPORT_VERSION = 1.1 +IMPORT_VERSION = 1.2 QT *= qml-private quick-private gui-private core-private diff --git a/src/layouts/plugin.cpp b/src/layouts/plugin.cpp index 243eea08..52af126c 100644 --- a/src/layouts/plugin.cpp +++ b/src/layouts/plugin.cpp @@ -52,7 +52,9 @@ public: qmlRegisterType(uri, 1, 0, "ColumnLayout"); qmlRegisterType(uri, 1, 0, "GridLayout"); qmlRegisterUncreatableType(uri, 1, 0, "Layout", - QLatin1String("Do not create objects of type Layout")); + QStringLiteral("Do not create objects of type Layout")); + qmlRegisterUncreatableType(uri, 1, 2, "Layout", + QStringLiteral("Do not create objects of type Layout")); qmlRegisterRevision(uri, 1, 1); } }; diff --git a/src/layouts/plugins.qmltypes b/src/layouts/plugins.qmltypes index 20a8f932..637210e2 100644 --- a/src/layouts/plugins.qmltypes +++ b/src/layouts/plugins.qmltypes @@ -4,7 +4,7 @@ import QtQuick.tooling 1.1 // It is used for QML tooling purposes only. // // This file was auto-generated by: -// 'qmlplugindump.exe -nonrelocatable QtQuick.Layouts 1.1' +// 'qmlplugindump -nonrelocatable QtQuick.Layouts 1.2' Module { Component { @@ -44,9 +44,9 @@ Module { name: "QQuickLayout" defaultProperty: "data" prototype: "QQuickItem" - exports: ["QtQuick.Layouts/Layout 1.0"] + exports: ["QtQuick.Layouts/Layout 1.0", "QtQuick.Layouts/Layout 1.2"] isCreatable: false - exportMetaObjectRevisions: [0] + exportMetaObjectRevisions: [0, 0] attachedType: "QQuickLayoutAttached" } Component { @@ -65,6 +65,11 @@ Module { Property { name: "rowSpan"; type: "int" } Property { name: "columnSpan"; type: "int" } Property { name: "alignment"; type: "Qt::Alignment" } + Property { name: "margins"; type: "double" } + Property { name: "leftMargin"; type: "double" } + Property { name: "topMargin"; type: "double" } + Property { name: "rightMargin"; type: "double" } + Property { name: "bottomMargin"; type: "double" } } Component { name: "QQuickLinearLayout" diff --git a/src/layouts/qquickgridlayoutengine.cpp b/src/layouts/qquickgridlayoutengine.cpp index b006a275..fc11c0fc 100644 --- a/src/layouts/qquickgridlayoutengine.cpp +++ b/src/layouts/qquickgridlayoutengine.cpp @@ -256,6 +256,14 @@ void QQuickGridLayoutItem::effectiveSizeHints_helper(QQuickItem *item, QSizeF *c const qreal minimumDescent = minS.height() - item->baselineOffset(); descentS.setHeight(minimumDescent); + if (info) { + QMarginsF margins = info->qMargins(); + QSizeF extraMargins(margins.left() + margins.right(), margins.top() + margins.bottom()); + minS += extraMargins; + prefS += extraMargins; + maxS += extraMargins; + descentS += extraMargins; + } if (attachedInfo) *attachedInfo = info; } diff --git a/src/layouts/qquickgridlayoutengine_p.h b/src/layouts/qquickgridlayoutengine_p.h index fb6949bc..fadaed72 100644 --- a/src/layouts/qquickgridlayoutengine_p.h +++ b/src/layouts/qquickgridlayoutengine_p.h @@ -105,9 +105,11 @@ public: void setGeometry(const QRectF &rect) { + QQuickLayoutAttached *info = attachedLayoutObject(m_item, false); + const QRectF r = info ? rect.marginsRemoved(info->qMargins()) : rect; const QSizeF oldSize(m_item->width(), m_item->height()); - const QSizeF newSize = rect.size(); - const QPointF topLeft(qCeil(rect.x()), qCeil(rect.y())); + const QSizeF newSize = r.size(); + QPointF topLeft(qCeil(r.x()), qCeil(r.y())); m_item->setPosition(topLeft); if (newSize == oldSize) { if (QQuickLayout *lay = qobject_cast(m_item)) { diff --git a/src/layouts/qquicklayout.cpp b/src/layouts/qquicklayout.cpp index 3772b6f4..fe57e35a 100644 --- a/src/layouts/qquicklayout.cpp +++ b/src/layouts/qquicklayout.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Quick Layouts module of the Qt Toolkit. @@ -86,6 +86,7 @@ QQuickLayoutAttached::QQuickLayoutAttached(QObject *parent) m_preferredHeight(-1), m_maximumWidth(std::numeric_limits::infinity()), m_maximumHeight(std::numeric_limits::infinity()), + m_defaultMargins(0), m_row(-1), m_column(-1), m_rowSpan(1), @@ -99,6 +100,10 @@ QQuickLayoutAttached::QQuickLayoutAttached(QObject *parent) m_isMaximumWidthSet(false), m_isMaximumHeightSet(false), m_changesNotificationEnabled(true), + m_isLeftMarginSet(false), + m_isTopMarginSet(false), + m_isRightMarginSet(false), + m_isBottomMarginSet(false), m_alignment(0) { @@ -417,6 +422,177 @@ void QQuickLayoutAttached::setAlignment(Qt::Alignment align) } } +/*! + \qmlattachedproperty real Layout::margins + + Sets the margins outside of an item to all have the same value. The item + itself does not evaluate its own margins. It is the parents responsibility + to decide if it wants to evaluate the margins. + + Specifically, margins are only evaluated by ColumnLayout, RowLayout, + GridLayout, and other layout-like containers, such as SplitView, where the + effective cell size of an item will be increased as the margins are + increased. + + Therefore, if an item with margins is a child of another \c Item, its + position, size and implicit size will remain unchanged. + + Combining margins with alignment will align the item *including* its + margins. For instance, a vertically-centered Item with top margin 1 and + bottom margin 9 will cause the Items effective alignment within the cell to + be 4 pixels above the center. + + The default value is 0 + + \sa leftMargin + \sa topMargin + \sa rightMargin + \sa bottomMargin + + \since QtQuick.Layouts 1.2 +*/ +void QQuickLayoutAttached::setMargins(qreal m) +{ + if (m == m_defaultMargins) + return; + + m_defaultMargins = m; + invalidateItem(); + if (!m_isLeftMarginSet && m_margins.left() != m) + emit leftMarginChanged(); + if (!m_isTopMarginSet && m_margins.top() != m) + emit topMarginChanged(); + if (!m_isRightMarginSet && m_margins.right() != m) + emit rightMarginChanged(); + if (!m_isBottomMarginSet && m_margins.bottom() != m) + emit bottomMarginChanged(); + emit marginsChanged(); +} + +/*! + \qmlattachedproperty real Layout::leftMargin + + Specifies the left margin outside of an item. + If the value is not set, it will use the value from \l margins. + + \sa margins + + \since QtQuick.Layouts 1.2 +*/ +void QQuickLayoutAttached::setLeftMargin(qreal m) +{ + const bool changed = leftMargin() != m; + m_margins.setLeft(m); + m_isLeftMarginSet = true; + if (changed) { + invalidateItem(); + emit leftMarginChanged(); + } +} + +void QQuickLayoutAttached::resetLeftMargin() +{ + const bool changed = m_isLeftMarginSet && (m_defaultMargins != m_margins.left()); + m_isLeftMarginSet = false; + if (changed) { + invalidateItem(); + emit leftMarginChanged(); + } +} + +/*! + \qmlattachedproperty real Layout::topMargin + + Specifies the top margin outside of an item. + If the value is not set, it will use the value from \l margins. + + \sa margins + + \since QtQuick.Layouts 1.2 +*/ +void QQuickLayoutAttached::setTopMargin(qreal m) +{ + const bool changed = topMargin() != m; + m_margins.setTop(m); + m_isTopMarginSet = true; + if (changed) { + invalidateItem(); + emit topMarginChanged(); + } +} + +void QQuickLayoutAttached::resetTopMargin() +{ + const bool changed = m_isTopMarginSet && (m_defaultMargins != m_margins.top()); + m_isTopMarginSet = false; + if (changed) { + invalidateItem(); + emit topMarginChanged(); + } +} + +/*! + \qmlattachedproperty real Layout::rightMargin + + Specifies the right margin outside of an item. + If the value is not set, it will use the value from \l margins. + + \sa margins + + \since QtQuick.Layouts 1.2 +*/ +void QQuickLayoutAttached::setRightMargin(qreal m) +{ + const bool changed = rightMargin() != m; + m_margins.setRight(m); + m_isRightMarginSet = true; + if (changed) { + invalidateItem(); + emit rightMarginChanged(); + } +} + +void QQuickLayoutAttached::resetRightMargin() +{ + const bool changed = m_isRightMarginSet && (m_defaultMargins != m_margins.right()); + m_isRightMarginSet = false; + if (changed) { + invalidateItem(); + emit rightMarginChanged(); + } +} + +/*! + \qmlattachedproperty real Layout::bottomMargin + + Specifies the bottom margin outside of an item. + If the value is not set, it will use the value from \l margins. + + \sa margins + + \since QtQuick.Layouts 1.2 +*/ +void QQuickLayoutAttached::setBottomMargin(qreal m) +{ + const bool changed = bottomMargin() != m; + m_margins.setBottom(m); + m_isBottomMarginSet = true; + if (changed) { + invalidateItem(); + emit bottomMarginChanged(); + } +} + +void QQuickLayoutAttached::resetBottomMargin() +{ + const bool changed = m_isBottomMarginSet && (m_defaultMargins != m_margins.bottom()); + m_isBottomMarginSet = false; + if (changed) { + invalidateItem(); + emit bottomMarginChanged(); + } +} + /*! \qmlattachedproperty int Layout::rowSpan diff --git a/src/layouts/qquicklayout_p.h b/src/layouts/qquicklayout_p.h index a92fea7b..3eeefccd 100644 --- a/src/layouts/qquicklayout_p.h +++ b/src/layouts/qquicklayout_p.h @@ -119,6 +119,12 @@ class QQuickLayoutAttached : public QObject Q_PROPERTY(int columnSpan READ columnSpan WRITE setColumnSpan NOTIFY columnSpanChanged) Q_PROPERTY(Qt::Alignment alignment READ alignment WRITE setAlignment NOTIFY alignmentChanged) + Q_PROPERTY(qreal margins READ margins WRITE setMargins NOTIFY marginsChanged) + Q_PROPERTY(qreal leftMargin READ leftMargin WRITE setLeftMargin RESET resetLeftMargin NOTIFY leftMarginChanged) + Q_PROPERTY(qreal topMargin READ topMargin WRITE setTopMargin RESET resetTopMargin NOTIFY topMarginChanged) + Q_PROPERTY(qreal rightMargin READ rightMargin WRITE setRightMargin RESET resetRightMargin NOTIFY rightMarginChanged) + Q_PROPERTY(qreal bottomMargin READ bottomMargin WRITE setBottomMargin RESET resetBottomMargin NOTIFY bottomMarginChanged) + public: QQuickLayoutAttached(QObject *object); @@ -166,6 +172,29 @@ public: Qt::Alignment alignment() const { return m_alignment; } void setAlignment(Qt::Alignment align); + qreal margins() const { return m_defaultMargins; } + void setMargins(qreal m); + + qreal leftMargin() const { return m_isLeftMarginSet ? m_margins.left() : m_defaultMargins; } + void setLeftMargin(qreal m); + void resetLeftMargin(); + + qreal topMargin() const { return m_isTopMarginSet ? m_margins.top() : m_defaultMargins; } + void setTopMargin(qreal m); + void resetTopMargin(); + + qreal rightMargin() const { return m_isRightMarginSet ? m_margins.right() : m_defaultMargins; } + void setRightMargin(qreal m); + void resetRightMargin(); + + qreal bottomMargin() const { return m_isBottomMarginSet ? m_margins.bottom() : m_defaultMargins; } + void setBottomMargin(qreal m); + void resetBottomMargin(); + + QMarginsF qMargins() const { + return QMarginsF(leftMargin(), topMargin(), rightMargin(), bottomMargin()); + } + bool setChangesNotificationEnabled(bool enabled) { const bool old = m_changesNotificationEnabled; @@ -200,6 +229,11 @@ signals: void maximumHeightChanged(); void fillWidthChanged(); void fillHeightChanged(); + void leftMarginChanged(); + void topMarginChanged(); + void rightMarginChanged(); + void bottomMarginChanged(); + void marginsChanged(); void rowChanged(); void columnChanged(); void rowSpanChanged(); @@ -219,6 +253,9 @@ private: qreal m_maximumWidth; qreal m_maximumHeight; + qreal m_defaultMargins; + QMarginsF m_margins; + // GridLayout specific properties int m_row; int m_column; @@ -236,6 +273,10 @@ private: unsigned m_isMaximumWidthSet : 1; unsigned m_isMaximumHeightSet : 1; unsigned m_changesNotificationEnabled : 1; + unsigned m_isLeftMarginSet : 1; + unsigned m_isTopMarginSet : 1; + unsigned m_isRightMarginSet : 1; + unsigned m_isBottomMarginSet : 1; Qt::Alignment m_alignment; friend class QQuickLayout; }; -- cgit v1.2.1