diff options
author | Fabian Kosmale <fabian.kosmale@qt.io> | 2021-01-15 10:45:18 +0100 |
---|---|---|
committer | Fabian Kosmale <fabian.kosmale@qt.io> | 2021-01-18 09:45:44 +0100 |
commit | 12115bbda219a651ef86a4e91fd5e52eb54ed29b (patch) | |
tree | 08c17ec1b5064603ebf3943abd3147216026aeb9 /src/quicklayouts/qquicklinearlayout.cpp | |
parent | 704df6f14137d7e91cccb6f895d07fabcdb10f69 (diff) |
Quick.Layouts: Make plugin optional
This moves the Layouts types into a new library and is meant to make
them availabe to the QML compiler at some point in the future.
Change-Id: I9b2b31a78b0e9ca8b6c0db1fc9272d9941c61814
Reviewed-by: Maximilian Goldstein <max.goldstein@qt.io>
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src/quicklayouts/qquicklinearlayout.cpp')
-rw-r--r-- | src/quicklayouts/qquicklinearlayout.cpp | 888 |
1 files changed, 888 insertions, 0 deletions
diff --git a/src/quicklayouts/qquicklinearlayout.cpp b/src/quicklayouts/qquicklinearlayout.cpp new file mode 100644 index 0000000000..760700beaf --- /dev/null +++ b/src/quicklayouts/qquicklinearlayout.cpp @@ -0,0 +1,888 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Layouts module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquicklinearlayout_p.h" +#include "qquickgridlayoutengine_p.h" +#include "qquicklayoutstyleinfo_p.h" +#include <QtCore/private/qnumeric_p.h> +#include <QtQml/qqmlinfo.h> +#include "qdebug.h" +#include <limits> + +/*! + \qmltype RowLayout + \instantiates QQuickRowLayout + \inherits Item + \inqmlmodule QtQuick.Layouts + \ingroup layouts + \brief Identical to \l GridLayout, but having only one row. + + It is available as a convenience for developers, as it offers a cleaner API. + + Items in a RowLayout support these attached properties: + \list + \input layout.qdocinc attached-properties + \endlist + + \image rowlayout.png + + \code + RowLayout { + id: layout + anchors.fill: parent + spacing: 6 + Rectangle { + color: 'teal' + Layout.fillWidth: true + Layout.minimumWidth: 50 + Layout.preferredWidth: 100 + Layout.maximumWidth: 300 + Layout.minimumHeight: 150 + Text { + anchors.centerIn: parent + text: parent.width + 'x' + parent.height + } + } + Rectangle { + color: 'plum' + Layout.fillWidth: true + Layout.minimumWidth: 100 + Layout.preferredWidth: 200 + Layout.preferredHeight: 100 + Text { + anchors.centerIn: parent + text: parent.width + 'x' + parent.height + } + } + } + \endcode + + Read more about attached properties \l{QML Object Attributes}{here}. + \sa ColumnLayout + \sa GridLayout + \sa Row +*/ + +/*! + \qmltype ColumnLayout + \instantiates QQuickColumnLayout + \inherits Item + \inqmlmodule QtQuick.Layouts + \ingroup layouts + \brief Identical to \l GridLayout, but having only one column. + + It is available as a convenience for developers, as it offers a cleaner API. + + Items in a ColumnLayout support these attached properties: + \list + \input layout.qdocinc attached-properties + \endlist + + \image columnlayout.png + + \code + ColumnLayout{ + spacing: 2 + + Rectangle { + Layout.alignment: Qt.AlignCenter + color: "red" + Layout.preferredWidth: 40 + Layout.preferredHeight: 40 + } + + Rectangle { + Layout.alignment: Qt.AlignRight + color: "green" + Layout.preferredWidth: 40 + Layout.preferredHeight: 70 + } + + Rectangle { + Layout.alignment: Qt.AlignBottom + Layout.fillHeight: true + color: "blue" + Layout.preferredWidth: 70 + Layout.preferredHeight: 40 + } + } + \endcode + + Read more about attached properties \l{QML Object Attributes}{here}. + + \sa RowLayout + \sa GridLayout + \sa Column +*/ + + +/*! + \qmltype GridLayout + \instantiates QQuickGridLayout + \inherits Item + \inqmlmodule QtQuick.Layouts + \ingroup layouts + \brief Provides a way of dynamically arranging items in a grid. + + + + If the GridLayout is resized, all items in the layout will be rearranged. It is similar + to the widget-based QGridLayout. All visible children of the GridLayout element will belong to + the layout. If you want a layout with just one row or one column, you can use the + \l RowLayout or \l ColumnLayout. These offer a bit more convenient API, and improve + readability. + + By default items will be arranged according to the \l flow property. The default value of + the \l flow property is \c GridLayout.LeftToRight. + + If the \l columns property is specified, it will be treated as a maximum limit of how many + columns the layout can have, before the auto-positioning wraps back to the beginning of the + next row. The \l columns property is only used when \l flow is \c GridLayout.LeftToRight. + + \image gridlayout.png + + \code + GridLayout { + id: grid + columns: 3 + + Text { text: "Three"; font.bold: true; } + Text { text: "words"; color: "red" } + Text { text: "in"; font.underline: true } + Text { text: "a"; font.pixelSize: 20 } + Text { text: "row"; font.strikeout: true } + } + \endcode + + The \l rows property works in a similar way, but items are auto-positioned vertically. The \l + rows property is only used when \l flow is \c GridLayout.TopToBottom. + + You can specify which cell you want an item to occupy by setting the + \l{Layout::row}{Layout.row} and \l{Layout::column}{Layout.column} properties. You can also + specify the row span or column span by setting the \l{Layout::rowSpan}{Layout.rowSpan} or + \l{Layout::columnSpan}{Layout.columnSpan} properties. + + + Items in a GridLayout support these attached properties: + \list + \li \l{Layout::row}{Layout.row} + \li \l{Layout::column}{Layout.column} + \li \l{Layout::rowSpan}{Layout.rowSpan} + \li \l{Layout::columnSpan}{Layout.columnSpan} + \input layout.qdocinc attached-properties + \endlist + + Read more about attached properties \l{QML Object Attributes}{here}. + + \sa RowLayout + \sa ColumnLayout + \sa Grid +*/ + + + +QT_BEGIN_NAMESPACE + +QQuickGridLayoutBase::QQuickGridLayoutBase() + : QQuickLayout(*new QQuickGridLayoutBasePrivate) +{ + +} + +QQuickGridLayoutBase::QQuickGridLayoutBase(QQuickGridLayoutBasePrivate &dd, + Qt::Orientation orientation, + QQuickItem *parent /*= 0*/) + : QQuickLayout(dd, parent) +{ + Q_D(QQuickGridLayoutBase); + d->orientation = orientation; + d->styleInfo = new QQuickLayoutStyleInfo; +} + +Qt::Orientation QQuickGridLayoutBase::orientation() const +{ + Q_D(const QQuickGridLayoutBase); + return d->orientation; +} + +void QQuickGridLayoutBase::setOrientation(Qt::Orientation orientation) +{ + Q_D(QQuickGridLayoutBase); + if (d->orientation == orientation) + return; + + d->orientation = orientation; + invalidate(); +} + +QSizeF QQuickGridLayoutBase::sizeHint(Qt::SizeHint whichSizeHint) const +{ + Q_D(const QQuickGridLayoutBase); + ensureLayoutItemsUpdated(); + return d->engine.sizeHint(whichSizeHint, QSizeF(), d->styleInfo); +} + +/*! + \qmlproperty enumeration GridLayout::layoutDirection + \since QtQuick.Layouts 1.1 + + This property holds the layout direction of the grid layout - it controls whether items are + laid out from left to right or right to left. If \c Qt.RightToLeft is specified, + left-aligned items will be right-aligned and right-aligned items will be left-aligned. + + Possible values: + + \list + \li Qt.LeftToRight (default) - Items are laid out from left to right. + \li Qt.RightToLeft - Items are laid out from right to left. + \endlist + + \sa RowLayout::layoutDirection, ColumnLayout::layoutDirection +*/ +Qt::LayoutDirection QQuickGridLayoutBase::layoutDirection() const +{ + Q_D(const QQuickGridLayoutBase); + return d->m_layoutDirection; +} + +void QQuickGridLayoutBase::setLayoutDirection(Qt::LayoutDirection dir) +{ + Q_D(QQuickGridLayoutBase); + if (d->m_layoutDirection == dir) + return; + d->m_layoutDirection = dir; + invalidate(); + emit layoutDirectionChanged(); +} + +Qt::LayoutDirection QQuickGridLayoutBase::effectiveLayoutDirection() const +{ + Q_D(const QQuickGridLayoutBase); + return !d->effectiveLayoutMirror == (layoutDirection() == Qt::LeftToRight) + ? Qt::LeftToRight : Qt::RightToLeft; +} + +void QQuickGridLayoutBase::setAlignment(QQuickItem *item, Qt::Alignment alignment) +{ + Q_D(QQuickGridLayoutBase); + d->engine.setAlignment(item, alignment); +} + +QQuickGridLayoutBase::~QQuickGridLayoutBase() +{ + Q_D(QQuickGridLayoutBase); + + // Remove item listeners so we do not act on signalling unnecessarily + // (there is no point, as the layout will be torn down anyway). + deactivateRecur(); + delete d->styleInfo; +} + +void QQuickGridLayoutBase::componentComplete() +{ + qCDebug(lcQuickLayouts) << "QQuickGridLayoutBase::componentComplete()" << this << parent(); + QQuickLayout::componentComplete(); + + /* The layout is invalid when it is constructed, but during construction of the layout and + its children (in the "static/from QML" case which this is trying to cover) things + change and as a consequence invalidate() and ensureLayoutItemsUpdated() might be called. + As soon as ensureLayoutItemsUpdated() is called it will set d->dirty = false. + However, a subsequent invalidate() will return early if the component is not completed + because it knows that componentComplete() will take care of doing the proper layouting + (so it won't set d->dirty = true). When we then call ensureLayoutItemsUpdated() again here + it sees that its not dirty and assumes everything up-to-date. For those cases we therefore + need to call invalidate() in advance + */ + invalidate(); + ensureLayoutItemsUpdated(); + + QQuickItem *par = parentItem(); + if (qobject_cast<QQuickLayout*>(par)) + return; + rearrange(QSizeF(width(), height())); + qCDebug(lcQuickLayouts) << "QQuickGridLayoutBase::componentComplete(). COMPLETED" << this << parent(); +} + +/* + Invalidation happens like this as a reaction to that a size hint changes on an item "a": + + Suppose we have the following Qml document: + RowLayout { + id: l1 + RowLayout { + id: l2 + Item { + id: a + } + Item { + id: b + } + } + } + + 1. l2->invalidate(a) is called on l2, where item refers to "a". + (this will dirty the cached size hints of item "a") + 2. The layout engine will invalidate: + i) invalidate the layout engine + ii) dirty the cached size hints of item "l2" (by calling parentLayout()->invalidate(l2) + The recursion continues to the topmost layout + */ +/*! + \internal + + Invalidates \a childItem and this layout. + After a call to invalidate, the next call to retrieve e.g. sizeHint will be up-to date. + This function will also call QQuickLayout::invalidate(0), to ensure that the parent layout + is invalidated. + */ +void QQuickGridLayoutBase::invalidate(QQuickItem *childItem) +{ + Q_D(QQuickGridLayoutBase); + if (!isReady()) + return; + qCDebug(lcQuickLayouts) << "QQuickGridLayoutBase::invalidate()" << this << ", invalidated:" << invalidated(); + if (invalidated()) { + return; + } + qCDebug(lcQuickLayouts) << "d->m_rearranging:" << d->m_rearranging; + if (d->m_rearranging) { + d->m_invalidateAfterRearrange << childItem; + return; + } + + if (childItem) { + if (QQuickGridLayoutItem *layoutItem = d->engine.findLayoutItem(childItem)) + layoutItem->invalidate(); + } + // invalidate engine + d->engine.invalidate(); + + qCDebug(lcQuickLayouts) << "calling QQuickLayout::invalidate();"; + QQuickLayout::invalidate(); + + if (QQuickLayout *parentLayout = qobject_cast<QQuickLayout *>(parentItem())) + parentLayout->invalidate(this); + qCDebug(lcQuickLayouts) << "QQuickGridLayoutBase::invalidate() LEAVING" << this; +} + +void QQuickGridLayoutBase::updateLayoutItems() +{ + Q_D(QQuickGridLayoutBase); + if (!isReady()) + return; + if (d->m_rearranging) { + d->m_updateAfterRearrange = true; + return; + } + + qCDebug(lcQuickLayouts) << "QQuickGridLayoutBase::updateLayoutItems ENTERING" << this; + d->engine.deleteItems(); + insertLayoutItems(); + qCDebug(lcQuickLayouts) << "QQuickGridLayoutBase::updateLayoutItems() LEAVING" << this; +} + +QQuickItem *QQuickGridLayoutBase::itemAt(int index) const +{ + Q_D(const QQuickGridLayoutBase); + qCDebug(lcQuickLayouts).nospace() << "QQuickGridLayoutBase::itemAt(" << index << ")"; + ensureLayoutItemsUpdated(); + qCDebug(lcQuickLayouts).nospace() << "QQuickGridLayoutBase::itemAt(" << index << ") LEAVING"; + return static_cast<QQuickGridLayoutItem*>(d->engine.itemAt(index))->layoutItem(); +} + +int QQuickGridLayoutBase::itemCount() const +{ + Q_D(const QQuickGridLayoutBase); + ensureLayoutItemsUpdated(); + return d->engine.itemCount(); +} + +void QQuickGridLayoutBase::removeGridItem(QGridLayoutItem *gridItem) +{ + Q_D(QQuickGridLayoutBase); + const int index = gridItem->firstRow(d->orientation); + d->engine.removeItem(gridItem); + d->engine.removeRows(index, 1, d->orientation); +} + +void QQuickGridLayoutBase::itemDestroyed(QQuickItem *item) +{ + if (!isReady()) + return; + Q_D(QQuickGridLayoutBase); + qCDebug(lcQuickLayouts) << "QQuickGridLayoutBase::itemDestroyed"; + if (QQuickGridLayoutItem *gridItem = d->engine.findLayoutItem(item)) { + removeGridItem(gridItem); + delete gridItem; + invalidate(); + } +} + +void QQuickGridLayoutBase::itemVisibilityChanged(QQuickItem *item) +{ + Q_UNUSED(item); + + if (!isReady()) + return; + qCDebug(lcQuickLayouts) << "QQuickGridLayoutBase::itemVisibilityChanged()"; + invalidate(item); +} + +void QQuickGridLayoutBase::rearrange(const QSizeF &size) +{ + Q_D(QQuickGridLayoutBase); + if (!isReady()) + return; + + qCDebug(lcQuickLayouts) << "QQuickGridLayoutBase::rearrange" << d->m_recurRearrangeCounter << this; + const auto refCounter = qScopeGuard([&d] { + --(d->m_recurRearrangeCounter); + }); + if (d->m_recurRearrangeCounter++ == 2) { + // allow a recursive depth of two in order to respond to height-for-width + // (e.g QQuickText changes implicitHeight when its width gets changed) + qWarning() << "Qt Quick Layouts: Detected recursive rearrange. Aborting after two iterations."; + return; + } + + ensureLayoutItemsUpdated(); + + d->m_rearranging = true; + qCDebug(lcQuickLayouts) << objectName() << "QQuickGridLayoutBase::rearrange()" << size; + Qt::LayoutDirection visualDir = effectiveLayoutDirection(); + d->engine.setVisualDirection(visualDir); + + /* + qreal left, top, right, bottom; + left = top = right = bottom = 0; // ### support for margins? + if (visualDir == Qt::RightToLeft) + qSwap(left, right); + */ + + // Set m_dirty to false in case size hint changes during arrangement. + // This could happen if there is a binding like implicitWidth: height + QQuickLayout::rearrange(size); + d->engine.setGeometries(QRectF(QPointF(0,0), size), d->styleInfo); + d->m_rearranging = false; + + for (QQuickItem *invalid : qAsConst(d->m_invalidateAfterRearrange)) + invalidate(invalid); + d->m_invalidateAfterRearrange.clear(); + + if (d->m_updateAfterRearrange) { + ensureLayoutItemsUpdated(); + d->m_updateAfterRearrange = false; + } +} + +/********************************** + ** + ** QQuickGridLayout + ** + **/ +QQuickGridLayout::QQuickGridLayout(QQuickItem *parent /* = 0*/) + : QQuickGridLayoutBase(*new QQuickGridLayoutPrivate, Qt::Horizontal, parent) +{ +} + +/*! + \qmlproperty real GridLayout::columnSpacing + + This property holds the spacing between each column. + The default value is \c 5. +*/ +qreal QQuickGridLayout::columnSpacing() const +{ + Q_D(const QQuickGridLayout); + return d->engine.spacing(Qt::Horizontal, d->styleInfo); +} + +void QQuickGridLayout::setColumnSpacing(qreal spacing) +{ + Q_D(QQuickGridLayout); + if (qt_is_nan(spacing) || columnSpacing() == spacing) + return; + + d->engine.setSpacing(spacing, Qt::Horizontal); + invalidate(); + emit columnSpacingChanged(); +} + +/*! + \qmlproperty real GridLayout::rowSpacing + + This property holds the spacing between each row. + The default value is \c 5. +*/ +qreal QQuickGridLayout::rowSpacing() const +{ + Q_D(const QQuickGridLayout); + return d->engine.spacing(Qt::Vertical, d->styleInfo); +} + +void QQuickGridLayout::setRowSpacing(qreal spacing) +{ + Q_D(QQuickGridLayout); + if (qt_is_nan(spacing) || rowSpacing() == spacing) + return; + + d->engine.setSpacing(spacing, Qt::Vertical); + invalidate(); + emit rowSpacingChanged(); +} + +/*! + \qmlproperty int GridLayout::columns + + This property holds the column limit for items positioned if \l flow is + \c GridLayout.LeftToRight. + The default value is that there is no limit. +*/ +int QQuickGridLayout::columns() const +{ + Q_D(const QQuickGridLayout); + return d->columns; +} + +void QQuickGridLayout::setColumns(int columns) +{ + Q_D(QQuickGridLayout); + if (d->columns == columns) + return; + d->columns = columns; + invalidate(); + emit columnsChanged(); +} + + +/*! + \qmlproperty int GridLayout::rows + + This property holds the row limit for items positioned if \l flow is \c GridLayout.TopToBottom. + The default value is that there is no limit. +*/ +int QQuickGridLayout::rows() const +{ + Q_D(const QQuickGridLayout); + return d->rows; +} + +void QQuickGridLayout::setRows(int rows) +{ + Q_D(QQuickGridLayout); + if (d->rows == rows) + return; + d->rows = rows; + invalidate(); + emit rowsChanged(); +} + + +/*! + \qmlproperty enumeration GridLayout::flow + + This property holds the flow direction of items that does not have an explicit cell + position set. + It is used together with the \l columns or \l rows property, where + they specify when flow is reset to the next row or column respectively. + + Possible values are: + + \list + \li GridLayout.LeftToRight (default) - Items are positioned next to + each other, then wrapped to the next line. + \li GridLayout.TopToBottom - Items are positioned next to each + other from top to bottom, then wrapped to the next column. + \endlist + + \sa rows + \sa columns +*/ +QQuickGridLayout::Flow QQuickGridLayout::flow() const +{ + Q_D(const QQuickGridLayout); + return d->flow; +} + +void QQuickGridLayout::setFlow(QQuickGridLayout::Flow flow) +{ + Q_D(QQuickGridLayout); + if (d->flow == flow) + return; + d->flow = flow; + // If flow is changed, the layout needs to be repopulated + invalidate(); + emit flowChanged(); +} + +void QQuickGridLayout::insertLayoutItems() +{ + Q_D(QQuickGridLayout); + + int nextCellPos[2] = {0,0}; + int &nextColumn = nextCellPos[0]; + int &nextRow = nextCellPos[1]; + + const QSize gridSize(columns(), rows()); + const int flowOrientation = flow(); + int &flowColumn = nextCellPos[flowOrientation]; + int &flowRow = nextCellPos[1 - flowOrientation]; + int flowBound = (flowOrientation == QQuickGridLayout::LeftToRight) ? columns() : rows(); + + if (flowBound < 0) + flowBound = std::numeric_limits<int>::max(); + + QSizeF sizeHints[Qt::NSizeHints]; + const auto items = childItems(); + for (QQuickItem *child : items) { + checkAnchors(child); + QQuickLayoutAttached *info = nullptr; + + // Will skip all items with effective maximum width/height == 0 + if (shouldIgnoreItem(child, info, sizeHints)) + continue; + + Qt::Alignment alignment; + int row = -1; + int column = -1; + int span[2] = {1,1}; + int &columnSpan = span[0]; + int &rowSpan = span[1]; + + if (info) { + if (info->isRowSet() || info->isColumnSet()) { + // If row is specified and column is not specified (or vice versa), + // the unspecified component of the cell position should default to 0 + // The getters do this for us, as they will return 0 for an + // unset (or negative) value. + // In addition, if \a rows is less than Layout.row, treat Layout.row as if it was not set + // This will basically make it find the next available cell (potentially wrapping to + // the next line). Likewise for an invalid Layout.column + + if (gridSize.height() >= 0 && row >= gridSize.height()) { + qmlWarning(child) << QString::fromLatin1("Layout: row (%1) should be less than the number of rows (%2)").arg(info->row()).arg(rows()); + } else { + row = info->row(); + } + + if (gridSize.width() >= 0 && info->column() >= gridSize.width()) { + qmlWarning(child) << QString::fromLatin1("Layout: column (%1) should be less than the number of columns (%2)").arg(info->column()).arg(columns()); + } else { + column = info->column(); + } + } + rowSpan = info->rowSpan(); + columnSpan = info->columnSpan(); + if (columnSpan < 1) { + qmlWarning(child) << "Layout: invalid column span: " << columnSpan; + return; + + } else if (rowSpan < 1) { + qmlWarning(child) << "Layout: invalid row span: " << rowSpan; + return; + } + alignment = info->alignment(); + } + + Q_ASSERT(columnSpan >= 1); + Q_ASSERT(rowSpan >= 1); + const int sp = span[flowOrientation]; + if (sp > flowBound) + return; + + if (row >= 0) + nextRow = row; + if (column >= 0) + nextColumn = column; + + if (row < 0 || column < 0) { + /* if row or column is not specified, find next position by + advancing in the flow direction until there is a cell that + can accept the item. + + The acceptance rules are pretty simple, but complexity arises + when an item requires several cells (due to spans): + 1. Check if the cells that the item will require + does not extend beyond columns (for LeftToRight) or + rows (for TopToBottom). + 2. Check if the cells that the item will require is not already + taken by another item. + */ + bool cellAcceptsItem; + while (true) { + // Check if the item does not span beyond the layout bound + cellAcceptsItem = (flowColumn + sp) <= flowBound; + + // Check if all the required cells are not taken + for (int rs = 0; cellAcceptsItem && rs < rowSpan; ++rs) { + for (int cs = 0; cellAcceptsItem && cs < columnSpan; ++cs) { + if (d->engine.itemAt(nextRow + rs, nextColumn + cs)) { + cellAcceptsItem = false; + } + } + } + if (cellAcceptsItem) + break; + ++flowColumn; + if (flowColumn == flowBound) { + flowColumn = 0; + ++flowRow; + } + } + } + column = nextColumn; + row = nextRow; + QQuickGridLayoutItem *layoutItem = new QQuickGridLayoutItem(child, row, column, rowSpan, columnSpan, alignment); + layoutItem->setCachedSizeHints(sizeHints); + + d->engine.insertItem(layoutItem, -1); + } +} + +/********************************** + ** + ** QQuickLinearLayout + ** + **/ +QQuickLinearLayout::QQuickLinearLayout(Qt::Orientation orientation, + QQuickItem *parent /*= 0*/) + : QQuickGridLayoutBase(*new QQuickLinearLayoutPrivate, orientation, parent) +{ +} + +/*! + \qmlproperty enumeration RowLayout::layoutDirection + \since QtQuick.Layouts 1.1 + + This property holds the layout direction of the row layout - it controls whether items are laid + out from left to right or right to left. If \c Qt.RightToLeft is specified, + left-aligned items will be right-aligned and right-aligned items will be left-aligned. + + Possible values: + + \list + \li Qt.LeftToRight (default) - Items are laid out from left to right. + \li Qt.RightToLeft - Items are laid out from right to left + \endlist + + \sa GridLayout::layoutDirection, ColumnLayout::layoutDirection +*/ +/*! + \qmlproperty enumeration ColumnLayout::layoutDirection + \since QtQuick.Layouts 1.1 + + This property holds the layout direction of the column layout - it controls whether items are laid + out from left to right or right to left. If \c Qt.RightToLeft is specified, + left-aligned items will be right-aligned and right-aligned items will be left-aligned. + + Possible values: + + \list + \li Qt.LeftToRight (default) - Items are laid out from left to right. + \li Qt.RightToLeft - Items are laid out from right to left + \endlist + + \sa GridLayout::layoutDirection, RowLayout::layoutDirection +*/ + + +/*! + \qmlproperty real RowLayout::spacing + + This property holds the spacing between each cell. + The default value is \c 5. +*/ +/*! + \qmlproperty real ColumnLayout::spacing + + This property holds the spacing between each cell. + The default value is \c 5. +*/ + +qreal QQuickLinearLayout::spacing() const +{ + Q_D(const QQuickLinearLayout); + return d->engine.spacing(d->orientation, d->styleInfo); +} + +void QQuickLinearLayout::setSpacing(qreal space) +{ + Q_D(QQuickLinearLayout); + if (qt_is_nan(space) || spacing() == space) + return; + + d->engine.setSpacing(space, Qt::Horizontal | Qt::Vertical); + invalidate(); + emit spacingChanged(); +} + +void QQuickLinearLayout::insertLayoutItems() +{ + Q_D(QQuickLinearLayout); + QSizeF sizeHints[Qt::NSizeHints]; + const auto items = childItems(); + for (QQuickItem *child : items) { + Q_ASSERT(child); + checkAnchors(child); + QQuickLayoutAttached *info = nullptr; + + // Will skip all items with effective maximum width/height == 0 + if (shouldIgnoreItem(child, info, sizeHints)) + continue; + + Qt::Alignment alignment; + if (info) + alignment = info->alignment(); + + const int index = d->engine.rowCount(d->orientation); + d->engine.insertRow(index, d->orientation); + + int gridRow = 0; + int gridColumn = index; + if (d->orientation == Qt::Vertical) + qSwap(gridRow, gridColumn); + QQuickGridLayoutItem *layoutItem = new QQuickGridLayoutItem(child, gridRow, gridColumn, 1, 1, alignment); + layoutItem->setCachedSizeHints(sizeHints); + d->engine.insertItem(layoutItem, index); + } +} + +QT_END_NAMESPACE + +#include "moc_qquicklinearlayout_p.cpp" |