1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QQUICKLAYOUT_P_H
5#define QQUICKLAYOUT_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <QPointer>
19#include <QQuickItem>
20#include <QtCore/qflags.h>
21
22#include <QtQuickLayouts/private/qquicklayoutglobal_p.h>
23#include <private/qquickitem_p.h>
24#include <QtQuick/private/qquickitemchangelistener_p.h>
25#include <QtGui/private/qlayoutpolicy_p.h>
26#include <QtGui/qguiapplication.h>
27
28QT_BEGIN_NAMESPACE
29
30class QQuickLayoutAttached;
31Q_DECLARE_LOGGING_CATEGORY(lcQuickLayouts)
32
33class QQuickLayoutPrivate;
34class Q_QUICKLAYOUTS_EXPORT QQuickLayout : public QQuickItem, public QQuickItemChangeListener
35
36{
37 Q_OBJECT
38 QML_NAMED_ELEMENT(Layout)
39 QML_ADDED_IN_VERSION(1, 0)
40 QML_UNCREATABLE("Do not create objects of type Layout.")
41 QML_ATTACHED(QQuickLayoutAttached)
42
43public:
44 enum SizeHint {
45 MinimumSize = 0,
46 PreferredSize,
47 MaximumSize,
48 NSizes
49 };
50
51 enum EnsureLayoutItemsUpdatedOption {
52 Recursive = 0b001,
53 ApplySizeHints = 0b010
54 };
55
56 enum SizePolicy {
57 SizePolicyImplicit = 1,
58 SizePolicyExplicit
59 };
60 Q_ENUM(SizePolicy)
61
62 Q_DECLARE_FLAGS(EnsureLayoutItemsUpdatedOptions, EnsureLayoutItemsUpdatedOption)
63
64 explicit QQuickLayout(QQuickLayoutPrivate &dd, QQuickItem *parent = nullptr);
65 ~QQuickLayout();
66
67 static QQuickLayoutAttached *qmlAttachedProperties(QObject *object);
68
69
70 void componentComplete() override;
71 virtual QSizeF sizeHint(Qt::SizeHint whichSizeHint) const = 0;
72 virtual void setAlignment(QQuickItem *item, Qt::Alignment align) = 0;
73 virtual void setStretchFactor(QQuickItem *item, int stretchFactor, Qt::Orientation orient) = 0;
74
75 virtual void invalidate(QQuickItem * childItem = nullptr);
76 virtual void updateLayoutItems() = 0;
77
78 void ensureLayoutItemsUpdated(EnsureLayoutItemsUpdatedOptions options = {}) const;
79
80 // iterator
81 virtual QQuickItem *itemAt(int index) const = 0;
82 virtual int itemCount() const = 0;
83
84 virtual void rearrange(const QSizeF &);
85
86 static void effectiveSizeHints_helper(QQuickItem *item, QSizeF *cachedSizeHints, QQuickLayoutAttached **info, bool useFallbackToWidthOrHeight);
87 static QLayoutPolicy::Policy effectiveSizePolicy_helper(QQuickItem *item, Qt::Orientation orientation, QQuickLayoutAttached *info);
88 bool shouldIgnoreItem(QQuickItem *child) const;
89 void checkAnchors(QQuickItem *item) const;
90
91 void itemChange(ItemChange change, const ItemChangeData &value) override;
92 void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override;
93 bool isReady() const;
94 void deactivateRecur();
95
96 bool invalidated() const;
97 bool invalidatedArrangement() const;
98 bool isMirrored() const;
99
100 /* QQuickItemChangeListener */
101 void itemSiblingOrderChanged(QQuickItem *item) override;
102 void itemImplicitWidthChanged(QQuickItem *item) override;
103 void itemImplicitHeightChanged(QQuickItem *item) override;
104 void itemDestroyed(QQuickItem *item) override;
105 void itemVisibilityChanged(QQuickItem *item) override;
106
107 void maybeSubscribeToBaseLineOffsetChanges(QQuickItem *item);
108
109 Q_INVOKABLE void _q_dumpLayoutTree() const;
110 void dumpLayoutTreeRecursive(int level, QString &buf) const;
111
112protected:
113 void updatePolish() override;
114
115 enum Orientation {
116 Vertical = 0,
117 Horizontal,
118 NOrientations
119 };
120
121protected Q_SLOTS:
122 void invalidateSenderItem();
123
124private:
125 unsigned m_inUpdatePolish : 1;
126 unsigned m_polishInsideUpdatePolish : 2;
127
128 Q_DECLARE_PRIVATE(QQuickLayout)
129
130 friend class QQuickLayoutAttached;
131};
132
133Q_DECLARE_OPERATORS_FOR_FLAGS(QQuickLayout::EnsureLayoutItemsUpdatedOptions)
134
135class QQuickLayoutPrivate : public QQuickItemPrivate
136{
137 Q_DECLARE_PUBLIC(QQuickLayout)
138public:
139 QQuickLayoutPrivate() : m_dirty(true)
140 , m_dirtyArrangement(true)
141 , m_isReady(false)
142 , m_disableRearrange(true)
143 , m_hasItemChangeListeners(false) {}
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};
164
165
166class Q_QUICKLAYOUTS_EXPORT QQuickLayoutAttached : public QObject
167{
168 Q_OBJECT
169 Q_PROPERTY(qreal minimumWidth READ minimumWidth WRITE setMinimumWidth NOTIFY minimumWidthChanged FINAL)
170 Q_PROPERTY(qreal minimumHeight READ minimumHeight WRITE setMinimumHeight NOTIFY minimumHeightChanged FINAL)
171 Q_PROPERTY(qreal preferredWidth READ preferredWidth WRITE setPreferredWidth NOTIFY preferredWidthChanged FINAL)
172 Q_PROPERTY(qreal preferredHeight READ preferredHeight WRITE setPreferredHeight NOTIFY preferredHeightChanged FINAL)
173 Q_PROPERTY(qreal maximumWidth READ maximumWidth WRITE setMaximumWidth NOTIFY maximumWidthChanged FINAL)
174 Q_PROPERTY(qreal maximumHeight READ maximumHeight WRITE setMaximumHeight NOTIFY maximumHeightChanged FINAL)
175 Q_PROPERTY(bool fillHeight READ fillHeight WRITE setFillHeight NOTIFY fillHeightChanged FINAL)
176 Q_PROPERTY(bool fillWidth READ fillWidth WRITE setFillWidth NOTIFY fillWidthChanged FINAL)
177 Q_PROPERTY(QQuickLayout::SizePolicy useDefaultSizePolicy READ useDefaultSizePolicy WRITE setUseDefaultSizePolicy NOTIFY useDefaultSizePolicyChanged FINAL REVISION(6, 8))
178 Q_PROPERTY(int row READ row WRITE setRow NOTIFY rowChanged FINAL)
179 Q_PROPERTY(int column READ column WRITE setColumn NOTIFY columnChanged FINAL)
180 Q_PROPERTY(int rowSpan READ rowSpan WRITE setRowSpan NOTIFY rowSpanChanged FINAL)
181 Q_PROPERTY(int columnSpan READ columnSpan WRITE setColumnSpan NOTIFY columnSpanChanged FINAL)
182 Q_PROPERTY(Qt::Alignment alignment READ alignment WRITE setAlignment NOTIFY alignmentChanged FINAL)
183 Q_PROPERTY(int horizontalStretchFactor READ horizontalStretchFactor WRITE setHorizontalStretchFactor NOTIFY horizontalStretchFactorChanged FINAL)
184 Q_PROPERTY(int verticalStretchFactor READ verticalStretchFactor WRITE setVerticalStretchFactor NOTIFY verticalStretchFactorChanged FINAL)
185
186 Q_PROPERTY(qreal margins READ margins WRITE setMargins NOTIFY marginsChanged FINAL)
187 Q_PROPERTY(qreal leftMargin READ leftMargin WRITE setLeftMargin RESET resetLeftMargin NOTIFY leftMarginChanged FINAL)
188 Q_PROPERTY(qreal topMargin READ topMargin WRITE setTopMargin RESET resetTopMargin NOTIFY topMarginChanged FINAL)
189 Q_PROPERTY(qreal rightMargin READ rightMargin WRITE setRightMargin RESET resetRightMargin NOTIFY rightMarginChanged FINAL)
190 Q_PROPERTY(qreal bottomMargin READ bottomMargin WRITE setBottomMargin RESET resetBottomMargin NOTIFY bottomMarginChanged FINAL)
191
192public:
193 QQuickLayoutAttached(QObject *object);
194
195 qreal minimumWidth() const { return !m_isMinimumWidthSet ? sizeHint(which: Qt::MinimumSize, orientation: Qt::Horizontal) : m_minimumWidth; }
196 void setMinimumWidth(qreal width);
197 bool isMinimumWidthSet() const {return m_isMinimumWidthSet; }
198
199 qreal minimumHeight() const { return !m_isMinimumHeightSet ? sizeHint(which: Qt::MinimumSize, orientation: Qt::Vertical) : m_minimumHeight; }
200 void setMinimumHeight(qreal height);
201 bool isMinimumHeightSet() const {return m_isMinimumHeightSet; }
202
203 qreal preferredWidth() const { return m_preferredWidth; }
204 void setPreferredWidth(qreal width);
205 bool isPreferredWidthSet() const {return m_preferredWidth > -1; }
206
207 qreal preferredHeight() const { return m_preferredHeight; }
208 void setPreferredHeight(qreal width);
209 bool isPreferredHeightSet() const {return m_preferredHeight > -1; }
210
211 qreal maximumWidth() const { return !m_isMaximumWidthSet ? sizeHint(which: Qt::MaximumSize, orientation: Qt::Horizontal) : m_maximumWidth; }
212 void setMaximumWidth(qreal width);
213 bool isMaximumWidthSet() const {return m_isMaximumWidthSet; }
214
215 qreal maximumHeight() const { return !m_isMaximumHeightSet ? sizeHint(which: Qt::MaximumSize, orientation: Qt::Vertical) : m_maximumHeight; }
216 void setMaximumHeight(qreal height);
217 bool isMaximumHeightSet() const {return m_isMaximumHeightSet; }
218
219 void setMinimumImplicitSize(const QSizeF &sz);
220 void setMaximumImplicitSize(const QSizeF &sz);
221
222 bool fillWidth() const {
223 if (auto *itemPriv = itemForSizePolicy(isFillSet: m_isFillWidthSet)) {
224 QLayoutPolicy::Policy hPolicy = itemPriv->sizePolicy().horizontalPolicy();
225 return hPolicy & QLayoutPolicy::GrowFlag;
226 }
227 return m_fillWidth;
228 }
229 void setFillWidth(bool fill);
230 bool isFillWidthSet() const { return m_isFillWidthSet; }
231
232 bool fillHeight() const {
233 if (auto *itemPriv = itemForSizePolicy(isFillSet: m_isFillHeightSet)) {
234 QLayoutPolicy::Policy vPolicy = itemPriv->sizePolicy().verticalPolicy();
235 return vPolicy & QLayoutPolicy::GrowFlag;
236 }
237 return m_fillHeight;
238 }
239 void setFillHeight(bool fill);
240 bool isFillHeightSet() const { return m_isFillHeightSet; }
241
242 QQuickLayout::SizePolicy useDefaultSizePolicy() const {
243 const bool appDefSizePolicy = QGuiApplication::testAttribute(attribute: Qt::AA_QtQuickUseDefaultSizePolicy);
244 return (m_isUseDefaultSizePolicySet ? m_useDefaultSizePolicy : (appDefSizePolicy ? QQuickLayout::SizePolicyImplicit : QQuickLayout::SizePolicyExplicit));
245 }
246 void setUseDefaultSizePolicy(QQuickLayout::SizePolicy sizePolicy);
247
248 int row() const { return qMax(a: m_row, b: 0); }
249 void setRow(int row);
250 bool isRowSet() const { return m_row >= 0; }
251 int column() const { return qMax(a: m_column, b: 0); }
252 void setColumn(int column);
253 bool isColumnSet() const { return m_column >= 0; }
254
255 int rowSpan() const { return m_rowSpan; }
256 void setRowSpan(int span);
257 int columnSpan() const { return m_columnSpan; }
258 void setColumnSpan(int span);
259
260 Qt::Alignment alignment() const { return m_alignment; }
261 void setAlignment(Qt::Alignment align);
262 bool isAlignmentSet() const {return m_isAlignmentSet; }
263
264 int horizontalStretchFactor() const { return m_horizontalStretch; }
265 void setHorizontalStretchFactor(int stretchFactor);
266 bool isHorizontalStretchFactorSet() const { return m_horizontalStretch > -1; }
267 int verticalStretchFactor() const { return m_verticalStretch; }
268 void setVerticalStretchFactor(int stretchFactor);
269 bool isVerticalStretchFactorSet() const { return m_verticalStretch > -1; }
270
271 qreal margins() const { return m_defaultMargins; }
272 void setMargins(qreal m);
273 bool isMarginsSet() const { return m_isMarginsSet; }
274
275 qreal leftMargin() const { return m_isLeftMarginSet ? m_margins.left() : m_defaultMargins; }
276 void setLeftMargin(qreal m);
277 void resetLeftMargin();
278 bool isLeftMarginSet() const { return m_isLeftMarginSet; }
279
280 qreal topMargin() const { return m_isTopMarginSet ? m_margins.top() : m_defaultMargins; }
281 void setTopMargin(qreal m);
282 void resetTopMargin();
283 bool isTopMarginSet() const {return m_isTopMarginSet; }
284
285 qreal rightMargin() const { return m_isRightMarginSet ? m_margins.right() : m_defaultMargins; }
286 void setRightMargin(qreal m);
287 void resetRightMargin();
288 bool isRightMarginSet() const { return m_isRightMarginSet; }
289
290 qreal bottomMargin() const { return m_isBottomMarginSet ? m_margins.bottom() : m_defaultMargins; }
291 void setBottomMargin(qreal m);
292 void resetBottomMargin();
293 bool isBottomMarginSet() const { return m_isBottomMarginSet; }
294
295 QMarginsF qMargins() const {
296 return QMarginsF(leftMargin(), topMargin(), rightMargin(), bottomMargin());
297 }
298
299 QMarginsF effectiveQMargins() const {
300 bool mirrored = parentLayout() && parentLayout()->isMirrored();
301 if (mirrored)
302 return QMarginsF(rightMargin(), topMargin(), leftMargin(), bottomMargin());
303 else
304 return qMargins();
305 }
306
307 bool setChangesNotificationEnabled(bool enabled)
308 {
309 const bool old = m_changesNotificationEnabled;
310 m_changesNotificationEnabled = enabled;
311 return old;
312 }
313
314 qreal sizeHint(Qt::SizeHint which, Qt::Orientation orientation) const;
315
316 bool isExtentExplicitlySet(Qt::Orientation o, Qt::SizeHint whichSize) const
317 {
318 switch (whichSize) {
319 case Qt::MinimumSize:
320 return o == Qt::Horizontal ? m_isMinimumWidthSet : m_isMinimumHeightSet;
321 case Qt::MaximumSize:
322 return o == Qt::Horizontal ? m_isMaximumWidthSet : m_isMaximumHeightSet;
323 case Qt::PreferredSize:
324 return true; // Layout.preferredWidth is always explicitly set
325 case Qt::MinimumDescent: // Not supported
326 case Qt::NSizeHints:
327 return false;
328 }
329 return false;
330 }
331
332 QQuickItemPrivate *itemForSizePolicy(bool isFillSet) const
333 {
334 QQuickItemPrivate *itemPriv = nullptr;
335 if (!isFillSet && qobject_cast<QQuickItem *>(o: item()) &&
336 QGuiApplication::testAttribute(attribute: Qt::AA_QtQuickUseDefaultSizePolicy))
337 itemPriv = QQuickItemPrivate::get(item: item());
338 return itemPriv;
339 }
340
341Q_SIGNALS:
342 void minimumWidthChanged();
343 void minimumHeightChanged();
344 void preferredWidthChanged();
345 void preferredHeightChanged();
346 void maximumWidthChanged();
347 void maximumHeightChanged();
348 void fillWidthChanged();
349 void fillHeightChanged();
350 Q_REVISION(6, 8) void useDefaultSizePolicyChanged();
351 void leftMarginChanged();
352 void topMarginChanged();
353 void rightMarginChanged();
354 void bottomMarginChanged();
355 void marginsChanged();
356 void rowChanged();
357 void columnChanged();
358 void rowSpanChanged();
359 void columnSpanChanged();
360 void alignmentChanged();
361 void horizontalStretchFactorChanged();
362 void verticalStretchFactorChanged();
363
364private:
365 void invalidateItem();
366 QQuickLayout *parentLayout() const;
367 QQuickItem *item() const;
368private:
369 qreal m_minimumWidth;
370 qreal m_minimumHeight;
371 qreal m_preferredWidth;
372 qreal m_preferredHeight;
373 qreal m_maximumWidth;
374 qreal m_maximumHeight;
375
376 qreal m_defaultMargins;
377 QMarginsF m_margins;
378
379 qreal m_fallbackWidth;
380 qreal m_fallbackHeight;
381
382 // GridLayout specific properties
383 int m_row;
384 int m_column;
385 int m_rowSpan;
386 int m_columnSpan;
387
388 unsigned m_fillWidth : 1;
389 unsigned m_fillHeight : 1;
390 unsigned m_isFillWidthSet : 1;
391 unsigned m_isFillHeightSet : 1;
392 unsigned m_isUseDefaultSizePolicySet: 1;
393 QQuickLayout::SizePolicy m_useDefaultSizePolicy;
394 unsigned m_isMinimumWidthSet : 1;
395 unsigned m_isMinimumHeightSet : 1;
396 // preferredWidth and preferredHeight are always explicit, since
397 // their implicit equivalent is implicitWidth and implicitHeight
398 unsigned m_isMaximumWidthSet : 1;
399 unsigned m_isMaximumHeightSet : 1;
400 unsigned m_changesNotificationEnabled : 1;
401 unsigned m_isMarginsSet : 1;
402 unsigned m_isLeftMarginSet : 1;
403 unsigned m_isTopMarginSet : 1;
404 unsigned m_isRightMarginSet : 1;
405 unsigned m_isBottomMarginSet : 1;
406 unsigned m_isAlignmentSet : 1;
407 Qt::Alignment m_alignment;
408 int m_horizontalStretch;
409 int m_verticalStretch;
410 friend class QQuickLayout;
411};
412
413inline QQuickLayoutAttached *attachedLayoutObject(QQuickItem *item, bool create = true)
414{
415 return static_cast<QQuickLayoutAttached *>(qmlAttachedPropertiesObject<QQuickLayout>(obj: item, create));
416}
417
418QT_END_NAMESPACE
419
420#endif // QQUICKLAYOUT_P_H
421

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

source code of qtdeclarative/src/quicklayouts/qquicklayout_p.h