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
qlayoutitem.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// Qt-Security score:significant reason:default
4
5#include "qlayout.h"
6
7#include "qapplication.h"
9#include "qevent.h"
10#include "qstyle.h"
11#include "qvariant.h"
12#include "qwidget_p.h"
13
15
16inline static QRect fromLayoutItemRect(QWidgetPrivate *priv, const QRect &rect)
17{
18 return rect.adjusted(priv->leftLayoutItemMargin, priv->topLayoutItemMargin,
19 -priv->rightLayoutItemMargin, -priv->bottomLayoutItemMargin);
20}
21
22inline static QSize fromLayoutItemSize(QWidgetPrivate *priv, const QSize &size)
23{
24 return fromLayoutItemRect(priv, QRect(QPoint(0, 0), size)).size();
25}
26
27inline static QRect toLayoutItemRect(QWidgetPrivate *priv, const QRect &rect)
28{
29 return rect.adjusted(-priv->leftLayoutItemMargin, -priv->topLayoutItemMargin,
30 priv->rightLayoutItemMargin, priv->bottomLayoutItemMargin);
31}
32
33inline static QSize toLayoutItemSize(QWidgetPrivate *priv, const QSize &size)
34{
35 return toLayoutItemRect(priv, QRect(QPoint(0, 0), size)).size();
36}
37
38/*!
39 \class QLayoutItem
40 \brief The QLayoutItem class provides an abstract item that a
41 QLayout manipulates.
42
43 \ingroup geomanagement
44 \inmodule QtWidgets
45
46 This is used by custom layouts.
48 Pure virtual functions are provided to return information about
49 the layout, including, sizeHint(), minimumSize(), maximumSize()
50 and expandingDirections().
51
52 The layout's geometry can be set and retrieved with setGeometry()
53 and geometry(), and its alignment with setAlignment() and
54 alignment().
55
56 isEmpty() returns whether the layout item is empty. If the
57 concrete item is a QWidget, it can be retrieved using widget().
58 Similarly for layout() and spacerItem().
59
60 Some layouts have width and height interdependencies. These can
61 be expressed using hasHeightForWidth(), heightForWidth(), and
62 minimumHeightForWidth(). For more explanation see the \e{Qt
63 Quarterly} article
64 \l{http://doc.qt.io/archives/qq/qq04-height-for-width.html}{Trading
65 Height for Width}.
66
67 \sa QLayout
68*/
69
70/*!
71 \class QSpacerItem
72 \ingroup geomanagement
73 \brief The QSpacerItem class provides blank space in a layout.
74
75 \inmodule QtWidgets
76
77 Normally, you don't need to use this class directly. Qt's
78 built-in layout managers provide the following functions for
79 manipulating empty space in layouts:
80
81 \table
82 \header \li Class
83 \li Functions
84 \row \li QHBoxLayout
85 \li \l{QBoxLayout::addSpacing()}{addSpacing()},
86 \l{QBoxLayout::addStretch()}{addStretch()},
87 \l{QBoxLayout::insertSpacing()}{insertSpacing()},
88 \l{QBoxLayout::insertStretch()}{insertStretch()}
89 \row \li QGridLayout
90 \li \l{QGridLayout::setRowMinimumHeight()}{setRowMinimumHeight()},
91 \l{QGridLayout::setRowStretch()}{setRowStretch()},
92 \l{QGridLayout::setColumnMinimumWidth()}{setColumnMinimumWidth()},
93 \l{QGridLayout::setColumnStretch()}{setColumnStretch()}
94 \endtable
95
96 \sa QLayout, QWidgetItem, QLayoutItem::spacerItem()
97*/
98
99/*!
100 \class QWidgetItem
101 \ingroup geomanagement
102 \brief The QWidgetItem class is a layout item that represents a widget.
103
104 \inmodule QtWidgets
105
106 Normally, you don't need to use this class directly. Qt's
107 built-in layout managers provide the following functions for
108 manipulating widgets in layouts:
109
110 \table
111 \header \li Class
112 \li Functions
113 \row \li QBoxLayout
114 \li \l{QBoxLayout::addWidget()}{addWidget()},
115 \l{QBoxLayout::insertWidget()}{insertWidget()},
116 \l{QBoxLayout::setStretchFactor()}{setStretchFactor()}
117 \row \li QGridLayout
118 \li \l{QGridLayout::addWidget()}{addWidget()}
119 \row \li QStackedLayout
120 \li \l{QStackedLayout::addWidget()}{addWidget()},
121 \l{QStackedLayout::insertWidget()}{insertWidget()},
122 \l{QStackedLayout::currentWidget()}{currentWidget()},
123 \l{QStackedLayout::setCurrentWidget()}{setCurrentWidget()},
124 \l{QStackedLayout::widget()}{widget()}
125 \endtable
126
127 \sa QLayout, QSpacerItem, QLayoutItem::widget()
128*/
129
130/*!
131 \fn QLayoutItem::QLayoutItem(Qt::Alignment alignment)
132
133 Constructs a layout item with an \a alignment.
134 Not all subclasses support alignment.
135*/
136
137/*!
138 \fn Qt::Alignment QLayoutItem::alignment() const
139
140 Returns the alignment of this item.
141*/
142
143/*!
144 Sets the alignment of this item to \a alignment.
145
146 \b{Note:} Item alignment is only supported by QLayoutItem subclasses
147 where it would have a visual effect. Except for QSpacerItem, which provides
148 blank space for layouts, all public Qt classes that inherit QLayoutItem
149 support item alignment.
150*/
151void QLayoutItem::setAlignment(Qt::Alignment alignment)
152{
153 align = alignment;
154}
155
156/*!
157 \fn QSize QLayoutItem::maximumSize() const
158
159 Implemented in subclasses to return the maximum size of this item.
160*/
161
162/*!
163 \fn QSize QLayoutItem::minimumSize() const
164
165 Implemented in subclasses to return the minimum size of this item.
166*/
167
168/*!
169 \fn QSize QLayoutItem::sizeHint() const
170
171 Implemented in subclasses to return the preferred size of this item.
172*/
173
174/*!
175 \fn Qt::Orientations QLayoutItem::expandingDirections() const
176
177 Returns whether this layout item can make use of more space than
178 sizeHint(). A value of Qt::Vertical or Qt::Horizontal means that
179 it wants to grow in only one dimension, whereas Qt::Vertical |
180 Qt::Horizontal means that it wants to grow in both dimensions.
181*/
182
183/*!
184 \fn void QLayoutItem::setGeometry(const QRect &r)
185
186 Implemented in subclasses to set this item's geometry to \a r.
187
188 \sa geometry()
189*/
190
191/*!
192 \fn QRect QLayoutItem::geometry() const
193
194 Returns the rectangle covered by this layout item.
195
196 \sa setGeometry()
197*/
198
199/*!
200 \fn virtual bool QLayoutItem::isEmpty() const
201
202 Implemented in subclasses to return whether this item is empty,
203 i.e. whether it contains any widgets.
204*/
205
206/*!
207 \fn QSpacerItem::QSpacerItem(int w, int h, QSizePolicy::Policy hPolicy, QSizePolicy::Policy vPolicy)
208
209 Constructs a spacer item with preferred width \a w, preferred
210 height \a h, horizontal size policy \a hPolicy and vertical size
211 policy \a vPolicy.
212
213 The default values provide a gap that is able to stretch if
214 nothing else wants the space.
215*/
216
217/*!
218 Destructor.
219*/
220QSpacerItem::~QSpacerItem() {}
221
222/*!
223 Changes this spacer item to have preferred width \a w, preferred
224 height \a h, horizontal size policy \a hPolicy and vertical size
225 policy \a vPolicy.
226
227 The default values provide a gap that is able to stretch if
228 nothing else wants the space.
229
230 Note that if changeSize() is called after the spacer item has been added
231 to a layout, it is necessary to invalidate the layout in order for the
232 spacer item's new size to take effect.
233
234 \sa QSpacerItem::invalidate()
235*/
236void QSpacerItem::changeSize(int w, int h, QSizePolicy::Policy hPolicy,
237 QSizePolicy::Policy vPolicy)
238{
239 width = w;
240 height = h;
241 sizeP = QSizePolicy(hPolicy, vPolicy);
242}
243
244/*!
245 \fn QWidgetItem::QWidgetItem(QWidget *widget)
246
247 Creates an item containing the given \a widget.
248*/
249
250/*!
251 Destructor.
252*/
253QWidgetItem::~QWidgetItem() = default;
254
255/*!
256 Destroys the QLayoutItem.
257*/
258QLayoutItem::~QLayoutItem() = default;
259
260/*!
261 Invalidates any cached information in this layout item.
262*/
263void QLayoutItem::invalidate()
264{
265}
266
267/*!
268 If this item is a QLayout, it is returned as a QLayout; otherwise
269 \nullptr is returned. This function provides type-safe casting.
270
271 \sa spacerItem(), widget()
272*/
273QLayout *QLayoutItem::layout()
274{
275 return nullptr;
276}
277
278/*!
279 If this item is a QSpacerItem, it is returned as a QSpacerItem;
280 otherwise \nullptr is returned. This function provides type-safe casting.
281
282 \sa layout(), widget()
283*/
284QSpacerItem *QLayoutItem::spacerItem()
285{
286 return nullptr;
287}
288
289/*!
290 \reimp
291*/
292QLayout * QLayout::layout()
293{
294 return this;
295}
296
297/*!
298 Returns a pointer to this object.
299*/
300QSpacerItem * QSpacerItem::spacerItem()
301{
302 return this;
303}
304
305/*!
306 \fn QSizePolicy QSpacerItem::sizePolicy() const
307 \since 5.5
308
309 Returns the size policy of this item.
310*/
311
312/*!
313 If this item manages a QWidget, returns that widget. Otherwise,
314 \nullptr is returned.
315
316 \note While the functions layout() and spacerItem() perform casts, this
317 function returns another object: QLayout and QSpacerItem inherit QLayoutItem,
318 while QWidget does not.
319
320 \sa layout(), spacerItem()
321*/
322QWidget *QLayoutItem::widget() const
323{
324 return nullptr;
325}
326
327/*!
328 Returns the widget managed by this item.
329*/
330QWidget *QWidgetItem::widget() const
331{
332 return wid;
333}
334
335/*!
336 Returns \c true if this layout's preferred height depends on its
337 width; otherwise returns \c false. The default implementation returns
338 false.
339
340 Reimplement this function in layout managers that support height
341 for width.
342
343 \sa heightForWidth(), QWidget::heightForWidth()
344*/
345bool QLayoutItem::hasHeightForWidth() const
346{
347 return false;
348}
349
350/*!
351 Returns the minimum height this widget needs for the given width,
352 \a w. The default implementation simply returns heightForWidth(\a
353 w).
354*/
355int QLayoutItem::minimumHeightForWidth(int w) const
356{
357 return heightForWidth(w);
358}
359
360
361/*!
362 Returns the preferred height for this layout item, given the
363 width, which is not used in this default implementation.
364
365 The default implementation returns -1, indicating that the
366 preferred height is independent of the width of the item. Using
367 the function hasHeightForWidth() will typically be much faster
368 than calling this function and testing for -1.
369
370 Reimplement this function in layout managers that support height
371 for width. A typical implementation will look like this:
372 \snippet code/src_gui_kernel_qlayoutitem.cpp 0
373
374 Caching is strongly recommended; without it layout will take
375 exponential time.
376
377 \sa hasHeightForWidth()
378*/
379int QLayoutItem::heightForWidth(int /* w */) const
380{
381 return -1;
382}
383
384/*!
385 Returns the control type(s) for the layout item. For a
386 QWidgetItem, the control type comes from the widget's size
387 policy; for a QLayoutItem, the control types is derived from the
388 layout's contents.
389
390 \sa QSizePolicy::controlType()
391*/
392QSizePolicy::ControlTypes QLayoutItem::controlTypes() const
393{
394 return QSizePolicy::DefaultType;
395}
396
397/*!
398 \reimp
399*/
400void QSpacerItem::setGeometry(const QRect &r)
401{
402 rect = r;
403}
404
405/*!
406 \reimp
407*/
408void QWidgetItem::setGeometry(const QRect &rect)
409{
410 if (isEmpty())
411 return;
412
413 QRect r = !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
414 ? fromLayoutItemRect(wid->d_func(), rect)
415 : rect;
416 const QSize widgetRectSurplus = r.size() - rect.size();
417
418 /*
419 For historical reasons, this code is done using widget rect
420 coordinates, not layout item rect coordinates. However,
421 QWidgetItem's sizeHint(), maximumSize(), and heightForWidth()
422 all work in terms of layout item rect coordinates, so we have to
423 add or subtract widgetRectSurplus here and there. The code could
424 be much simpler if we did everything using layout item rect
425 coordinates and did the conversion right before the call to
426 QWidget::setGeometry().
427 */
428
429 QSize s = r.size().boundedTo(maximumSize() + widgetRectSurplus);
430 int x = r.x();
431 int y = r.y();
432 if (align & (Qt::AlignHorizontal_Mask | Qt::AlignVertical_Mask)) {
433 QSize pref(sizeHint());
434 QSizePolicy sp = wid->sizePolicy();
435 if (sp.horizontalPolicy() == QSizePolicy::Ignored)
436 pref.setWidth(wid->sizeHint().expandedTo(wid->minimumSize()).width());
437 if (sp.verticalPolicy() == QSizePolicy::Ignored)
438 pref.setHeight(wid->sizeHint().expandedTo(wid->minimumSize()).height());
439 pref += widgetRectSurplus;
440 if (align & Qt::AlignHorizontal_Mask)
441 s.setWidth(qMin(s.width(), pref.width()));
442 if (align & Qt::AlignVertical_Mask) {
443 if (hasHeightForWidth())
444 s.setHeight(qMin(s.height(),
445 heightForWidth(s.width() - widgetRectSurplus.width())
446 + widgetRectSurplus.height()));
447 else
448 s.setHeight(qMin(s.height(), pref.height()));
449 }
450 }
451 Qt::Alignment alignHoriz = QStyle::visualAlignment(wid->layoutDirection(), align);
452 if (alignHoriz & Qt::AlignRight)
453 x = x + (r.width() - s.width());
454 else if (!(alignHoriz & Qt::AlignLeft))
455 x = x + (r.width() - s.width()) / 2;
456
457 if (align & Qt::AlignBottom)
458 y = y + (r.height() - s.height());
459 else if (!(align & Qt::AlignTop))
460 y = y + (r.height() - s.height()) / 2;
461
462 // Make sure we don't move outside of the parent, e.g when styles demand
463 // surplus space that exceeds the available margins (f.ex macOS with QGroupBox)
464 if (x < 0) {
465 s.rwidth() += x;
466 x = 0;
467 }
468 if (y < 0) {
469 s.rheight() += y;
470 y = 0;
471 }
472
473 wid->setGeometry(x, y, s.width(), s.height());
474}
475
476/*!
477 \reimp
478*/
479QRect QSpacerItem::geometry() const
480{
481 return rect;
482}
483
484/*!
485 \reimp
486*/
487QRect QWidgetItem::geometry() const
488{
489 return !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
490 ? toLayoutItemRect(wid->d_func(), wid->geometry())
491 : wid->geometry();
492}
493
494
495/*!
496 \reimp
497*/
498bool QWidgetItem::hasHeightForWidth() const
499{
500 if (isEmpty())
501 return false;
502 return wid->hasHeightForWidth();
503}
504
505/*!
506 \reimp
507*/
508int QWidgetItem::heightForWidth(int w) const
509{
510 if (isEmpty())
511 return -1;
512
513 w = !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
514 ? fromLayoutItemSize(wid->d_func(), QSize(w, 0)).width()
515 : w;
516
517 int hfw;
518 if (wid->layout())
519 hfw = wid->layout()->totalHeightForWidth(w);
520 else
521 hfw = wid->heightForWidth(w);
522
523 if (hfw > wid->maximumHeight())
524 hfw = wid->maximumHeight();
525 if (hfw < wid->minimumHeight())
526 hfw = wid->minimumHeight();
527
528 hfw = !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
529 ? toLayoutItemSize(wid->d_func(), QSize(0, hfw)).height()
530 : hfw;
531
532 if (hfw < 0)
533 hfw = 0;
534 return hfw;
535}
536
537int QWidgetItem::minimumHeightForWidth(int w) const
538{
539 if (isEmpty())
540 return -1;
541
542 w = !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
543 ? fromLayoutItemSize(wid->d_func(), QSize(w, 0)).width()
544 : w;
545
546 int hfw;
547 if (wid->layout())
548 hfw = wid->layout()->totalMinimumHeightForWidth(w);
549 else
550 hfw = wid->heightForWidth(w); // QWidget doesn't have minimumHeightForWidth()
551
552 if (hfw > wid->maximumHeight())
553 hfw = wid->maximumHeight();
554 if (hfw < wid->minimumHeight())
555 hfw = wid->minimumHeight();
556
557 hfw = !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
558 ? toLayoutItemSize(wid->d_func(), QSize(0, hfw)).height()
559 : hfw;
560
561 if (hfw < 0)
562 hfw = 0;
563 return hfw;
564
565}
566
567/*!
568 \reimp
569*/
570Qt::Orientations QSpacerItem::expandingDirections() const
571{
572 return sizeP.expandingDirections();
573}
574
575/*!
576 \reimp
577*/
578Qt::Orientations QWidgetItem::expandingDirections() const
579{
580 if (isEmpty())
581 return {};
582
583 Qt::Orientations e = wid->sizePolicy().expandingDirections();
584 /*
585 If the layout is expanding, we make the widget expanding, even if
586 its own size policy isn't expanding.
587 */
588 if (wid->layout()) {
589 if (wid->sizePolicy().horizontalPolicy() & QSizePolicy::GrowFlag
590 && (wid->layout()->expandingDirections() & Qt::Horizontal))
591 e |= Qt::Horizontal;
592 if (wid->sizePolicy().verticalPolicy() & QSizePolicy::GrowFlag
593 && (wid->layout()->expandingDirections() & Qt::Vertical))
594 e |= Qt::Vertical;
595 }
596
597 if (align & Qt::AlignHorizontal_Mask)
598 e &= ~Qt::Horizontal;
599 if (align & Qt::AlignVertical_Mask)
600 e &= ~Qt::Vertical;
601 return e;
602}
603
604/*!
605 \reimp
606*/
607QSize QSpacerItem::minimumSize() const
608{
609 return QSize(sizeP.horizontalPolicy() & QSizePolicy::ShrinkFlag ? 0 : width,
610 sizeP.verticalPolicy() & QSizePolicy::ShrinkFlag ? 0 : height);
611}
612
613/*!
614 \reimp
615*/
616QSize QWidgetItem::minimumSize() const
617{
618 if (isEmpty())
619 return QSize(0, 0);
620 return !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
621 ? toLayoutItemSize(wid->d_func(), qSmartMinSize(this))
622 : qSmartMinSize(this);
623}
624
625/*!
626 \reimp
627*/
628QSize QSpacerItem::maximumSize() const
629{
630 return QSize(sizeP.horizontalPolicy() & QSizePolicy::GrowFlag ? QLAYOUTSIZE_MAX : width,
631 sizeP.verticalPolicy() & QSizePolicy::GrowFlag ? QLAYOUTSIZE_MAX : height);
632}
633
634/*!
635 \reimp
636*/
637QSize QWidgetItem::maximumSize() const
638{
639 if (isEmpty()) {
640 return QSize(0, 0);
641 } else {
642 return !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
643 ? toLayoutItemSize(wid->d_func(), qSmartMaxSize(this, align))
644 : qSmartMaxSize(this, align);
645 }
646}
647
648/*!
649 \reimp
650*/
651QSize QSpacerItem::sizeHint() const
652{
653 return QSize(width, height);
654}
655
656/*!
657 \reimp
658*/
659QSize QWidgetItem::sizeHint() const
660{
661 QSize s(0, 0);
662 if (!isEmpty()) {
663 s = wid->sizeHint().expandedTo(wid->minimumSizeHint());
664 s = s.boundedTo(wid->maximumSize())
665 .expandedTo(wid->minimumSize());
666 s = !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
667 ? toLayoutItemSize(wid->d_func(), s)
668 : s;
669
670 if (wid->sizePolicy().horizontalPolicy() == QSizePolicy::Ignored)
671 s.setWidth(0);
672 if (wid->sizePolicy().verticalPolicy() == QSizePolicy::Ignored)
673 s.setHeight(0);
674 }
675 return s;
676}
677
678/*!
679 Returns \c true.
680*/
681bool QSpacerItem::isEmpty() const
682{
683 return true;
684}
685
686/*!
687 Returns \c true if the widget is hidden; otherwise returns \c false.
688
689 \sa QWidget::isHidden()
690*/
691bool QWidgetItem::isEmpty() const
692{
693 return (wid->isHidden() && !wid->sizePolicy().retainSizeWhenHidden()) || wid->isWindow();
694}
695
696/*!
697 Returns the control type associated with the widget for which
698 this size policy applies.
699
700 \sa QSizePolicy::controlType()
701 */
702QSizePolicy::ControlTypes QWidgetItem::controlTypes() const
703{
704 return wid->sizePolicy().controlType();
705}
706
707/*!
708 \class QWidgetItemV2
709 \internal
710*/
711
712inline bool QWidgetItemV2::useSizeCache() const
713{
714 return wid->d_func()->widgetItem == this;
715}
716
717void QWidgetItemV2::updateCacheIfNecessary() const
718{
719 if (q_cachedMinimumSize.width() != Dirty)
720 return;
721
722 const QSize sizeHint(wid->sizeHint());
723 const QSize minimumSizeHint(wid->minimumSizeHint());
724 const QSize minimumSize(wid->minimumSize());
725 const QSize maximumSize(wid->maximumSize());
726 const QSizePolicy sizePolicy(wid->sizePolicy());
727 const QSize expandedSizeHint(sizeHint.expandedTo(minimumSizeHint));
728
729 const QSize smartMinSize(qSmartMinSize(sizeHint, minimumSizeHint, minimumSize, maximumSize, sizePolicy));
730 const QSize smartMaxSize(qSmartMaxSize(expandedSizeHint, minimumSize, maximumSize, sizePolicy, align));
731
732 const bool useLayoutItemRect = !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect);
733
734 q_cachedMinimumSize = useLayoutItemRect
735 ? toLayoutItemSize(wid->d_func(), smartMinSize)
736 : smartMinSize;
737
738 q_cachedSizeHint = expandedSizeHint;
739 q_cachedSizeHint = q_cachedSizeHint.boundedTo(maximumSize)
740 .expandedTo(minimumSize);
741 q_cachedSizeHint = useLayoutItemRect
742 ? toLayoutItemSize(wid->d_func(), q_cachedSizeHint)
743 : q_cachedSizeHint;
744
745 if (wid->sizePolicy().horizontalPolicy() == QSizePolicy::Ignored)
746 q_cachedSizeHint.setWidth(0);
747 if (wid->sizePolicy().verticalPolicy() == QSizePolicy::Ignored)
748 q_cachedSizeHint.setHeight(0);
749
750 q_cachedMaximumSize = useLayoutItemRect
751 ? toLayoutItemSize(wid->d_func(), smartMaxSize)
752 : smartMaxSize;
753}
754
755QWidgetItemV2::QWidgetItemV2(QWidget *widget)
756 : QWidgetItem(widget),
757 q_cachedMinimumSize(Dirty, Dirty),
758 q_cachedSizeHint(Dirty, Dirty),
759 q_cachedMaximumSize(Dirty, Dirty),
760 q_firstCachedHfw(0),
761 q_hfwCacheSize(0),
762 d(nullptr)
763{
764 QWidgetPrivate *wd = wid->d_func();
765 if (!wd->widgetItem)
766 wd->widgetItem = this;
767}
768
769QWidgetItemV2::~QWidgetItemV2()
770{
771 if (wid) {
772 auto *wd = static_cast<QWidgetPrivate *>(QObjectPrivate::get(wid));
773 if (wd->widgetItem == this)
774 wd->widgetItem = nullptr;
775 }
776}
777
778QSize QWidgetItemV2::sizeHint() const
779{
780 if (isEmpty())
781 return QSize(0, 0);
782
783 if (useSizeCache()) {
784 updateCacheIfNecessary();
785 return q_cachedSizeHint;
786 } else {
787 return QWidgetItem::sizeHint();
788 }
789}
790
791QSize QWidgetItemV2::minimumSize() const
792{
793 if (isEmpty())
794 return QSize(0, 0);
795
796 if (useSizeCache()) {
797 updateCacheIfNecessary();
798 return q_cachedMinimumSize;
799 } else {
800 return QWidgetItem::minimumSize();
801 }
802}
803
804QSize QWidgetItemV2::maximumSize() const
805{
806 if (isEmpty())
807 return QSize(0, 0);
808
809 if (useSizeCache()) {
810 updateCacheIfNecessary();
811 return q_cachedMaximumSize;
812 } else {
813 return QWidgetItem::maximumSize();
814 }
815}
816
817/*
818 The height-for-width cache is organized as a circular buffer. The entries
819
820 q_hfwCachedHfws[q_firstCachedHfw],
821 ...,
822 q_hfwCachedHfws[(q_firstCachedHfw + q_hfwCacheSize - 1) % HfwCacheMaxSize]
823
824 contain the last cached values. When the cache is full, the first entry to
825 be erased is the entry before q_hfwCachedHfws[q_firstCachedHfw]. When
826 values are looked up, we try to move q_firstCachedHfw to point to that new
827 entry (unless the cache is not full, in which case it would leave the cache
828 in a broken state), so that the most recently used entry is also the last
829 to be erased.
830*/
831
832int QWidgetItemV2::heightForWidth(int width) const
833{
834 if (isEmpty())
835 return -1;
836
837 for (int i = 0; i < q_hfwCacheSize; ++i) {
838 int offset = q_firstCachedHfw + i;
839 const QSize &size = q_cachedHfws[offset % HfwCacheMaxSize];
840 if (size.width() == width) {
841 if (q_hfwCacheSize == HfwCacheMaxSize)
842 q_firstCachedHfw = offset % HfwCacheMaxSize;
843 return size.height();
844 }
845 }
846
847 if (q_hfwCacheSize < HfwCacheMaxSize)
848 ++q_hfwCacheSize;
849 q_firstCachedHfw = (q_firstCachedHfw + HfwCacheMaxSize - 1) % HfwCacheMaxSize;
850
851 int height = QWidgetItem::heightForWidth(width);
852 q_cachedHfws[q_firstCachedHfw] = QSize(width, height);
853 return height;
854}
855
856QT_END_NAMESPACE
static QSize toLayoutItemSize(QWidgetPrivate *priv, const QSize &size)
static QT_BEGIN_NAMESPACE QRect fromLayoutItemRect(QWidgetPrivate *priv, const QRect &rect)
static QRect toLayoutItemRect(QWidgetPrivate *priv, const QRect &rect)
static QSize fromLayoutItemSize(QWidgetPrivate *priv, const QSize &size)