Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qquicklayout.cpp
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
4#include "qquicklayout_p.h"
5#include <QEvent>
6#include <QtCore/qcoreapplication.h>
7#include <QtCore/private/qnumeric_p.h>
8#include <QtCore/qstack.h>
9#include <QtCore/qmath.h>
10#include <QtQml/qqmlinfo.h>
11#include <limits>
12
16
61
62Q_LOGGING_CATEGORY(lcQuickLayouts, "qt.quick.layouts")
63
65 : QObject(parent),
66 m_minimumWidth(0),
67 m_minimumHeight(0),
68 m_preferredWidth(-1),
69 m_preferredHeight(-1),
70 m_maximumWidth(std::numeric_limits<qreal>::infinity()),
71 m_maximumHeight(std::numeric_limits<qreal>::infinity()),
72 m_defaultMargins(0),
73 m_fallbackWidth(-1),
74 m_fallbackHeight(-1),
75 m_row(-1),
76 m_column(-1),
77 m_rowSpan(1),
78 m_columnSpan(1),
79 m_fillWidth(false),
80 m_fillHeight(false),
81 m_isFillWidthSet(false),
82 m_isFillHeightSet(false),
83 m_isMinimumWidthSet(false),
84 m_isMinimumHeightSet(false),
85 m_isMaximumWidthSet(false),
86 m_isMaximumHeightSet(false),
87 m_changesNotificationEnabled(true),
88 m_isMarginsSet(false),
89 m_isLeftMarginSet(false),
90 m_isTopMarginSet(false),
91 m_isRightMarginSet(false),
92 m_isBottomMarginSet(false),
93 m_isAlignmentSet(false),
94 m_horizontalStretch(-1),
95 m_verticalStretch(-1)
96{
97
98}
99
117{
118 if (qt_is_nan(width))
119 return;
120 m_isMinimumWidthSet = width >= 0;
121 if (m_minimumWidth == width)
122 return;
123
124 m_minimumWidth = width;
125 invalidateItem();
127}
128
145{
146 if (qt_is_nan(height))
147 return;
148 m_isMinimumHeightSet = height >= 0;
149 if (m_minimumHeight == height)
150 return;
151
152 m_minimumHeight = height;
153 invalidateItem();
155}
156
169{
170 if (qt_is_nan(width) || m_preferredWidth == width)
171 return;
172
173 m_preferredWidth = width;
174 invalidateItem();
176}
177
190{
191 if (qt_is_nan(height) || m_preferredHeight == height)
192 return;
193
194 m_preferredHeight = height;
195 invalidateItem();
197}
198
215{
216 if (qt_is_nan(width))
217 return;
218 m_isMaximumWidthSet = width >= 0;
219 if (m_maximumWidth == width)
220 return;
221
222 m_maximumWidth = width;
223 invalidateItem();
225}
226
242{
243 if (qt_is_nan(height))
244 return;
245 m_isMaximumHeightSet = height >= 0;
246 if (m_maximumHeight == height)
247 return;
248
249 m_maximumHeight = height;
250 invalidateItem();
252}
253
255{
256 bool emitWidthChanged = false;
257 bool emitHeightChanged = false;
258 if (!m_isMinimumWidthSet && m_minimumWidth != sz.width()) {
259 m_minimumWidth = sz.width();
260 emitWidthChanged = true;
261 }
262 if (!m_isMinimumHeightSet && m_minimumHeight != sz.height()) {
263 m_minimumHeight = sz.height();
264 emitHeightChanged = true;
265 }
266 // Only invalidate the item once, and make sure we emit signal changed after the call to
267 // invalidateItem()
268 if (emitWidthChanged || emitHeightChanged) {
269 invalidateItem();
270 if (emitWidthChanged)
272 if (emitHeightChanged)
274 }
275}
276
278{
279 bool emitWidthChanged = false;
280 bool emitHeightChanged = false;
281 if (!m_isMaximumWidthSet && m_maximumWidth != sz.width()) {
282 m_maximumWidth = sz.width();
283 emitWidthChanged = true;
284 }
285 if (!m_isMaximumHeightSet && m_maximumHeight != sz.height()) {
286 m_maximumHeight = sz.height();
287 emitHeightChanged = true;
288 }
289 // Only invalidate the item once, and make sure we emit changed signal after the call to
290 // invalidateItem()
291 if (emitWidthChanged || emitHeightChanged) {
292 invalidateItem();
293 if (emitWidthChanged)
295 if (emitHeightChanged)
297 }
298}
299
311{
312 m_isFillWidthSet = true;
313 if (m_fillWidth != fill) {
314 m_fillWidth = fill;
315 invalidateItem();
317 }
318}
319
331{
332 m_isFillHeightSet = true;
333 if (m_fillHeight != fill) {
334 m_fillHeight = fill;
335 invalidateItem();
337 }
338}
339
353{
354 if (row >= 0 && row != m_row) {
355 m_row = row;
356 invalidateItem();
358 }
359}
360
374{
375 if (column >= 0 && column != m_column) {
376 m_column = column;
377 invalidateItem();
379 }
380}
381
382
406void QQuickLayoutAttached::setAlignment(Qt::Alignment align)
407{
408 m_isAlignmentSet = true;
409 if (align != m_alignment) {
410 m_alignment = align;
411 if (QQuickLayout *layout = parentLayout()) {
412 layout->setAlignment(item(), align);
413 invalidateItem();
414 }
416 }
417}
418
445{
446 if (factor != m_horizontalStretch) {
447 m_horizontalStretch = factor;
448 if (QQuickLayout *layout = parentLayout()) {
449 layout->setStretchFactor(item(), factor, Qt::Horizontal);
450 invalidateItem();
451 }
453 }
454}
455
482{
483 if (factor != m_verticalStretch) {
484 m_verticalStretch = factor;
485 if (QQuickLayout *layout = parentLayout()) {
486 layout->setStretchFactor(item(), factor, Qt::Vertical);
487 invalidateItem();
488 }
490 }
491}
492
523{
524 m_isMarginsSet = true;
525 if (m == m_defaultMargins)
526 return;
527
528 m_defaultMargins = m;
529 invalidateItem();
530 if (!m_isLeftMarginSet && m_margins.left() != m)
532 if (!m_isTopMarginSet && m_margins.top() != m)
534 if (!m_isRightMarginSet && m_margins.right() != m)
536 if (!m_isBottomMarginSet && m_margins.bottom() != m)
539}
540
552{
553 const bool changed = leftMargin() != m;
554 m_margins.setLeft(m);
555 m_isLeftMarginSet = true;
556 if (changed) {
557 invalidateItem();
559 }
560}
561
563{
564 const bool changed = m_isLeftMarginSet && (m_defaultMargins != m_margins.left());
565 m_isLeftMarginSet = false;
566 if (changed) {
567 invalidateItem();
569 }
570}
571
583{
584 const bool changed = topMargin() != m;
585 m_margins.setTop(m);
586 m_isTopMarginSet = true;
587 if (changed) {
588 invalidateItem();
590 }
591}
592
594{
595 const bool changed = m_isTopMarginSet && (m_defaultMargins != m_margins.top());
596 m_isTopMarginSet = false;
597 if (changed) {
598 invalidateItem();
600 }
601}
602
614{
615 const bool changed = rightMargin() != m;
616 m_margins.setRight(m);
617 m_isRightMarginSet = true;
618 if (changed) {
619 invalidateItem();
621 }
622}
623
625{
626 const bool changed = m_isRightMarginSet && (m_defaultMargins != m_margins.right());
627 m_isRightMarginSet = false;
628 if (changed) {
629 invalidateItem();
631 }
632}
633
645{
646 const bool changed = bottomMargin() != m;
647 m_margins.setBottom(m);
648 m_isBottomMarginSet = true;
649 if (changed) {
650 invalidateItem();
652 }
653}
654
656{
657 const bool changed = m_isBottomMarginSet && (m_defaultMargins != m_margins.bottom());
658 m_isBottomMarginSet = false;
659 if (changed) {
660 invalidateItem();
662 }
663}
664
665
677{
678 if (span != m_rowSpan) {
679 m_rowSpan = span;
680 invalidateItem();
682 }
683}
684
685
697{
698 if (span != m_columnSpan) {
699 m_columnSpan = span;
700 invalidateItem();
702 }
703}
704
705
707{
708 qreal result = 0;
709 if (QQuickLayout *layout = qobject_cast<QQuickLayout *>(item())) {
710 const QSizeF sz = layout->sizeHint(which);
711 result = (orientation == Qt::Horizontal ? sz.width() : sz.height());
712 } else {
713 if (which == Qt::MaximumSize)
714 result = std::numeric_limits<qreal>::infinity();
715 }
716 return result;
717}
718
719void QQuickLayoutAttached::invalidateItem()
720{
721 qCDebug(lcQuickLayouts) << "QQuickLayoutAttached::invalidateItem";
722 if (QQuickLayout *layout = parentLayout()) {
723 layout->invalidate(item());
724 }
725}
726
727QQuickLayout *QQuickLayoutAttached::parentLayout() const
728{
729 QQuickItem *parentItem = item();
730 if (parentItem) {
731 parentItem = parentItem->parentItem();
732 return qobject_cast<QQuickLayout *>(parentItem);
733 } else {
734 qmlWarning(parent()) << "Layout must be attached to Item elements";
735 }
736 return nullptr;
737}
738
739QQuickItem *QQuickLayoutAttached::item() const
740{
742}
743
745{
746 Q_Q(const QQuickLayout);
747
748 QQuickLayout *that = const_cast<QQuickLayout*>(q);
750
751 const QSizeF min = q->sizeHint(Qt::MinimumSize);
752 const QSizeF max = q->sizeHint(Qt::MaximumSize);
753 const QSizeF pref = q->sizeHint(Qt::PreferredSize);
754 info->setMinimumImplicitSize(min);
755 info->setMaximumImplicitSize(max);
756 that->setImplicitSize(pref.width(), pref.height());
757}
758
760 : QQuickItem(dd, parent)
761 , m_inUpdatePolish(false)
762 , m_polishInsideUpdatePolish(0)
763{
764}
765
766static QQuickItemPrivate::ChangeTypes changeTypes =
772
774{
775 d_func()->m_isReady = false;
776
777 const auto childItems = d_func()->childItems;
780}
781
783{
784 return new QQuickLayoutAttached(object);
785}
786
788{
789 qCDebug(lcQuickLayouts) << "updatePolish() ENTERING" << this;
790 m_inUpdatePolish = true;
791
792 // Might have become "undirty" before we reach this updatePolish()
793 // (e.g. if somebody queried for implicitWidth it will immediately
794 // calculate size hints)
795 // Note that we need to call ensureLayoutItemsUpdated() *before* we query width() and height(),
796 // because width()/height() might return their implicitWidth/implicitHeight (e.g. for a layout
797 // with no explicitly specified size, (nor anchors.fill: parent))
800 m_inUpdatePolish = false;
801 qCDebug(lcQuickLayouts) << "updatePolish() LEAVING" << this;
802}
803
805{
806 Q_D(QQuickLayout);
807 d->m_disableRearrange = true;
808 QQuickItem::componentComplete(); // will call our geometryChange(), (where isComponentComplete() == true)
809 d->m_disableRearrange = false;
810 d->m_isReady = true;
811}
812
814{
816 if (info) {
817 if (info->alignment() == Qt::AlignBaseline && static_cast<QQuickLayout*>(item->parentItem()) == this) {
819 } else {
821 }
822 }
823}
824
826{
827 Q_D(QQuickLayout);
828 if (invalidated())
829 return;
830
831 qCDebug(lcQuickLayouts) << "QQuickLayout::invalidate()" << this;
832 d->m_dirty = true;
833 d->m_dirtyArrangement = true;
834
835 if (!qobject_cast<QQuickLayout *>(parentItem())) {
836
837 if (m_inUpdatePolish)
838 ++m_polishInsideUpdatePolish;
839 else
840 m_polishInsideUpdatePolish = 0;
841
842 if (m_polishInsideUpdatePolish <= 2) {
843 // allow at most two consecutive loops in order to respond to height-for-width
844 // (e.g QQuickText changes implicitHeight when its width gets changed)
845 qCDebug(lcQuickLayouts) << "QQuickLayout::invalidate(), polish()";
846 polish();
847 } else {
848 qmlWarning(this).nospace() << "Layout polish loop detected for " << this
849 << ". Aborting after two iterations.";
850 }
851 }
852}
853
855{
857 bool ignoreItem = !childPrivate->explicitVisible;
858 if (!ignoreItem && childPrivate->isTransparentForPositioner())
859 ignoreItem = true;
860 return ignoreItem;
861}
862
864{
867 qmlWarning(item) << "Detected anchors on an item that is managed by a layout. This is undefined behavior; use Layout.alignment instead.";
868}
869
870void QQuickLayout::ensureLayoutItemsUpdated(EnsureLayoutItemsUpdatedOptions options) const
871{
872 Q_D(const QQuickLayout);
873 if (!invalidated())
874 return;
875 qCDebug(lcQuickLayouts) << "ENTER QQuickLayout::ensureLayoutItemsUpdated()" << this << options;
877
878 // breadth-first
879 // must update the root first, and continue towards the leaf nodes.
880 // Otherwise, we wouldn't know which children to traverse to
881 const_cast<QQuickLayout*>(this)->updateLayoutItems();
882
883 // make invalidate() return true
884 d->m_dirty = false;
885
886 if (options & Recursive) {
887 for (int i = 0; i < itemCount(); ++i) {
888 QQuickItem *itm = itemAt(i);
889 if (QQuickLayout *lay = qobject_cast<QQuickLayout*>(itm)) {
890 lay->ensureLayoutItemsUpdated(options);
891 }
892 }
893 }
894
895 // size hints are updated depth-first (parent size hints depends on their childrens size hints)
896 if (options & ApplySizeHints)
897 priv->applySizeHints();
898 qCDebug(lcQuickLayouts) << "LEAVE QQuickLayout::ensureLayoutItemsUpdated()" << this;
899}
900
901
903{
904 if (change == ItemChildAddedChange) {
905 Q_D(QQuickLayout);
906 QQuickItem *item = value.item;
909 d->m_hasItemChangeListeners = true;
910 qCDebug(lcQuickLayouts) << "ChildAdded" << item;
911 if (isReady())
912 invalidate();
913 } else if (change == ItemChildRemovedChange) {
914 QQuickItem *item = value.item;
917 qCDebug(lcQuickLayouts) << "ChildRemoved" << item;
918 if (isReady())
919 invalidate();
920 }
922}
923
924void QQuickLayout::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
925{
926 Q_D(QQuickLayout);
927 QQuickItem::geometryChange(newGeometry, oldGeometry);
928 if (d->m_disableRearrange || !isReady())
929 return;
930
931 qCDebug(lcQuickLayouts) << "QQuickLayout::geometryChange" << newGeometry << oldGeometry;
932 rearrange(newGeometry.size());
933}
934
936{
937 if (!isReady())
938 return;
939 QQuickItem *item = static_cast<QQuickItem *>(sender());
940 Q_ASSERT(item);
942}
943
945{
946 return d_func()->m_isReady;
947}
948
958{
959 if (d_func()->m_hasItemChangeListeners) {
961 for (int i = 0; i < itemCount(); ++i) {
963 // When deleting a layout with children, there is no reason for the children to inform the layout that their
964 // e.g. visibility got changed. The layout already knows that all its children will eventually become invisible, so
965 // we therefore remove its change listener.
967 if (QQuickLayout *layout = qobject_cast<QQuickLayout*>(item))
968 layout->deactivateRecur();
969 }
970 d_func()->m_hasItemChangeListeners = false;
971 }
972}
973
975{
976 return d_func()->m_dirty;
977}
978
980{
981 return d_func()->m_dirtyArrangement;
982}
983
985{
986 return d_func()->isMirrored();
987}
988
990{
991 Q_UNUSED(item);
992 invalidate();
993}
994
996{
997 if (!isReady() || item->signalsBlocked())
998 return;
1000}
1001
1003{
1004 if (!isReady() || item->signalsBlocked())
1005 return;
1007}
1008
1010{
1011 Q_UNUSED(item);
1012}
1013
1015{
1016 Q_UNUSED(item);
1017}
1018
1019void QQuickLayout::rearrange(const QSizeF &/*size*/)
1020{
1021 d_func()->m_dirtyArrangement = false;
1022}
1023
1024
1025/*
1026 The layout engine assumes:
1027 1. minimum <= preferred <= maximum
1028 2. descent is within minimum and maximum bounds (### verify)
1029
1030 This function helps to ensure that by the following rules (in the following order):
1031 1. If minimum > maximum, set minimum = maximum
1032 2. Clamp preferred to be between the [minimum,maximum] range.
1033 3. If descent > minimum, set descent = minimum (### verify if this is correct, it might
1034 need some refinements to multiline texts)
1035
1036 If any values are "not set" (i.e. negative), they will be left untouched, so that we
1037 know which values needs to be fetched from the implicit hints (not user hints).
1038 */
1039static void normalizeHints(qreal &minimum, qreal &preferred, qreal &maximum, qreal &descent)
1040{
1041 if (minimum >= 0 && maximum >= 0 && minimum > maximum)
1042 minimum = maximum;
1043
1044 if (preferred >= 0) {
1045 if (minimum >= 0 && preferred < minimum) {
1046 preferred = minimum;
1047 } else if (maximum >= 0 && preferred > maximum) {
1048 preferred = maximum;
1049 }
1050 }
1051
1052 if (minimum >= 0 && descent > minimum)
1053 descent = minimum;
1054}
1055
1056static void boundSize(QSizeF &result, const QSizeF &size)
1057{
1058 if (size.width() >= 0 && size.width() < result.width())
1059 result.setWidth(size.width());
1060 if (size.height() >= 0 && size.height() < result.height())
1061 result.setHeight(size.height());
1062}
1063
1064static void expandSize(QSizeF &result, const QSizeF &size)
1065{
1066 if (size.width() >= 0 && size.width() > result.width())
1067 result.setWidth(size.width());
1068 if (size.height() >= 0 && size.height() > result.height())
1069 result.setHeight(size.height());
1070}
1071
1072static inline void combineHints(qreal &current, qreal fallbackHint)
1073{
1074 if (current < 0)
1075 current = fallbackHint;
1076}
1077
1078static inline void combineSize(QSizeF &result, const QSizeF &fallbackSize)
1079{
1080 combineHints(result.rwidth(), fallbackSize.width());
1081 combineHints(result.rheight(), fallbackSize.height());
1082}
1083
1085{
1086 if (!info) return;
1087
1088 Q_ASSERT(which == Qt::MinimumSize || which == Qt::MaximumSize);
1089
1090 const QSizeF constraint(which == Qt::MinimumSize
1091 ? QSizeF(info->minimumWidth(), info->minimumHeight())
1092 : QSizeF(info->maximumWidth(), info->maximumHeight()));
1093
1094 if (!info->isExtentExplicitlySet(Qt::Horizontal, which))
1095 combineHints(size->rwidth(), constraint.width());
1096 if (!info->isExtentExplicitlySet(Qt::Vertical, which))
1097 combineHints(size->rheight(), constraint.height());
1098}
1099
1101
1134void QQuickLayout::effectiveSizeHints_helper(QQuickItem *item, QSizeF *cachedSizeHints, QQuickLayoutAttached **attachedInfo, bool useFallbackToWidthOrHeight)
1135{
1136 for (int i = 0; i < Qt::NSizeHints; ++i)
1137 cachedSizeHints[i] = QSizeF();
1139 // First, retrieve the user-specified hints from the attached "Layout." properties
1140 if (info) {
1141 struct Getters {
1142 SizeGetter call[NSizes];
1143 };
1144
1145 static Getters horGetters = {
1147 };
1148
1149 static Getters verGetters = {
1151 };
1152 for (int i = 0; i < NSizes; ++i) {
1153 SizeGetter getter = horGetters.call[i];
1154 Q_ASSERT(getter);
1155
1156 if (info->isExtentExplicitlySet(Qt::Horizontal, (Qt::SizeHint)i))
1157 cachedSizeHints[i].setWidth((info->*getter)());
1158
1159 getter = verGetters.call[i];
1160 Q_ASSERT(getter);
1161 if (info->isExtentExplicitlySet(Qt::Vertical, (Qt::SizeHint)i))
1162 cachedSizeHints[i].setHeight((info->*getter)());
1163 }
1164 }
1165
1166 QSizeF &minS = cachedSizeHints[Qt::MinimumSize];
1167 QSizeF &prefS = cachedSizeHints[Qt::PreferredSize];
1168 QSizeF &maxS = cachedSizeHints[Qt::MaximumSize];
1169 QSizeF &descentS = cachedSizeHints[Qt::MinimumDescent];
1170
1171 // For instance, will normalize the following user-set hints
1172 // from: [10, 5, 60]
1173 // to: [10, 10, 60]
1174 normalizeHints(minS.rwidth(), prefS.rwidth(), maxS.rwidth(), descentS.rwidth());
1175 normalizeHints(minS.rheight(), prefS.rheight(), maxS.rheight(), descentS.rheight());
1176
1177 // All explicit values gathered, now continue to gather the implicit sizes
1178
1179 //--- GATHER MAXIMUM SIZE HINTS ---
1181 combineSize(maxS, QSizeF(std::numeric_limits<qreal>::infinity(), std::numeric_limits<qreal>::infinity()));
1182 // implicit max or min sizes should not limit an explicitly set preferred size
1183 expandSize(maxS, prefS);
1184 expandSize(maxS, minS);
1185
1186 //--- GATHER MINIMUM SIZE HINTS ---
1188 expandSize(minS, QSizeF(0,0));
1189 boundSize(minS, prefS);
1190 boundSize(minS, maxS);
1191
1192 //--- GATHER PREFERRED SIZE HINTS ---
1193 // First, from implicitWidth/Height
1194 qreal &prefWidth = prefS.rwidth();
1195 qreal &prefHeight = prefS.rheight();
1196 if (prefWidth < 0 && item->implicitWidth() > 0)
1197 prefWidth = qCeil(item->implicitWidth());
1198 if (prefHeight < 0 && item->implicitHeight() > 0)
1199 prefHeight = qCeil(item->implicitHeight());
1200
1201 // If that fails, make an ultimate fallback to width/height
1202 if (useFallbackToWidthOrHeight && !prefS.isValid()) {
1203 /* If we want to support using width/height as preferred size hints in
1204 layouts, (which we think most people expect), we only want to use the
1205 initial width.
1206 This is because the width will change due to layout rearrangement,
1207 and the preferred width should return the same value, regardless of
1208 the current width.
1209 We therefore store this initial width in the attached layout object
1210 and reuse it if needed rather than querying the width another time.
1211 That means we need to ensure that an Layout attached object is available
1212 by creating one if necessary.
1213 */
1214 if (!info)
1216
1217 auto updatePreferredSizes = [](qreal &cachedSize, qreal &attachedSize, qreal size) {
1218 if (cachedSize < 0) {
1219 if (attachedSize < 0)
1220 attachedSize = size;
1221
1222 cachedSize = attachedSize;
1223 }
1224 };
1225 updatePreferredSizes(prefWidth, info->m_fallbackWidth, item->width());
1226 updatePreferredSizes(prefHeight, info->m_fallbackHeight, item->height());
1227 }
1228
1229 // Normalize again after the implicit hints have been gathered
1230 expandSize(prefS, minS);
1231 boundSize(prefS, maxS);
1232
1233 //--- GATHER DESCENT
1234 // Minimum descent is only applicable for the effective minimum height,
1235 // so we gather the descent last.
1236 const qreal minimumDescent = minS.height() - item->baselineOffset();
1237 descentS.setHeight(minimumDescent);
1238
1239 if (info) {
1240 QMarginsF margins = info->qMargins();
1241 QSizeF extraMargins(margins.left() + margins.right(), margins.top() + margins.bottom());
1242 minS += extraMargins;
1243 prefS += extraMargins;
1244 maxS += extraMargins;
1245 descentS += extraMargins;
1246 }
1247 if (attachedInfo)
1248 *attachedInfo = info;
1249}
1250
1257{
1258 bool fillExtent = false;
1259 bool isSet = false;
1260 if (info) {
1261 if (orientation == Qt::Horizontal) {
1262 isSet = info->isFillWidthSet();
1263 if (isSet) fillExtent = info->fillWidth();
1264 } else {
1265 isSet = info->isFillHeightSet();
1266 if (isSet) fillExtent = info->fillHeight();
1267 }
1268 }
1269 if (!isSet && qobject_cast<QQuickLayout*>(item))
1270 fillExtent = true;
1271 return fillExtent ? QLayoutPolicy::Preferred : QLayoutPolicy::Fixed;
1272
1273}
1274
1276{
1277 QString buf;
1279 qDebug("\n%s", qPrintable(buf));
1280}
1281
1283{
1284 auto formatLine = [&level](const char *fmt) -> QString {
1285 QString ss(level *4, QLatin1Char(' '));
1286 return ss + QLatin1String(fmt) + QLatin1Char('\n');
1287 };
1288
1289 auto f2s = [](qreal f) {
1290 return QString::number(f);
1291 };
1292 auto b2s = [](bool b) {
1293 static const char *strBool[] = {"false", "true"};
1294 return QLatin1String(strBool[int(b)]);
1295 };
1296
1297 buf += formatLine("%1 {").arg(QQmlMetaType::prettyTypeName(this));
1298 ++level;
1299 buf += formatLine("// Effective calculated values:");
1300 buf += formatLine("sizeHintDirty: %2").arg(invalidated());
1302 buf += formatLine("sizeHint.min : [%1, %2]").arg(f2s(min.width()), 5).arg(min.height(), 5);
1304 buf += formatLine("sizeHint.pref: [%1, %2]").arg(pref.width(), 5).arg(pref.height(), 5);
1306 buf += formatLine("sizeHint.max : [%1, %2]").arg(f2s(max.width()), 5).arg(f2s(max.height()), 5);
1307
1308 for (QQuickItem *item : childItems()) {
1309 buf += QLatin1Char('\n');
1310 if (QQuickLayout *childLayout = qobject_cast<QQuickLayout*>(item)) {
1311 childLayout->dumpLayoutTreeRecursive(level, buf);
1312 } else {
1313 buf += formatLine("%1 {").arg(QQmlMetaType::prettyTypeName(item));
1314 ++level;
1315 if (item->implicitWidth() > 0)
1316 buf += formatLine("implicitWidth: %1").arg(f2s(item->implicitWidth()));
1317 if (item->implicitHeight() > 0)
1318 buf += formatLine("implicitHeight: %1").arg(f2s(item->implicitHeight()));
1319 QSizeF min;
1320 QSizeF pref;
1321 QSizeF max;
1323 if (info) {
1324 min = QSizeF(info->minimumWidth(), info->minimumHeight());
1325 pref = QSizeF(info->preferredWidth(), info->preferredHeight());
1326 max = QSizeF(info->maximumWidth(), info->maximumHeight());
1327 if (info->isExtentExplicitlySet(Qt::Horizontal, Qt::MinimumSize))
1328 buf += formatLine("Layout.minimumWidth: %1").arg(f2s(min.width()));
1329 if (info->isExtentExplicitlySet(Qt::Vertical, Qt::MinimumSize))
1330 buf += formatLine("Layout.minimumHeight: %1").arg(f2s(min.height()));
1331 if (pref.width() >= 0)
1332 buf += formatLine("Layout.preferredWidth: %1").arg(f2s(pref.width()));
1333 if (pref.height() >= 0)
1334 buf += formatLine("Layout.preferredHeight: %1").arg(f2s(pref.height()));
1335 if (info->isExtentExplicitlySet(Qt::Horizontal, Qt::MaximumSize))
1336 buf += formatLine("Layout.maximumWidth: %1").arg(f2s(max.width()));
1337 if (info->isExtentExplicitlySet(Qt::Vertical, Qt::MaximumSize))
1338 buf += formatLine("Layout.maximumHeight: %1").arg(f2s(max.height()));
1339
1340 if (info->isFillWidthSet())
1341 buf += formatLine("Layout.fillWidth: %1").arg(b2s(info->fillWidth()));
1342 if (info->isFillHeightSet())
1343 buf += formatLine("Layout.fillHeight: %1").arg(b2s(info->fillHeight()));
1344 }
1345 --level;
1346 buf += formatLine("}");
1347 }
1348 }
1349 --level;
1350 buf += formatLine("}");
1351}
1352
1354
1355#include "moc_qquicklayout_p.cpp"
void invalidate() override
Resets cached information.
QSize sizeHint() const override
\reimp
bool setStretchFactor(QWidget *w, int stretch)
Sets the stretch factor for widget to stretch and returns true if widget is found in this layout (not...
QGraphicsItem * parentItem() const
Returns a pointer to this item's parent item.
static constexpr Policy Preferred
static constexpr Policy Fixed
bool setAlignment(QWidget *w, Qt::Alignment alignment)
Sets the alignment for widget w to alignment and returns true if w is found in this layout (not inclu...
Definition qlayout.cpp:199
\inmodule QtCore
Definition qmargins.h:274
constexpr qreal right() const noexcept
Returns the right margin.
Definition qmargins.h:370
constexpr qreal left() const noexcept
Returns the left margin.
Definition qmargins.h:364
constexpr qreal top() const noexcept
Returns the top margin.
Definition qmargins.h:367
constexpr void setLeft(qreal aleft) noexcept
Sets the left margin to aleft (which must be finite).
Definition qmargins.h:377
constexpr void setRight(qreal aright) noexcept
Sets the right margin to aright (which must be finite).
Definition qmargins.h:383
constexpr void setBottom(qreal abottom) noexcept
Sets the bottom margin to abottom (which must be finite).
Definition qmargins.h:386
constexpr void setTop(qreal atop) noexcept
Sets the top margin to atop (which must be finite).
Definition qmargins.h:380
constexpr qreal bottom() const noexcept
Returns the bottom margin.
Definition qmargins.h:373
\inmodule QtCore
Definition qobject.h:90
QObject * parent() const
Returns a pointer to the parent object.
Definition qobject.h:311
QObject * sender() const
Returns a pointer to the object that sent the signal, if called in a slot activated by a signal; othe...
Definition qobject.cpp:2521
static QString prettyTypeName(const QObject *object)
Returns the pretty QML type name (e.g.
Qt::Orientations activeDirections() const
QQuickAnchors * _anchors
void removeItemChangeListener(QQuickItemChangeListener *, ChangeTypes types)
void addItemChangeListener(QQuickItemChangeListener *listener, ChangeTypes types)
static QQuickItemPrivate * get(QQuickItem *item)
bool isTransparentForPositioner() const
The QQuickItem class provides the most basic of all visual items in \l {Qt Quick}.
Definition qquickitem.h:64
void baselineOffsetChanged(qreal)
QList< QQuickItem * > childItems() const
Returns the children of this item.
virtual void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
qreal implicitWidth
Definition qquickitem.h:113
void componentComplete() override
\reimp Derived classes should call the base class method before adding their own actions to perform a...
QSizeF size() const
qreal width
This property holds the width of this item.
Definition qquickitem.h:76
QQuickItem * parentItem() const
virtual void itemChange(ItemChange, const ItemChangeData &)
Called when change occurs for this item.
qreal implicitHeight
Definition qquickitem.h:114
qreal height
This property holds the height of this item.
Definition qquickitem.h:77
ItemChange
Used in conjunction with QQuickItem::itemChange() to notify the item about certain types of changes.
Definition qquickitem.h:143
@ ItemChildAddedChange
Definition qquickitem.h:144
@ ItemChildRemovedChange
Definition qquickitem.h:145
void polish()
Schedules a polish event for this item.
void setImplicitSize(qreal, qreal)
void setMaximumWidth(qreal width)
\qmlattachedproperty real Layout::maximumWidth
void setBottomMargin(qreal m)
\qmlattachedproperty real Layout::bottomMargin
void setMaximumImplicitSize(const QSizeF &sz)
void setMinimumImplicitSize(const QSizeF &sz)
void setMinimumHeight(qreal height)
\qmlattachedproperty real Layout::minimumHeight
void setFillWidth(bool fill)
\qmlattachedproperty bool Layout::fillWidth
void setColumnSpan(int span)
\qmlattachedproperty int Layout::columnSpan
void setFillHeight(bool fill)
\qmlattachedproperty bool Layout::fillHeight
void setRow(int row)
\qmlattachedproperty int Layout::row
void setLeftMargin(qreal m)
\qmlattachedproperty real Layout::leftMargin
void setMaximumHeight(qreal height)
\qmlattachedproperty real Layout::maximumHeight
void setMinimumWidth(qreal width)
\qmlattachedproperty real Layout::minimumWidth
void setRowSpan(int span)
\qmlattachedproperty int Layout::rowSpan
void setMargins(qreal m)
\qmlattachedproperty real Layout::margins
void setVerticalStretchFactor(int stretchFactor)
\qmlattachedproperty int Layout::verticalStretchFactor
void setPreferredHeight(qreal width)
\qmlattachedproperty real Layout::preferredHeight
void setAlignment(Qt::Alignment align)
\qmlattachedproperty Qt.Alignment Layout::alignment
qreal sizeHint(Qt::SizeHint which, Qt::Orientation orientation) const
void setPreferredWidth(qreal width)
\qmlattachedproperty real Layout::preferredWidth
void setColumn(int column)
\qmlattachedproperty int Layout::column
void horizontalStretchFactorChanged()
void setTopMargin(qreal m)
\qmlattachedproperty real Layout::topMargin
void setHorizontalStretchFactor(int stretchFactor)
\qmlattachedproperty int Layout::horizontalStretchFactor
void setRightMargin(qreal m)
\qmlattachedproperty real Layout::rightMargin
void verticalStretchFactorChanged()
void applySizeHints() const
bool invalidated() const
bool isReady() const
bool invalidatedArrangement() const
static QLayoutPolicy::Policy effectiveSizePolicy_helper(QQuickItem *item, Qt::Orientation orientation, QQuickLayoutAttached *info)
Q_INVOKABLE void _q_dumpLayoutTree() const
void itemChange(ItemChange change, const ItemChangeData &value) override
Called when change occurs for this item.
void itemSiblingOrderChanged(QQuickItem *item) override
void itemImplicitHeightChanged(QQuickItem *item) override
void itemDestroyed(QQuickItem *item) override
void maybeSubscribeToBaseLineOffsetChanges(QQuickItem *item)
static void effectiveSizeHints_helper(QQuickItem *item, QSizeF *cachedSizeHints, QQuickLayoutAttached **info, bool useFallbackToWidthOrHeight)
friend class QQuickLayoutAttached
void updatePolish() override
This function should perform any layout as required for this item.
virtual void rearrange(const QSizeF &)
QQuickLayout(QQuickLayoutPrivate &dd, QQuickItem *parent=nullptr)
void itemVisibilityChanged(QQuickItem *item) override
virtual void invalidate(QQuickItem *childItem=nullptr)
void dumpLayoutTreeRecursive(int level, QString &buf) const
static QQuickLayoutAttached * qmlAttachedProperties(QObject *object)
bool isMirrored() const
bool shouldIgnoreItem(QQuickItem *child) const
virtual void updateLayoutItems()=0
void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override
virtual QQuickItem * itemAt(int index) const =0
void checkAnchors(QQuickItem *item) const
void ensureLayoutItemsUpdated(EnsureLayoutItemsUpdatedOptions options={}) const
void componentComplete() override
\reimp Derived classes should call the base class method before adding their own actions to perform a...
void invalidateSenderItem()
void itemImplicitWidthChanged(QQuickItem *item) override
virtual QSizeF sizeHint(Qt::SizeHint whichSizeHint) const =0
virtual int itemCount() const =0
void deactivateRecur()
QQuickLayout::deactivateRecur.
\inmodule QtCore\reentrant
Definition qrect.h:483
constexpr QSizeF size() const noexcept
Returns the size of the rectangle.
Definition qrect.h:721
\inmodule QtCore
Definition qsize.h:207
constexpr qreal & rwidth() noexcept
Returns a reference to the width.
Definition qsize.h:345
constexpr bool isValid() const noexcept
Returns true if both the width and height are equal to or greater than 0; otherwise returns false.
Definition qsize.h:318
constexpr void setHeight(qreal h) noexcept
Sets the height to the given finite height.
Definition qsize.h:330
constexpr qreal & rheight() noexcept
Returns a reference to the height.
Definition qsize.h:348
constexpr void setWidth(qreal w) noexcept
Sets the width to the given finite width.
Definition qsize.h:327
constexpr qreal width() const noexcept
Returns the width.
Definition qsize.h:321
constexpr qreal height() const noexcept
Returns the height.
Definition qsize.h:324
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:7822
Combined button and popup list for selecting options.
@ AlignBaseline
Definition qnamespace.h:155
Orientation
Definition qnamespace.h:97
@ Horizontal
Definition qnamespace.h:98
@ Vertical
Definition qnamespace.h:99
@ MaximumSize
@ PreferredSize
@ MinimumDescent
@ MinimumSize
@ NSizeHints
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
static void normalizeHints(qreal &minimum, qreal &preferred, qreal &maximum, qreal &descent)
static void boundSize(QSizeF &result, const QSizeF &size)
static void combineSize(QSizeF &result, const QSizeF &size)
static void expandSize(QSizeF &result, const QSizeF &size)
#define qDebug
[1]
Definition qlogging.h:160
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
int qCeil(T v)
Definition qmath.h:36
static const QMetaObjectPrivate * priv(const uint *data)
static Q_DECL_CONST_FUNCTION bool qt_is_nan(double d)
Definition qnumeric_p.h:106
#define SLOT(a)
Definition qobjectdefs.h:51
#define SIGNAL(a)
Definition qobjectdefs.h:52
GLboolean GLboolean GLboolean b
const GLfloat * m
GLenum GLuint GLint level
GLint GLsizei GLsizei height
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLfloat GLfloat f
GLint GLsizei width
GLenum GLuint GLenum GLsizei const GLchar * buf
GLenum GLenum GLsizei void GLsizei void * column
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLenum GLenum GLsizei void * row
GLenum GLenum GLsizei void GLsizei void void * span
GLuint64EXT * result
[6]
#define qmlobject_disconnect(Sender, SenderType, Signal, Receiver, ReceiverType, Method)
Disconnect Signal of Sender from Method of Receiver.
#define qmlobject_connect(Sender, SenderType, Signal, Receiver, ReceiverType, Method)
Connect Signal of Sender to Method of Receiver.
Q_QML_EXPORT QQmlInfo qmlWarning(const QObject *me)
QQuickAnchors * anchors(QQuickItem *item)
QQuickItem * qobject_cast< QQuickItem * >(QObject *o)
Definition qquickitem.h:483
static void combineHints(qreal &current, qreal fallbackHint)
static void combineImplicitHints(QQuickLayoutAttached *info, Qt::SizeHint which, QSizeF *size)
qreal(QQuickLayoutAttached::* SizeGetter)() const
static void normalizeHints(qreal &minimum, qreal &preferred, qreal &maximum, qreal &descent)
static QQuickItemPrivate::ChangeTypes changeTypes
static void boundSize(QSizeF &result, const QSizeF &size)
static void combineSize(QSizeF &result, const QSizeF &fallbackSize)
static void expandSize(QSizeF &result, const QSizeF &size)
QQuickLayoutAttached * attachedLayoutObject(QQuickItem *item, bool create=true)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define qPrintable(string)
Definition qstring.h:1391
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define emit
#define Q_UNUSED(x)
double qreal
Definition qtypes.h:92
QVideoFrameFormat::PixelFormat fmt
QFileInfo info(fileName)
[8]
QVBoxLayout * layout
ba fill(true)
QGraphicsItem * item
QLayoutItem * child
[0]
\inmodule QtCore \reentrant
Definition qchar.h:17
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent
\inmodule QtQuick
Definition qquickitem.h:158