Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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 bool oldFillWidth = fillWidth();
313 m_isFillWidthSet = true;
314 m_fillWidth = fill;
315 if (oldFillWidth != fill) {
316 invalidateItem();
318 }
319}
320
332{
333 bool oldFillHeight = fillHeight();
334 m_isFillHeightSet = true;
335 m_fillHeight = fill;
336 if (oldFillHeight != fill) {
337 invalidateItem();
339 }
340}
341
355{
356 if (row >= 0 && row != m_row) {
357 m_row = row;
358 invalidateItem();
360 }
361}
362
376{
377 if (column >= 0 && column != m_column) {
378 m_column = column;
379 invalidateItem();
381 }
382}
383
384
408void QQuickLayoutAttached::setAlignment(Qt::Alignment align)
409{
410 m_isAlignmentSet = true;
411 if (align != m_alignment) {
412 m_alignment = align;
413 if (QQuickLayout *layout = parentLayout()) {
414 layout->setAlignment(item(), align);
415 invalidateItem();
416 }
418 }
419}
420
447{
448 if (factor != m_horizontalStretch) {
449 m_horizontalStretch = factor;
450 if (QQuickLayout *layout = parentLayout()) {
451 layout->setStretchFactor(item(), factor, Qt::Horizontal);
452 invalidateItem();
453 }
455 }
456}
457
484{
485 if (factor != m_verticalStretch) {
486 m_verticalStretch = factor;
487 if (QQuickLayout *layout = parentLayout()) {
488 layout->setStretchFactor(item(), factor, Qt::Vertical);
489 invalidateItem();
490 }
492 }
493}
494
525{
526 m_isMarginsSet = true;
527 if (m == m_defaultMargins)
528 return;
529
530 m_defaultMargins = m;
531 invalidateItem();
532 if (!m_isLeftMarginSet && m_margins.left() != m)
534 if (!m_isTopMarginSet && m_margins.top() != m)
536 if (!m_isRightMarginSet && m_margins.right() != m)
538 if (!m_isBottomMarginSet && m_margins.bottom() != m)
541}
542
554{
555 const bool changed = leftMargin() != m;
556 m_margins.setLeft(m);
557 m_isLeftMarginSet = true;
558 if (changed) {
559 invalidateItem();
561 }
562}
563
565{
566 const bool changed = m_isLeftMarginSet && (m_defaultMargins != m_margins.left());
567 m_isLeftMarginSet = false;
568 if (changed) {
569 invalidateItem();
571 }
572}
573
585{
586 const bool changed = topMargin() != m;
587 m_margins.setTop(m);
588 m_isTopMarginSet = true;
589 if (changed) {
590 invalidateItem();
592 }
593}
594
596{
597 const bool changed = m_isTopMarginSet && (m_defaultMargins != m_margins.top());
598 m_isTopMarginSet = false;
599 if (changed) {
600 invalidateItem();
602 }
603}
604
616{
617 const bool changed = rightMargin() != m;
618 m_margins.setRight(m);
619 m_isRightMarginSet = true;
620 if (changed) {
621 invalidateItem();
623 }
624}
625
627{
628 const bool changed = m_isRightMarginSet && (m_defaultMargins != m_margins.right());
629 m_isRightMarginSet = false;
630 if (changed) {
631 invalidateItem();
633 }
634}
635
647{
648 const bool changed = bottomMargin() != m;
649 m_margins.setBottom(m);
650 m_isBottomMarginSet = true;
651 if (changed) {
652 invalidateItem();
654 }
655}
656
658{
659 const bool changed = m_isBottomMarginSet && (m_defaultMargins != m_margins.bottom());
660 m_isBottomMarginSet = false;
661 if (changed) {
662 invalidateItem();
664 }
665}
666
667
679{
680 if (span != m_rowSpan) {
681 m_rowSpan = span;
682 invalidateItem();
684 }
685}
686
687
699{
700 if (span != m_columnSpan) {
701 m_columnSpan = span;
702 invalidateItem();
704 }
705}
706
707
709{
710 qreal result = 0;
711 if (QQuickLayout *layout = qobject_cast<QQuickLayout *>(item())) {
712 const QSizeF sz = layout->sizeHint(which);
713 result = (orientation == Qt::Horizontal ? sz.width() : sz.height());
714 } else {
715 if (which == Qt::MaximumSize)
716 result = std::numeric_limits<qreal>::infinity();
717 }
718 return result;
719}
720
721void QQuickLayoutAttached::invalidateItem()
722{
723 qCDebug(lcQuickLayouts) << "QQuickLayoutAttached::invalidateItem";
724 if (QQuickLayout *layout = parentLayout()) {
725 layout->invalidate(item());
726 }
727}
728
729QQuickLayout *QQuickLayoutAttached::parentLayout() const
730{
731 QQuickItem *parentItem = item();
732 if (parentItem) {
733 parentItem = parentItem->parentItem();
734 return qobject_cast<QQuickLayout *>(parentItem);
735 } else {
736 qmlWarning(parent()) << "Layout must be attached to Item elements";
737 }
738 return nullptr;
739}
740
741QQuickItem *QQuickLayoutAttached::item() const
742{
744}
745
747{
748 Q_Q(const QQuickLayout);
749
750 QQuickLayout *that = const_cast<QQuickLayout*>(q);
752
753 const QSizeF min = q->sizeHint(Qt::MinimumSize);
754 const QSizeF max = q->sizeHint(Qt::MaximumSize);
755 const QSizeF pref = q->sizeHint(Qt::PreferredSize);
756 info->setMinimumImplicitSize(min);
757 info->setMaximumImplicitSize(max);
758 that->setImplicitSize(pref.width(), pref.height());
759}
760
762 : QQuickItem(dd, parent)
763 , m_inUpdatePolish(false)
764 , m_polishInsideUpdatePolish(0)
765{
766}
767
768static QQuickItemPrivate::ChangeTypes changeTypes =
774
776{
777 d_func()->m_isReady = false;
778
779 const auto childItems = d_func()->childItems;
781 QQuickItemPrivate::get(child)->removeItemChangeListener(this, changeTypes);
782}
783
788
790{
791 qCDebug(lcQuickLayouts) << "updatePolish() ENTERING" << this;
792 m_inUpdatePolish = true;
793
794 // Might have become "undirty" before we reach this updatePolish()
795 // (e.g. if somebody queried for implicitWidth it will immediately
796 // calculate size hints)
797 // Note that we need to call ensureLayoutItemsUpdated() *before* we query width() and height(),
798 // because width()/height() might return their implicitWidth/implicitHeight (e.g. for a layout
799 // with no explicitly specified size, (nor anchors.fill: parent))
802 m_inUpdatePolish = false;
803 qCDebug(lcQuickLayouts) << "updatePolish() LEAVING" << this;
804}
805
807{
808 Q_D(QQuickLayout);
809 d->m_disableRearrange = true;
810 QQuickItem::componentComplete(); // will call our geometryChange(), (where isComponentComplete() == true)
811 d->m_disableRearrange = false;
812 d->m_isReady = true;
813}
814
826
828{
829 Q_D(QQuickLayout);
830 if (invalidated())
831 return;
832
833 qCDebug(lcQuickLayouts) << "QQuickLayout::invalidate()" << this;
834 d->m_dirty = true;
835 d->m_dirtyArrangement = true;
836
837 if (!qobject_cast<QQuickLayout *>(parentItem())) {
838 polish();
839
840 if (m_inUpdatePolish) {
841 if (++m_polishInsideUpdatePolish > 2)
842 // allow at most two consecutive loops in order to respond to height-for-width
843 // (e.g QQuickText changes implicitHeight when its width gets changed)
844 qCDebug(lcQuickLayouts) << "Layout polish loop detected for " << this
845 << ". The polish request will still be scheduled.";
846 } else {
847 m_polishInsideUpdatePolish = 0;
848 }
849 }
850}
851
853{
855 bool ignoreItem = !childPrivate->explicitVisible;
856 if (!ignoreItem && childPrivate->isTransparentForPositioner())
857 ignoreItem = true;
858 return ignoreItem;
859}
860
862{
865 qmlWarning(item) << "Detected anchors on an item that is managed by a layout. This is undefined behavior; use Layout.alignment instead.";
866}
867
868void QQuickLayout::ensureLayoutItemsUpdated(EnsureLayoutItemsUpdatedOptions options) const
869{
870 Q_D(const QQuickLayout);
871 if (!invalidated())
872 return;
873 qCDebug(lcQuickLayouts) << "ENTER QQuickLayout::ensureLayoutItemsUpdated()" << this << options;
875
876 // breadth-first
877 // must update the root first, and continue towards the leaf nodes.
878 // Otherwise, we wouldn't know which children to traverse to
879 const_cast<QQuickLayout*>(this)->updateLayoutItems();
880
881 // make invalidate() return true
882 d->m_dirty = false;
883
884 if (options & Recursive) {
885 for (int i = 0; i < itemCount(); ++i) {
886 QQuickItem *itm = itemAt(i);
887 if (QQuickLayout *lay = qobject_cast<QQuickLayout*>(itm)) {
888 lay->ensureLayoutItemsUpdated(options);
889 }
890 }
891 }
892
893 // size hints are updated depth-first (parent size hints depends on their childrens size hints)
894 if (options & ApplySizeHints)
895 priv->applySizeHints();
896 qCDebug(lcQuickLayouts) << "LEAVE QQuickLayout::ensureLayoutItemsUpdated()" << this;
897}
898
899
901{
902 if (change == ItemChildAddedChange) {
903 Q_D(QQuickLayout);
904 QQuickItem *item = value.item;
906 QQuickItemPrivate::get(item)->addItemChangeListener(this, changeTypes);
907 d->m_hasItemChangeListeners = true;
908 qCDebug(lcQuickLayouts) << "ChildAdded" << item;
909 if (isReady())
910 invalidate();
911 } else if (change == ItemChildRemovedChange) {
912 QQuickItem *item = value.item;
914 QQuickItemPrivate::get(item)->removeItemChangeListener(this, changeTypes);
915 qCDebug(lcQuickLayouts) << "ChildRemoved" << item;
916 if (isReady())
917 invalidate();
918 }
920}
921
922void QQuickLayout::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
923{
924 Q_D(QQuickLayout);
925 QQuickItem::geometryChange(newGeometry, oldGeometry);
926 if (invalidated() || d->m_disableRearrange || !isReady())
927 return;
928
929 qCDebug(lcQuickLayouts) << "QQuickLayout::geometryChange" << newGeometry << oldGeometry;
930 rearrange(newGeometry.size());
931}
932
934{
935 if (!isReady())
936 return;
937 QQuickItem *item = static_cast<QQuickItem *>(sender());
938 Q_ASSERT(item);
940}
941
943{
944 return d_func()->m_isReady;
945}
946
956{
957 if (d_func()->m_hasItemChangeListeners) {
959 for (int i = 0; i < itemCount(); ++i) {
961 // When deleting a layout with children, there is no reason for the children to inform the layout that their
962 // e.g. visibility got changed. The layout already knows that all its children will eventually become invisible, so
963 // we therefore remove its change listener.
964 QQuickItemPrivate::get(item)->removeItemChangeListener(this, changeTypes);
965 if (QQuickLayout *layout = qobject_cast<QQuickLayout*>(item))
966 layout->deactivateRecur();
967 }
968 d_func()->m_hasItemChangeListeners = false;
969 }
970}
971
973{
974 return d_func()->m_dirty;
975}
976
978{
979 return d_func()->m_dirtyArrangement;
980}
981
983{
984 return d_func()->isMirrored();
985}
986
992
994{
995 if (!isReady() || item->signalsBlocked())
996 return;
998}
999
1001{
1002 if (!isReady() || item->signalsBlocked())
1003 return;
1005}
1006
1011
1016
1017void QQuickLayout::rearrange(const QSizeF &/*size*/)
1018{
1019 d_func()->m_dirtyArrangement = false;
1020}
1021
1022
1023/*
1024 The layout engine assumes:
1025 1. minimum <= preferred <= maximum
1026 2. descent is within minimum and maximum bounds (### verify)
1027
1028 This function helps to ensure that by the following rules (in the following order):
1029 1. If minimum > maximum, set minimum = maximum
1030 2. Clamp preferred to be between the [minimum,maximum] range.
1031 3. If descent > minimum, set descent = minimum (### verify if this is correct, it might
1032 need some refinements to multiline texts)
1033
1034 If any values are "not set" (i.e. negative), they will be left untouched, so that we
1035 know which values needs to be fetched from the implicit hints (not user hints).
1036 */
1037static void normalizeHints(qreal &minimum, qreal &preferred, qreal &maximum, qreal &descent)
1038{
1039 if (minimum >= 0 && maximum >= 0 && minimum > maximum)
1040 minimum = maximum;
1041
1042 if (preferred >= 0) {
1043 if (minimum >= 0 && preferred < minimum) {
1044 preferred = minimum;
1045 } else if (maximum >= 0 && preferred > maximum) {
1046 preferred = maximum;
1047 }
1048 }
1049
1050 if (minimum >= 0 && descent > minimum)
1051 descent = minimum;
1052}
1053
1054static void boundSize(QSizeF &result, const QSizeF &size)
1055{
1056 if (size.width() >= 0 && size.width() < result.width())
1057 result.setWidth(size.width());
1058 if (size.height() >= 0 && size.height() < result.height())
1059 result.setHeight(size.height());
1060}
1061
1062static void expandSize(QSizeF &result, const QSizeF &size)
1063{
1064 if (size.width() >= 0 && size.width() > result.width())
1065 result.setWidth(size.width());
1066 if (size.height() >= 0 && size.height() > result.height())
1067 result.setHeight(size.height());
1068}
1069
1070static inline void combineHints(qreal &current, qreal fallbackHint)
1071{
1072 if (current < 0)
1073 current = fallbackHint;
1074}
1075
1076static inline void combineSize(QSizeF &result, const QSizeF &fallbackSize)
1077{
1078 combineHints(result.rwidth(), fallbackSize.width());
1079 combineHints(result.rheight(), fallbackSize.height());
1080}
1081
1083{
1084 if (!info) return;
1085
1086 Q_ASSERT(which == Qt::MinimumSize || which == Qt::MaximumSize);
1087
1088 const QSizeF constraint(which == Qt::MinimumSize
1089 ? QSizeF(info->minimumWidth(), info->minimumHeight())
1090 : QSizeF(info->maximumWidth(), info->maximumHeight()));
1091
1092 if (!info->isExtentExplicitlySet(Qt::Horizontal, which))
1093 combineHints(size->rwidth(), constraint.width());
1094 if (!info->isExtentExplicitlySet(Qt::Vertical, which))
1095 combineHints(size->rheight(), constraint.height());
1096}
1097
1099
1132void QQuickLayout::effectiveSizeHints_helper(QQuickItem *item, QSizeF *cachedSizeHints, QQuickLayoutAttached **attachedInfo, bool useFallbackToWidthOrHeight)
1133{
1134 for (int i = 0; i < Qt::NSizeHints; ++i)
1135 cachedSizeHints[i] = QSizeF();
1137 // First, retrieve the user-specified hints from the attached "Layout." properties
1138 if (info) {
1139 struct Getters {
1140 SizeGetter call[NSizes];
1141 };
1142
1143 static Getters horGetters = {
1145 };
1146
1147 static Getters verGetters = {
1149 };
1150 for (int i = 0; i < NSizes; ++i) {
1151 SizeGetter getter = horGetters.call[i];
1152 Q_ASSERT(getter);
1153
1154 if (info->isExtentExplicitlySet(Qt::Horizontal, (Qt::SizeHint)i))
1155 cachedSizeHints[i].setWidth((info->*getter)());
1156
1157 getter = verGetters.call[i];
1158 Q_ASSERT(getter);
1159 if (info->isExtentExplicitlySet(Qt::Vertical, (Qt::SizeHint)i))
1160 cachedSizeHints[i].setHeight((info->*getter)());
1161 }
1162 }
1163
1164 QSizeF &minS = cachedSizeHints[Qt::MinimumSize];
1165 QSizeF &prefS = cachedSizeHints[Qt::PreferredSize];
1166 QSizeF &maxS = cachedSizeHints[Qt::MaximumSize];
1167 QSizeF &descentS = cachedSizeHints[Qt::MinimumDescent];
1168
1169 // For instance, will normalize the following user-set hints
1170 // from: [10, 5, 60]
1171 // to: [10, 10, 60]
1172 normalizeHints(minS.rwidth(), prefS.rwidth(), maxS.rwidth(), descentS.rwidth());
1173 normalizeHints(minS.rheight(), prefS.rheight(), maxS.rheight(), descentS.rheight());
1174
1175 // All explicit values gathered, now continue to gather the implicit sizes
1176
1177 //--- GATHER MAXIMUM SIZE HINTS ---
1179 combineSize(maxS, QSizeF(std::numeric_limits<qreal>::infinity(), std::numeric_limits<qreal>::infinity()));
1180 // implicit max or min sizes should not limit an explicitly set preferred size
1181 expandSize(maxS, prefS);
1182 expandSize(maxS, minS);
1183
1184 //--- GATHER MINIMUM SIZE HINTS ---
1186 expandSize(minS, QSizeF(0,0));
1187 boundSize(minS, prefS);
1188 boundSize(minS, maxS);
1189
1190 //--- GATHER PREFERRED SIZE HINTS ---
1191 // First, from implicitWidth/Height
1192 qreal &prefWidth = prefS.rwidth();
1193 qreal &prefHeight = prefS.rheight();
1194 if (prefWidth < 0 && item->implicitWidth() > 0)
1195 prefWidth = qCeil(item->implicitWidth());
1196 if (prefHeight < 0 && item->implicitHeight() > 0)
1197 prefHeight = qCeil(item->implicitHeight());
1198
1199 // If that fails, make an ultimate fallback to width/height
1200 if (useFallbackToWidthOrHeight && !prefS.isValid()) {
1201 /* If we want to support using width/height as preferred size hints in
1202 layouts, (which we think most people expect), we only want to use the
1203 initial width.
1204 This is because the width will change due to layout rearrangement,
1205 and the preferred width should return the same value, regardless of
1206 the current width.
1207 We therefore store this initial width in the attached layout object
1208 and reuse it if needed rather than querying the width another time.
1209 That means we need to ensure that an Layout attached object is available
1210 by creating one if necessary.
1211 */
1212 if (!info)
1214
1215 auto updatePreferredSizes = [](qreal &cachedSize, qreal &attachedSize, qreal size) {
1216 if (cachedSize < 0) {
1217 if (attachedSize < 0)
1218 attachedSize = size;
1219
1220 cachedSize = attachedSize;
1221 }
1222 };
1223 updatePreferredSizes(prefWidth, info->m_fallbackWidth, item->width());
1224 updatePreferredSizes(prefHeight, info->m_fallbackHeight, item->height());
1225 }
1226
1227 // Normalize again after the implicit hints have been gathered
1228 expandSize(prefS, minS);
1229 boundSize(prefS, maxS);
1230
1231 //--- GATHER DESCENT
1232 // Minimum descent is only applicable for the effective minimum height,
1233 // so we gather the descent last.
1234 const qreal minimumDescent = minS.height() - item->baselineOffset();
1235 descentS.setHeight(minimumDescent);
1236
1237 if (info) {
1238 QMarginsF margins = info->qMargins();
1239 QSizeF extraMargins(margins.left() + margins.right(), margins.top() + margins.bottom());
1240 minS += extraMargins;
1241 prefS += extraMargins;
1242 maxS += extraMargins;
1243 descentS += extraMargins;
1244 }
1245 if (attachedInfo)
1246 *attachedInfo = info;
1247}
1248
1255{
1256 bool fillExtent([&]{
1257 QLayoutPolicy::Policy policy{QLayoutPolicy::Fixed};
1259 QLayoutPolicy sizePolicy = QQuickItemPrivate::get(item)->sizePolicy();
1260 policy = (orientation == Qt::Horizontal) ? sizePolicy.horizontalPolicy() : sizePolicy.verticalPolicy();
1261 }
1262 return (policy == QLayoutPolicy::Preferred);
1263 }());
1264
1265 bool isSet = false;
1266 if (info) {
1267 if (orientation == Qt::Horizontal) {
1268 isSet = info->isFillWidthSet();
1269 if (isSet) fillExtent = info->fillWidth();
1270 } else {
1271 isSet = info->isFillHeightSet();
1272 if (isSet) fillExtent = info->fillHeight();
1273 }
1274 }
1275 if (!isSet && qobject_cast<QQuickLayout*>(item))
1276 fillExtent = true;
1277
1278 return fillExtent ? QLayoutPolicy::Preferred : QLayoutPolicy::Fixed;
1279}
1280
1282{
1283 QString buf;
1285 qDebug("\n%s", qPrintable(buf));
1286}
1287
1289{
1290 auto formatLine = [&level](const char *fmt) -> QString {
1291 QString ss(level *4, QLatin1Char(' '));
1292 return ss + QLatin1String(fmt) + QLatin1Char('\n');
1293 };
1294
1295 auto f2s = [](qreal f) {
1296 return QString::number(f);
1297 };
1298 auto b2s = [](bool b) {
1299 static const char *strBool[] = {"false", "true"};
1300 return QLatin1String(strBool[int(b)]);
1301 };
1302
1303 buf += formatLine("%1 {").arg(QQmlMetaType::prettyTypeName(this));
1304 ++level;
1305 buf += formatLine("// Effective calculated values:");
1306 buf += formatLine("sizeHintDirty: %2").arg(invalidated());
1308 buf += formatLine("sizeHint.min : [%1, %2]").arg(f2s(min.width()), 5).arg(min.height(), 5);
1310 buf += formatLine("sizeHint.pref: [%1, %2]").arg(pref.width(), 5).arg(pref.height(), 5);
1312 buf += formatLine("sizeHint.max : [%1, %2]").arg(f2s(max.width()), 5).arg(f2s(max.height()), 5);
1313
1314 for (QQuickItem *item : childItems()) {
1315 buf += QLatin1Char('\n');
1316 if (QQuickLayout *childLayout = qobject_cast<QQuickLayout*>(item)) {
1317 childLayout->dumpLayoutTreeRecursive(level, buf);
1318 } else {
1319 buf += formatLine("%1 {").arg(QQmlMetaType::prettyTypeName(item));
1320 ++level;
1321 if (item->implicitWidth() > 0)
1322 buf += formatLine("implicitWidth: %1").arg(f2s(item->implicitWidth()));
1323 if (item->implicitHeight() > 0)
1324 buf += formatLine("implicitHeight: %1").arg(f2s(item->implicitHeight()));
1325 QSizeF min;
1326 QSizeF pref;
1327 QSizeF max;
1329 if (info) {
1330 min = QSizeF(info->minimumWidth(), info->minimumHeight());
1331 pref = QSizeF(info->preferredWidth(), info->preferredHeight());
1332 max = QSizeF(info->maximumWidth(), info->maximumHeight());
1333 if (info->isExtentExplicitlySet(Qt::Horizontal, Qt::MinimumSize))
1334 buf += formatLine("Layout.minimumWidth: %1").arg(f2s(min.width()));
1335 if (info->isExtentExplicitlySet(Qt::Vertical, Qt::MinimumSize))
1336 buf += formatLine("Layout.minimumHeight: %1").arg(f2s(min.height()));
1337 if (pref.width() >= 0)
1338 buf += formatLine("Layout.preferredWidth: %1").arg(f2s(pref.width()));
1339 if (pref.height() >= 0)
1340 buf += formatLine("Layout.preferredHeight: %1").arg(f2s(pref.height()));
1341 if (info->isExtentExplicitlySet(Qt::Horizontal, Qt::MaximumSize))
1342 buf += formatLine("Layout.maximumWidth: %1").arg(f2s(max.width()));
1343 if (info->isExtentExplicitlySet(Qt::Vertical, Qt::MaximumSize))
1344 buf += formatLine("Layout.maximumHeight: %1").arg(f2s(max.height()));
1345
1346 if (info->isFillWidthSet())
1347 buf += formatLine("Layout.fillWidth: %1").arg(b2s(info->fillWidth()));
1348 if (info->isFillHeightSet())
1349 buf += formatLine("Layout.fillHeight: %1").arg(b2s(info->fillHeight()));
1350 }
1351 --level;
1352 buf += formatLine("}");
1353 }
1354 }
1355 --level;
1356 buf += formatLine("}");
1357}
1358
1360
1361#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...
static bool testAttribute(Qt::ApplicationAttribute attribute)
Returns true if attribute attribute is set; otherwise returns false.
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:270
constexpr qreal right() const noexcept
Returns the right margin.
Definition qmargins.h:383
constexpr qreal left() const noexcept
Returns the left margin.
Definition qmargins.h:377
constexpr qreal top() const noexcept
Returns the top margin.
Definition qmargins.h:380
constexpr void setLeft(qreal aleft) noexcept
Sets the left margin to aleft (which must be finite).
Definition qmargins.h:390
constexpr void setRight(qreal aright) noexcept
Sets the right margin to aright (which must be finite).
Definition qmargins.h:396
constexpr void setBottom(qreal abottom) noexcept
Sets the bottom margin to abottom (which must be finite).
Definition qmargins.h:399
constexpr void setTop(qreal atop) noexcept
Sets the top margin to atop (which must be finite).
Definition qmargins.h:393
constexpr qreal bottom() const noexcept
Returns the bottom margin.
Definition qmargins.h:386
\inmodule QtCore
Definition qobject.h:103
QObject * parent() const
Returns a pointer to the parent object.
Definition qobject.h:346
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:2658
static QString prettyTypeName(const QObject *object)
Returns the pretty QML type name (e.g.
Qt::Orientations activeDirections() const
static QQuickItemPrivate * get(QQuickItem *item)
The QQuickItem class provides the most basic of all visual items in \l {Qt Quick}.
Definition qquickitem.h:63
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:114
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:75
QQuickItem * parentItem() const
virtual void itemChange(ItemChange, const ItemChangeData &)
Called when change occurs for this item.
qreal implicitHeight
Definition qquickitem.h:115
qreal height
This property holds the height of this item.
Definition qquickitem.h:76
ItemChange
Used in conjunction with QQuickItem::itemChange() to notify the item about certain types of changes.
Definition qquickitem.h:144
@ ItemChildAddedChange
Definition qquickitem.h:145
@ ItemChildRemovedChange
Definition qquickitem.h:146
void polish()
Schedules a polish event for this item.
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:484
constexpr QSizeF size() const noexcept
Returns the size of the rectangle.
Definition qrect.h:735
\inmodule QtCore
Definition qsize.h:208
constexpr qreal & rwidth() noexcept
Returns a reference to the width.
Definition qsize.h:356
constexpr void setHeight(qreal h) noexcept
Sets the height to the given finite height.
Definition qsize.h:341
constexpr qreal & rheight() noexcept
Returns a reference to the height.
Definition qsize.h:359
constexpr void setWidth(qreal w) noexcept
Sets the width to the given finite width.
Definition qsize.h:338
constexpr qreal width() const noexcept
Returns the width.
Definition qsize.h:332
constexpr qreal height() const noexcept
Returns the height.
Definition qsize.h:335
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
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:8084
Combined button and popup list for selecting options.
@ AlignBaseline
Definition qnamespace.h:156
Orientation
Definition qnamespace.h:98
@ Horizontal
Definition qnamespace.h:99
@ Vertical
Definition qnamespace.h:100
@ AA_QtQuickUseDefaultSizePolicy
Definition qnamespace.h:426
@ 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:164
#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:112
#define SLOT(a)
Definition qobjectdefs.h:52
#define SIGNAL(a)
Definition qobjectdefs.h:53
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:492
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:1531
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define emit
#define Q_UNUSED(x)
double qreal
Definition qtypes.h:187
QVideoFrameFormat::PixelFormat fmt
QVBoxLayout * layout
ba fill(true)
QGraphicsItem * item
QLayoutItem * child
[0]
QSizePolicy policy
QHostInfo info
[0]
\inmodule QtCore \reentrant
Definition qchar.h:18
\inmodule QtQuick
Definition qquickitem.h:159