1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt Quick Layouts module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#ifndef QQUICKLAYOUT_P_H
41#define QQUICKLAYOUT_P_H
42
43#include <QPointer>
44#include <QQuickItem>
45#include <private/qquickitem_p.h>
46#include <QtQuick/private/qquickitemchangelistener_p.h>
47#include <QtGui/private/qlayoutpolicy_p.h>
48
49QT_BEGIN_NAMESPACE
50
51class QQuickLayoutAttached;
52Q_DECLARE_LOGGING_CATEGORY(lcQuickLayouts)
53
54class QQuickLayoutPrivate;
55class QQuickLayout : public QQuickItem, public QQuickItemChangeListener
56
57{
58 Q_OBJECT
59 QML_NAMED_ELEMENT(Layout)
60 QML_UNCREATABLE("Do not create objects of type Layout.")
61 QML_ATTACHED(QQuickLayoutAttached)
62
63public:
64 enum SizeHint {
65 MinimumSize = 0,
66 PreferredSize,
67 MaximumSize,
68 NSizes
69 };
70
71 explicit QQuickLayout(QQuickLayoutPrivate &dd, QQuickItem *parent = 0);
72 ~QQuickLayout();
73
74 static QQuickLayoutAttached *qmlAttachedProperties(QObject *object);
75
76
77 void componentComplete() override;
78 virtual QSizeF sizeHint(Qt::SizeHint whichSizeHint) const = 0;
79 virtual void setAlignment(QQuickItem *item, Qt::Alignment align) = 0;
80 virtual void invalidate(QQuickItem * childItem = 0);
81 virtual void updateLayoutItems() = 0;
82 void ensureLayoutItemsUpdated() const;
83
84 // iterator
85 virtual QQuickItem *itemAt(int index) const = 0;
86 virtual int itemCount() const = 0;
87
88 virtual void rearrange(const QSizeF &);
89
90 static void effectiveSizeHints_helper(QQuickItem *item, QSizeF *cachedSizeHints, QQuickLayoutAttached **info, bool useFallbackToWidthOrHeight);
91 static QLayoutPolicy::Policy effectiveSizePolicy_helper(QQuickItem *item, Qt::Orientation orientation, QQuickLayoutAttached *info);
92 bool shouldIgnoreItem(QQuickItem *child, QQuickLayoutAttached *&info, QSizeF *sizeHints) const;
93 void checkAnchors(QQuickItem *item) const;
94
95 void itemChange(ItemChange change, const ItemChangeData &value) override;
96 void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override;
97 bool isReady() const;
98 void deactivateRecur();
99
100 bool invalidated() const;
101 bool invalidatedArrangement() const;
102 bool isMirrored() const;
103
104 /* QQuickItemChangeListener */
105 void itemSiblingOrderChanged(QQuickItem *item) override;
106 void itemImplicitWidthChanged(QQuickItem *item) override;
107 void itemImplicitHeightChanged(QQuickItem *item) override;
108 void itemDestroyed(QQuickItem *item) override;
109 void itemVisibilityChanged(QQuickItem *item) override;
110
111 Q_INVOKABLE void _q_dumpLayoutTree() const;
112 void dumpLayoutTreeRecursive(int level, QString &buf) const;
113
114protected:
115 void updatePolish() override;
116
117 enum Orientation {
118 Vertical = 0,
119 Horizontal,
120 NOrientations
121 };
122
123protected slots:
124 void invalidateSenderItem();
125
126private:
127 unsigned m_inUpdatePolish : 1;
128 unsigned m_polishInsideUpdatePolish : 2;
129
130 Q_DECLARE_PRIVATE(QQuickLayout)
131
132 friend class QQuickLayoutAttached;
133};
134
135
136class QQuickLayoutPrivate : public QQuickItemPrivate
137{
138 Q_DECLARE_PUBLIC(QQuickLayout)
139public:
140 QQuickLayoutPrivate() : m_dirty(true), m_dirtyArrangement(true), m_isReady(false), m_disableRearrange(true), m_hasItemChangeListeners(false) {}
141
142 qreal getImplicitWidth() const override;
143 qreal getImplicitHeight() const override;
144
145 void applySizeHints() const;
146
147protected:
148 /* m_dirty == true means that something in the layout was changed,
149 but its state has not been synced to the internal grid layout engine. It is usually:
150 1. A child item was added or removed from the layout (or made visible/invisble)
151 2. A child item got one of its size hints changed
152 */
153 mutable unsigned m_dirty : 1;
154 /* m_dirtyArrangement == true means that the layout still needs a rearrange despite that
155 * m_dirty == false. This is only used for the case that a layout has been invalidated,
156 * but its new size is the same as the old size (in that case the child layout won't get
157 * a geometryChanged() notification, which rearrange() usually reacts to)
158 */
159 mutable unsigned m_dirtyArrangement : 1;
160 unsigned m_isReady : 1;
161 unsigned m_disableRearrange : 1;
162 unsigned m_hasItemChangeListeners : 1; // if false, we don't need to remove its item change listeners...
163 mutable QSet<QQuickItem *> m_ignoredItems;
164};
165
166
167class QQuickLayoutAttached : public QObject
168{
169 Q_OBJECT
170 Q_PROPERTY(qreal minimumWidth READ minimumWidth WRITE setMinimumWidth NOTIFY minimumWidthChanged)
171 Q_PROPERTY(qreal minimumHeight READ minimumHeight WRITE setMinimumHeight NOTIFY minimumHeightChanged)
172 Q_PROPERTY(qreal preferredWidth READ preferredWidth WRITE setPreferredWidth NOTIFY preferredWidthChanged)
173 Q_PROPERTY(qreal preferredHeight READ preferredHeight WRITE setPreferredHeight NOTIFY preferredHeightChanged)
174 Q_PROPERTY(qreal maximumWidth READ maximumWidth WRITE setMaximumWidth NOTIFY maximumWidthChanged)
175 Q_PROPERTY(qreal maximumHeight READ maximumHeight WRITE setMaximumHeight NOTIFY maximumHeightChanged)
176 Q_PROPERTY(bool fillHeight READ fillHeight WRITE setFillHeight NOTIFY fillHeightChanged)
177 Q_PROPERTY(bool fillWidth READ fillWidth WRITE setFillWidth NOTIFY fillWidthChanged)
178 Q_PROPERTY(int row READ row WRITE setRow NOTIFY rowChanged)
179 Q_PROPERTY(int column READ column WRITE setColumn NOTIFY columnChanged)
180 Q_PROPERTY(int rowSpan READ rowSpan WRITE setRowSpan NOTIFY rowSpanChanged)
181 Q_PROPERTY(int columnSpan READ columnSpan WRITE setColumnSpan NOTIFY columnSpanChanged)
182 Q_PROPERTY(Qt::Alignment alignment READ alignment WRITE setAlignment NOTIFY alignmentChanged)
183
184 Q_PROPERTY(qreal margins READ margins WRITE setMargins NOTIFY marginsChanged)
185 Q_PROPERTY(qreal leftMargin READ leftMargin WRITE setLeftMargin RESET resetLeftMargin NOTIFY leftMarginChanged)
186 Q_PROPERTY(qreal topMargin READ topMargin WRITE setTopMargin RESET resetTopMargin NOTIFY topMarginChanged)
187 Q_PROPERTY(qreal rightMargin READ rightMargin WRITE setRightMargin RESET resetRightMargin NOTIFY rightMarginChanged)
188 Q_PROPERTY(qreal bottomMargin READ bottomMargin WRITE setBottomMargin RESET resetBottomMargin NOTIFY bottomMarginChanged)
189
190public:
191 QQuickLayoutAttached(QObject *object);
192
193 qreal minimumWidth() const { return !m_isMinimumWidthSet ? sizeHint(which: Qt::MinimumSize, orientation: Qt::Horizontal) : m_minimumWidth; }
194 void setMinimumWidth(qreal width);
195
196 qreal minimumHeight() const { return !m_isMinimumHeightSet ? sizeHint(which: Qt::MinimumSize, orientation: Qt::Vertical) : m_minimumHeight; }
197 void setMinimumHeight(qreal height);
198
199 qreal preferredWidth() const { return m_preferredWidth; }
200 void setPreferredWidth(qreal width);
201
202 qreal preferredHeight() const { return m_preferredHeight; }
203 void setPreferredHeight(qreal width);
204
205 qreal maximumWidth() const { return !m_isMaximumWidthSet ? sizeHint(which: Qt::MaximumSize, orientation: Qt::Horizontal) : m_maximumWidth; }
206 void setMaximumWidth(qreal width);
207
208 qreal maximumHeight() const { return !m_isMaximumHeightSet ? sizeHint(which: Qt::MaximumSize, orientation: Qt::Vertical) : m_maximumHeight; }
209 void setMaximumHeight(qreal height);
210
211 void setMinimumImplicitSize(const QSizeF &sz);
212 void setMaximumImplicitSize(const QSizeF &sz);
213
214 bool fillWidth() const { return m_fillWidth; }
215 void setFillWidth(bool fill);
216 bool isFillWidthSet() const { return m_isFillWidthSet; }
217
218 bool fillHeight() const { return m_fillHeight; }
219 void setFillHeight(bool fill);
220 bool isFillHeightSet() const { return m_isFillHeightSet; }
221
222 int row() const { return qMax(a: m_row, b: 0); }
223 void setRow(int row);
224 bool isRowSet() const { return m_row >= 0; }
225 int column() const { return qMax(a: m_column, b: 0); }
226 void setColumn(int column);
227 bool isColumnSet() const { return m_column >= 0; }
228
229 int rowSpan() const { return m_rowSpan; }
230 void setRowSpan(int span);
231 int columnSpan() const { return m_columnSpan; }
232 void setColumnSpan(int span);
233
234 Qt::Alignment alignment() const { return m_alignment; }
235 void setAlignment(Qt::Alignment align);
236
237 qreal margins() const { return m_defaultMargins; }
238 void setMargins(qreal m);
239
240 qreal leftMargin() const { return m_isLeftMarginSet ? m_margins.left() : m_defaultMargins; }
241 void setLeftMargin(qreal m);
242 void resetLeftMargin();
243
244 qreal topMargin() const { return m_isTopMarginSet ? m_margins.top() : m_defaultMargins; }
245 void setTopMargin(qreal m);
246 void resetTopMargin();
247
248 qreal rightMargin() const { return m_isRightMarginSet ? m_margins.right() : m_defaultMargins; }
249 void setRightMargin(qreal m);
250 void resetRightMargin();
251
252 qreal bottomMargin() const { return m_isBottomMarginSet ? m_margins.bottom() : m_defaultMargins; }
253 void setBottomMargin(qreal m);
254 void resetBottomMargin();
255
256 QMarginsF qMargins() const {
257 return QMarginsF(leftMargin(), topMargin(), rightMargin(), bottomMargin());
258 }
259
260 QMarginsF effectiveQMargins() const {
261 bool mirrored = parentLayout() && parentLayout()->isMirrored();
262 if (mirrored)
263 return QMarginsF(rightMargin(), topMargin(), leftMargin(), bottomMargin());
264 else
265 return qMargins();
266 }
267
268 bool setChangesNotificationEnabled(bool enabled)
269 {
270 const bool old = m_changesNotificationEnabled;
271 m_changesNotificationEnabled = enabled;
272 return old;
273 }
274
275 qreal sizeHint(Qt::SizeHint which, Qt::Orientation orientation) const;
276
277 bool isExtentExplicitlySet(Qt::Orientation o, Qt::SizeHint whichSize) const
278 {
279 switch (whichSize) {
280 case Qt::MinimumSize:
281 return o == Qt::Horizontal ? m_isMinimumWidthSet : m_isMinimumHeightSet;
282 case Qt::MaximumSize:
283 return o == Qt::Horizontal ? m_isMaximumWidthSet : m_isMaximumHeightSet;
284 case Qt::PreferredSize:
285 return true; // Layout.preferredWidth is always explicitly set
286 case Qt::MinimumDescent: // Not supported
287 case Qt::NSizeHints:
288 return false;
289 }
290 return false;
291 }
292
293signals:
294 void minimumWidthChanged();
295 void minimumHeightChanged();
296 void preferredWidthChanged();
297 void preferredHeightChanged();
298 void maximumWidthChanged();
299 void maximumHeightChanged();
300 void fillWidthChanged();
301 void fillHeightChanged();
302 void leftMarginChanged();
303 void topMarginChanged();
304 void rightMarginChanged();
305 void bottomMarginChanged();
306 void marginsChanged();
307 void rowChanged();
308 void columnChanged();
309 void rowSpanChanged();
310 void columnSpanChanged();
311 void alignmentChanged();
312
313private:
314 void invalidateItem();
315 QQuickLayout *parentLayout() const;
316 QQuickItem *item() const;
317private:
318 qreal m_minimumWidth;
319 qreal m_minimumHeight;
320 qreal m_preferredWidth;
321 qreal m_preferredHeight;
322 qreal m_maximumWidth;
323 qreal m_maximumHeight;
324
325 qreal m_defaultMargins;
326 QMarginsF m_margins;
327
328 qreal m_fallbackWidth;
329 qreal m_fallbackHeight;
330
331 // GridLayout specific properties
332 int m_row;
333 int m_column;
334 int m_rowSpan;
335 int m_columnSpan;
336
337 unsigned m_fillWidth : 1;
338 unsigned m_fillHeight : 1;
339 unsigned m_isFillWidthSet : 1;
340 unsigned m_isFillHeightSet : 1;
341 unsigned m_isMinimumWidthSet : 1;
342 unsigned m_isMinimumHeightSet : 1;
343 // preferredWidth and preferredHeight are always explicit, since
344 // their implicit equivalent is implicitWidth and implicitHeight
345 unsigned m_isMaximumWidthSet : 1;
346 unsigned m_isMaximumHeightSet : 1;
347 unsigned m_changesNotificationEnabled : 1;
348 unsigned m_isLeftMarginSet : 1;
349 unsigned m_isTopMarginSet : 1;
350 unsigned m_isRightMarginSet : 1;
351 unsigned m_isBottomMarginSet : 1;
352 Qt::Alignment m_alignment;
353 friend class QQuickLayout;
354};
355
356inline QQuickLayoutAttached *attachedLayoutObject(QQuickItem *item, bool create = true)
357{
358 return static_cast<QQuickLayoutAttached *>(qmlAttachedPropertiesObject<QQuickLayout>(obj: item, create));
359}
360
361QT_END_NAMESPACE
362
363QML_DECLARE_TYPE(QQuickLayout)
364
365#endif // QQUICKLAYOUT_P_H
366

source code of qtdeclarative/src/imports/layouts/qquicklayout_p.h