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