aboutsummaryrefslogtreecommitdiffstats
path: root/src/quicklayouts/qquicklinearlayout.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quicklayouts/qquicklinearlayout.cpp')
-rw-r--r--src/quicklayouts/qquicklinearlayout.cpp292
1 files changed, 192 insertions, 100 deletions
diff --git a/src/quicklayouts/qquicklinearlayout.cpp b/src/quicklayouts/qquicklinearlayout.cpp
index 2f97708b52..41f45259ea 100644
--- a/src/quicklayouts/qquicklinearlayout.cpp
+++ b/src/quicklayouts/qquicklinearlayout.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qquicklinearlayout_p.h"
#include "qquickgridlayoutengine_p.h"
@@ -53,6 +17,10 @@
\ingroup layouts
\brief Identical to \l GridLayout, but having only one row.
+ To be able to use this type more efficiently, it is recommended that you
+ understand the general mechanism of the Qt Quick Layouts module. Refer to
+ \l{Qt Quick Layouts Overview} for more information.
+
It is available as a convenience for developers, as it offers a cleaner API.
Items in a RowLayout support these attached properties:
@@ -96,7 +64,9 @@
Read more about attached properties \l{QML Object Attributes}{here}.
\sa ColumnLayout
\sa GridLayout
+ \sa StackLayout
\sa Row
+ \sa {Qt Quick Layouts Overview}
*/
/*!
@@ -107,6 +77,10 @@
\ingroup layouts
\brief Identical to \l GridLayout, but having only one column.
+ To be able to use this type more efficiently, it is recommended that you
+ understand the general mechanism of the Qt Quick Layouts module. Refer to
+ \l{Qt Quick Layouts Overview} for more information.
+
It is available as a convenience for developers, as it offers a cleaner API.
Items in a ColumnLayout support these attached properties:
@@ -148,7 +122,9 @@
\sa RowLayout
\sa GridLayout
+ \sa StackLayout
\sa Column
+ \sa {Qt Quick Layouts Overview}
*/
@@ -160,7 +136,9 @@
\ingroup layouts
\brief Provides a way of dynamically arranging items in a grid.
-
+ To be able to use this type more efficiently, it is recommended that you
+ understand the general mechanism of the Qt Quick Layouts module. Refer to
+ \l{Qt Quick Layouts Overview} for more information.
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
@@ -212,7 +190,9 @@
\sa RowLayout
\sa ColumnLayout
+ \sa StackLayout
\sa Grid
+ \sa {Qt Quick Layouts Overview}
*/
@@ -227,7 +207,7 @@ QQuickGridLayoutBase::QQuickGridLayoutBase()
QQuickGridLayoutBase::QQuickGridLayoutBase(QQuickGridLayoutBasePrivate &dd,
Qt::Orientation orientation,
- QQuickItem *parent /*= 0*/)
+ QQuickItem *parent /*= nullptr */)
: QQuickLayout(dd, parent)
{
Q_D(QQuickGridLayoutBase);
@@ -254,7 +234,6 @@ void QQuickGridLayoutBase::setOrientation(Qt::Orientation orientation)
QSizeF QQuickGridLayoutBase::sizeHint(Qt::SizeHint whichSizeHint) const
{
Q_D(const QQuickGridLayoutBase);
- ensureLayoutItemsUpdated();
return d->engine.sizeHint(whichSizeHint, QSizeF(), d->styleInfo);
}
@@ -268,10 +247,8 @@ QSizeF QQuickGridLayoutBase::sizeHint(Qt::SizeHint whichSizeHint) const
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
+ \value Qt.LeftToRight (default) Items are laid out from left to right.
+ \value Qt.RightToLeft Items are laid out from right to left.
\sa RowLayout::layoutDirection, ColumnLayout::layoutDirection
*/
@@ -302,6 +279,13 @@ void QQuickGridLayoutBase::setAlignment(QQuickItem *item, Qt::Alignment alignmen
{
Q_D(QQuickGridLayoutBase);
d->engine.setAlignment(item, alignment);
+ maybeSubscribeToBaseLineOffsetChanges(item);
+}
+
+void QQuickGridLayoutBase::setStretchFactor(QQuickItem *item, int stretchFactor, Qt::Orientation orient)
+{
+ Q_D(QQuickGridLayoutBase);
+ d->engine.setStretchFactor(item, stretchFactor, orient);
}
QQuickGridLayoutBase::~QQuickGridLayoutBase()
@@ -330,7 +314,7 @@ void QQuickGridLayoutBase::componentComplete()
need to call invalidate() in advance
*/
invalidate();
- ensureLayoutItemsUpdated();
+ ensureLayoutItemsUpdated(QQuickLayout::ApplySizeHints);
QQuickItem *par = parentItem();
if (qobject_cast<QQuickLayout*>(par))
@@ -377,26 +361,24 @@ void QQuickGridLayoutBase::invalidate(QQuickItem *childItem)
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))
+ if (d->m_rearranging) {
+ if (!d->m_invalidateAfterRearrange.contains(childItem))
+ d->m_invalidateAfterRearrange << childItem;
+ return;
+ }
+ 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()))
+ if (auto *parentLayout = qobject_cast<QQuickLayout *>(parentItem()))
parentLayout->invalidate(this);
qCDebug(lcQuickLayouts) << "QQuickGridLayoutBase::invalidate() LEAVING" << this;
}
@@ -406,10 +388,6 @@ 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();
@@ -420,16 +398,12 @@ void QQuickGridLayoutBase::updateLayoutItems()
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();
}
@@ -467,7 +441,7 @@ void QQuickGridLayoutBase::itemVisibilityChanged(QQuickItem *item)
void QQuickGridLayoutBase::rearrange(const QSizeF &size)
{
Q_D(QQuickGridLayoutBase);
- if (!isReady())
+ if (!isReady() || !size.isValid())
return;
qCDebug(lcQuickLayouts) << "QQuickGridLayoutBase::rearrange" << d->m_recurRearrangeCounter << this;
@@ -481,7 +455,9 @@ void QQuickGridLayoutBase::rearrange(const QSizeF &size)
return;
}
- ensureLayoutItemsUpdated();
+ // Should normally not be needed, but there might be an incoming window resize event that we
+ // will process before we process updatePolish()
+ ensureLayoutItemsUpdated(QQuickLayout::ApplySizeHints | QQuickLayout::Recursive);
d->m_rearranging = true;
qCDebug(lcQuickLayouts) << objectName() << "QQuickGridLayoutBase::rearrange()" << size;
@@ -501,14 +477,9 @@ void QQuickGridLayoutBase::rearrange(const QSizeF &size)
d->engine.setGeometries(QRectF(QPointF(0,0), size), d->styleInfo);
d->m_rearranging = false;
- for (QQuickItem *invalid : qAsConst(d->m_invalidateAfterRearrange))
- invalidate(invalid);
+ for (auto childItem : std::as_const(d->m_invalidateAfterRearrange))
+ invalidate(childItem);
d->m_invalidateAfterRearrange.clear();
-
- if (d->m_updateAfterRearrange) {
- ensureLayoutItemsUpdated();
- d->m_updateAfterRearrange = false;
- }
}
/**********************************
@@ -516,7 +487,7 @@ void QQuickGridLayoutBase::rearrange(const QSizeF &size)
** QQuickGridLayout
**
**/
-QQuickGridLayout::QQuickGridLayout(QQuickItem *parent /* = 0*/)
+QQuickGridLayout::QQuickGridLayout(QQuickItem *parent /* = nullptr*/)
: QQuickGridLayoutBase(*new QQuickGridLayoutPrivate, Qt::Horizontal, parent)
{
}
@@ -624,12 +595,10 @@ void QQuickGridLayout::setRows(int rows)
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
+ \value GridLayout.LeftToRight
+ (default) Items are positioned next to each other, then wrapped to the next line.
+ \value GridLayout.TopToBottom
+ Items are positioned next to each other from top to bottom, then wrapped to the next column.
\sa rows
\sa columns
@@ -651,6 +620,69 @@ void QQuickGridLayout::setFlow(QQuickGridLayout::Flow flow)
emit flowChanged();
}
+/*!
+ \qmlproperty bool GridLayout::uniformCellWidths
+ \since QtQuick.Layouts 6.6
+
+ If this property is set to \c true, the layout will force all cells to have
+ a uniform width. The layout aims to respect
+ \l{Layout::minimumWidth}{Layout.minimumWidth},
+ \l{Layout::preferredWidth}{Layout.preferredWidth} and
+ \l{Layout::maximumWidth}{Layout.maximumWidth} in this mode but might make
+ compromisses to fullfill the requirements of all items.
+
+ Default value is \c false.
+
+ \sa GridLayout::uniformCellHeights, RowLayout::uniformCellSizes, ColumnLayout::uniformCellSizes
+*/
+bool QQuickGridLayout::uniformCellWidths() const
+{
+ Q_D(const QQuickGridLayout);
+ return d->engine.uniformCellWidths();
+}
+
+void QQuickGridLayout::setUniformCellWidths(bool uniformCellWidths)
+{
+ Q_D(QQuickGridLayout);
+ if (d->engine.uniformCellWidths() == uniformCellWidths)
+ return;
+ d->engine.setUniformCellWidths(uniformCellWidths);
+ invalidate();
+ emit uniformCellWidthsChanged();
+}
+
+/*!
+ \qmlproperty bool GridLayout::uniformCellHeights
+ \since QtQuick.Layouts 6.6
+
+ If this property is set to \c true, the layout will force all cells to have an
+ uniform Height. The layout aims to respect
+ \l{Layout::minimumHeight}{Layout.minimumHeight},
+ \l{Layout::preferredHeight}{Layout.preferredHeight} and
+ \l{Layout::maximumHeight}{Layout.maximumHeight} in this mode but might make
+ compromisses to fullfill the requirements of all items.
+
+ Default value is \c false.
+
+ \sa GridLayout::uniformCellWidths, RowLayout::uniformCellSizes, ColumnLayout::uniformCellSizes
+*/
+bool QQuickGridLayout::uniformCellHeights() const
+{
+ Q_D(const QQuickGridLayout);
+ return d->engine.uniformCellHeights();
+}
+
+void QQuickGridLayout::setUniformCellHeights(bool uniformCellHeights)
+{
+ Q_D(QQuickGridLayout);
+ if (d->engine.uniformCellHeights() == uniformCellHeights)
+ return;
+ d->engine.setUniformCellHeights(uniformCellHeights);
+ invalidate();
+ emit uniformCellHeightsChanged();
+}
+
+
void QQuickGridLayout::insertLayoutItems()
{
Q_D(QQuickGridLayout);
@@ -668,17 +700,17 @@ void QQuickGridLayout::insertLayoutItems()
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))
+ if (shouldIgnoreItem(child))
continue;
+ QQuickLayoutAttached *info = attachedLayoutObject(child, false);
Qt::Alignment alignment;
+ int hStretch = -1;
+ int vStretch = -1;
int row = -1;
int column = -1;
int span[2] = {1,1};
@@ -718,6 +750,12 @@ void QQuickGridLayout::insertLayoutItems()
return;
}
alignment = info->alignment();
+ hStretch = info->horizontalStretchFactor();
+ if (hStretch >= 0 && !info->fillWidth())
+ qmlWarning(child) << "horizontalStretchFactor requires fillWidth to also be set to true";
+ vStretch = info->verticalStretchFactor();
+ if (vStretch >= 0 && !info->fillHeight())
+ qmlWarning(child) << "verticalStretchFactor requires fillHeight to also be set to true";
}
Q_ASSERT(columnSpan >= 1);
@@ -769,7 +807,10 @@ void QQuickGridLayout::insertLayoutItems()
column = nextColumn;
row = nextRow;
QQuickGridLayoutItem *layoutItem = new QQuickGridLayoutItem(child, row, column, rowSpan, columnSpan, alignment);
- layoutItem->setCachedSizeHints(sizeHints);
+ if (hStretch >= 0)
+ layoutItem->setStretchFactor(hStretch, Qt::Horizontal);
+ if (vStretch >= 0)
+ layoutItem->setStretchFactor(vStretch, Qt::Vertical);
d->engine.insertItem(layoutItem, -1);
}
@@ -781,7 +822,7 @@ void QQuickGridLayout::insertLayoutItems()
**
**/
QQuickLinearLayout::QQuickLinearLayout(Qt::Orientation orientation,
- QQuickItem *parent /*= 0*/)
+ QQuickItem *parent /*= nullptr*/)
: QQuickGridLayoutBase(*new QQuickLinearLayoutPrivate, orientation, parent)
{
}
@@ -796,10 +837,8 @@ QQuickLinearLayout::QQuickLinearLayout(Qt::Orientation orientation,
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
+ \value Qt.LeftToRight (default) Items are laid out from left to right.
+ \value Qt.RightToLeft Items are laid out from right to left
\sa GridLayout::layoutDirection, ColumnLayout::layoutDirection
*/
@@ -813,14 +852,49 @@ QQuickLinearLayout::QQuickLinearLayout(Qt::Orientation orientation,
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
+ \value Qt.LeftToRight (default) Items are laid out from left to right.
+ \value Qt.RightToLeft Items are laid out from right to left
\sa GridLayout::layoutDirection, RowLayout::layoutDirection
*/
+/*!
+ \qmlproperty bool RowLayout::uniformCellSizes
+ \since QtQuick.Layouts 6.6
+
+ If this property is set to \c true, the layout will force all cells to have
+ a uniform size.
+
+ \sa GridLayout::uniformCellWidths, GridLayout::uniformCellHeights, ColumnLayout::uniformCellSizes
+*/
+/*!
+ \qmlproperty bool ColumnLayout::uniformCellSizes
+ \since QtQuick.Layouts 6.6
+
+ If this property is set to \c true, the layout will force all cells to have
+ a uniform size.
+
+ \sa GridLayout::uniformCellWidths, GridLayout::uniformCellHeights, RowLayout::uniformCellSizes
+*/
+bool QQuickLinearLayout::uniformCellSizes() const
+{
+ Q_D(const QQuickLinearLayout);
+ Q_ASSERT(d->engine.uniformCellWidths() == d->engine.uniformCellHeights());
+ return d->engine.uniformCellWidths();
+}
+
+void QQuickLinearLayout::setUniformCellSizes(bool uniformCellSizes)
+{
+ Q_D(QQuickLinearLayout);
+ Q_ASSERT(d->engine.uniformCellWidths() == d->engine.uniformCellHeights());
+ if (d->engine.uniformCellHeights() == uniformCellSizes)
+ return;
+ d->engine.setUniformCellWidths(uniformCellSizes);
+ d->engine.setUniformCellHeights(uniformCellSizes);
+ invalidate();
+ emit uniformCellSizesChanged();
+}
+
/*!
\qmlproperty real RowLayout::spacing
@@ -855,20 +929,28 @@ void QQuickLinearLayout::setSpacing(qreal space)
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))
+ if (shouldIgnoreItem(child))
continue;
+ QQuickLayoutAttached *info = attachedLayoutObject(child, false);
Qt::Alignment alignment;
- if (info)
+ int hStretch = -1;
+ int vStretch = -1;
+ bool fillWidth = false;
+ bool fillHeight = false;
+ if (info) {
alignment = info->alignment();
+ hStretch = info->horizontalStretchFactor();
+ vStretch = info->verticalStretchFactor();
+ fillWidth = info->fillWidth();
+ fillHeight = info->fillHeight();
+ }
const int index = d->engine.rowCount(d->orientation);
d->engine.insertRow(index, d->orientation);
@@ -878,7 +960,17 @@ void QQuickLinearLayout::insertLayoutItems()
if (d->orientation == Qt::Vertical)
qSwap(gridRow, gridColumn);
QQuickGridLayoutItem *layoutItem = new QQuickGridLayoutItem(child, gridRow, gridColumn, 1, 1, alignment);
- layoutItem->setCachedSizeHints(sizeHints);
+
+ if (hStretch >= 0) {
+ if (!fillWidth)
+ qmlWarning(child) << "horizontalStretchFactor requires fillWidth to also be set to true";
+ layoutItem->setStretchFactor(hStretch, Qt::Horizontal);
+ }
+ if (vStretch >= 0) {
+ if (!fillHeight)
+ qmlWarning(child) << "verticalStretchFactor requires fillHeight to also be set to true";
+ layoutItem->setStretchFactor(vStretch, Qt::Vertical);
+ }
d->engine.insertItem(layoutItem, index);
}
}