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
qlayout.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
9#include "qevent.h"
10#include "qstyle.h"
11#include "qwidget_p.h"
12#include "qlayout_p.h"
13
15
16static int menuBarHeightForWidth(QWidget *menubar, int w)
17{
18 if (menubar && !menubar->isHidden() && !menubar->isWindow()) {
19 int result = menubar->heightForWidth(qMax(w, menubar->minimumWidth()));
20 if (result == -1)
21 result = menubar->sizeHint().height();
22 const int min = qSmartMinSize(menubar).height();
23 result = qBound(min, result, menubar->maximumSize().height());
24 if (result != -1)
25 return result;
26 }
27 return 0;
28}
29
30/*!
31 \class QLayout
32 \brief The QLayout class is the base class of geometry managers.
33
34 \ingroup geomanagement
35 \inmodule QtWidgets
36
37 This is an abstract base class inherited by the concrete classes
38 QBoxLayout, QGridLayout, QFormLayout, and QStackedLayout.
39
40 For users of QLayout subclasses or of QMainWindow there is seldom
41 any need to use the basic functions provided by QLayout, such as
42 setSizeConstraint() or setMenuBar(). See \l{Layout Management}
43 for more information.
44
45 To make your own layout manager, implement the functions
46 addItem(), sizeHint(), setGeometry(), itemAt() and takeAt(). You
47 should also implement minimumSize() to ensure your layout isn't
48 resized to zero size if there is too little space. To support
49 children whose heights depend on their widths, implement
50 hasHeightForWidth() and heightForWidth(). See the
51 \l{layouts/flowlayout}{Flow Layout} example for
52 more information about implementing custom layout managers.
53
54 Geometry management stops when the layout manager is deleted.
55
56 \sa QLayoutItem, {Layout Management}, {Basic Layouts Example},
57 {Flow Layout Example}
58*/
59
60
61/*!
62 Constructs a new top-level QLayout, with parent \a parent.
63
64 The layout is set directly as the top-level layout for
65 \a parent. There can be only one top-level layout for a
66 widget. It is returned by QWidget::layout().
67
68 If \a parent is \nullptr, then you must insert this layout
69 into another layout, or set it as a widget's layout using
70 QWidget::setLayout().
71
72 \sa QWidget::setLayout()
73*/
74QLayout::QLayout(QWidget *parent)
75 : QObject(*new QLayoutPrivate, parent)
76{
77 if (!parent)
78 return;
79 parent->setLayout(this);
80}
81
82/*! \internal
83 */
84QLayout::QLayout(QLayoutPrivate &dd, QLayout *lay, QWidget *w)
85 : QObject(dd, lay ? static_cast<QObject*>(lay) : static_cast<QObject*>(w))
86{
87 Q_D(QLayout);
88 if (lay) {
89 lay->addItem(this);
90 } else if (w) {
91 if (Q_UNLIKELY(w->layout())) {
92 qWarning("QLayout: Attempting to add QLayout \"%ls\" to %s \"%ls\", which"
93 " already has a layout",
94 qUtf16Printable(QObject::objectName()), w->metaObject()->className(),
95 qUtf16Printable(w->objectName()));
96 setParent(nullptr);
97 } else {
98 d->topLevel = true;
99 w->d_func()->layout = this;
100 QT_TRY {
101 invalidate();
102 } QT_CATCH(...) {
103 w->d_func()->layout = nullptr;
104 QT_RETHROW;
105 }
106 }
107 }
108}
109
110QLayoutPrivate::QLayoutPrivate()
111 : QObjectPrivate(), insideSpacing(-1), userLeftMargin(-1), userTopMargin(-1), userRightMargin(-1),
112 userBottomMargin(-1), topLevel(false), enabled(true), activated(true), autoNewChild(false),
113 horizontalConstraint(QLayout::SetDefaultConstraint), verticalConstraint(QLayout::SetDefaultConstraint), menubar(nullptr)
114{
115}
116
117void QLayoutPrivate::getMargin(int *result, int userMargin, QStyle::PixelMetric pm) const
118{
119 if (!result)
120 return;
121
122 Q_Q(const QLayout);
123 if (userMargin >= 0) {
124 *result = userMargin;
125 } else if (!topLevel) {
126 *result = 0;
127 } else if (QWidget *pw = q->parentWidget()) {
128 *result = pw->style()->pixelMetric(pm, nullptr, pw);
129 } else {
130 *result = 0;
131 }
132}
133
134// Static item factory functions that allow for hooking things in Designer
135
136QLayoutPrivate::QWidgetItemFactoryMethod QLayoutPrivate::widgetItemFactoryMethod = nullptr;
137QLayoutPrivate::QSpacerItemFactoryMethod QLayoutPrivate::spacerItemFactoryMethod = nullptr;
138
139QWidgetItem *QLayoutPrivate::createWidgetItem(const QLayout *layout, QWidget *widget)
140{
141 if (widgetItemFactoryMethod)
142 if (QWidgetItem *wi = (*widgetItemFactoryMethod)(layout, widget))
143 return wi;
144 return new QWidgetItemV2(widget);
145}
146
147QSpacerItem *QLayoutPrivate::createSpacerItem(const QLayout *layout, int w, int h, QSizePolicy::Policy hPolicy, QSizePolicy::Policy vPolicy)
148{
149 if (spacerItemFactoryMethod)
150 if (QSpacerItem *si = (*spacerItemFactoryMethod)(layout, w, h, hPolicy, vPolicy))
151 return si;
152 return new QSpacerItem(w, h, hPolicy, vPolicy);
153}
154
155
156
157/*!
158 \fn void QLayout::addItem(QLayoutItem *item)
159
160 Implemented in subclasses to add an \a item. How it is added is
161 specific to each subclass.
162
163 This function is not usually called in application code. To add a widget
164 to a layout, use the addWidget() function; to add a child layout, use the
165 addLayout() function provided by the relevant QLayout subclass.
166
167 \b{Note:} The ownership of \a item is transferred to the layout, and it's
168 the layout's responsibility to delete it.
169
170 \sa addWidget(), QBoxLayout::addLayout(), QGridLayout::addLayout()
171*/
172
173/*!
174 Adds widget \a w to this layout in a manner specific to the
175 layout. This function uses addItem().
176*/
177void QLayout::addWidget(QWidget *w)
178{
179 addChildWidget(w);
180 addItem(QLayoutPrivate::createWidgetItem(this, w));
181}
182
183
184
185/*!
186 Sets the alignment for widget \a w to \a alignment and returns
187 true if \a w is found in this layout (not including child
188 layouts); otherwise returns \c false.
189*/
190bool QLayout::setAlignment(QWidget *w, Qt::Alignment alignment)
191{
192 int i = 0;
193 QLayoutItem *item = itemAt(i);
194 while (item) {
195 if (item->widget() == w) {
196 item->setAlignment(alignment);
197 invalidate();
198 return true;
199 }
200 ++i;
201 item = itemAt(i);
202 }
203 return false;
204}
205
206/*!
207 \overload
208
209 Sets the alignment for the layout \a l to \a alignment and
210 returns \c true if \a l is found in this layout (not including child
211 layouts); otherwise returns \c false.
212*/
213bool QLayout::setAlignment(QLayout *l, Qt::Alignment alignment)
214{
215 int i = 0;
216 QLayoutItem *item = itemAt(i);
217 while (item) {
218 if (item->layout() == l) {
219 item->setAlignment(alignment);
220 invalidate();
221 return true;
222 }
223 ++i;
224 item = itemAt(i);
225 }
226 return false;
227}
228
229/*!
230 \property QLayout::spacing
231 \brief the spacing between widgets inside the layout
232
233 If no value is explicitly set, the layout's spacing is inherited
234 from the parent layout, or from the style settings for the parent
235 widget.
236
237 For QGridLayout and QFormLayout, it is possible to set different horizontal and
238 vertical spacings using \l{QGridLayout::}{setHorizontalSpacing()}
239 and \l{QGridLayout::}{setVerticalSpacing()}. In that case,
240 spacing() returns -1.
241
242 \sa contentsRect(), getContentsMargins(), QStyle::layoutSpacing(),
243 QStyle::pixelMetric()
244*/
245
246int QLayout::spacing() const
247{
248 Q_D(const QLayout);
249 if (d->insideSpacing >=0) {
250 return d->insideSpacing;
251 } else {
252 // arbitrarily prefer horizontal spacing to vertical spacing
253 return qSmartSpacing(this, QStyle::PM_LayoutHorizontalSpacing);
254 }
255}
256
257void QLayout::setSpacing(int spacing)
258{
259 Q_D(QLayout);
260 d->insideSpacing = spacing;
261 invalidate();
262}
263
264/*!
265 \since 4.3
266
267 Sets the \a left, \a top, \a right, and \a bottom margins to use
268 around the layout.
269
270 By default, QLayout uses the values provided by the style. On
271 most platforms, the margin is 11 pixels in all directions.
272
273 \sa getContentsMargins(), QStyle::pixelMetric(),
274 {QStyle::}{PM_LayoutLeftMargin},
275 {QStyle::}{PM_LayoutTopMargin},
276 {QStyle::}{PM_LayoutRightMargin},
277 {QStyle::}{PM_LayoutBottomMargin}
278*/
279void QLayout::setContentsMargins(int left, int top, int right, int bottom)
280{
281 Q_D(QLayout);
282
283 if (d->userLeftMargin == left && d->userTopMargin == top &&
284 d->userRightMargin == right && d->userBottomMargin == bottom)
285 return;
286
287 d->userLeftMargin = left;
288 d->userTopMargin = top;
289 d->userRightMargin = right;
290 d->userBottomMargin = bottom;
291 invalidate();
292}
293
294/*!
295 \since 4.6
296
297 Sets the \a margins to use around the layout.
298
299 By default, QLayout uses the values provided by the style. On
300 most platforms, the margin is 11 pixels in all directions.
301
302 \sa contentsMargins()
303*/
304void QLayout::setContentsMargins(const QMargins &margins)
305{
306 setContentsMargins(margins.left(), margins.top(), margins.right(), margins.bottom());
307}
308
309/*!
310 \since 6.1
311
312 Unsets any user-defined margins around the layout. The layout will
313 use the default values provided by the style.
314
315 \sa setContentsMargins()
316*/
317void QLayout::unsetContentsMargins()
318{
319 setContentsMargins(-1, -1, -1, -1);
320}
321
322/*!
323 \since 4.3
324
325 For each of \a left, \a top, \a right and \a bottom that is not
326 \nullptr, stores the size of the margin named in the location the
327 pointer refers to.
328
329 By default, QLayout uses the values provided by the style. On
330 most platforms, the margin is 11 pixels in all directions.
331
332 \sa setContentsMargins(), QStyle::pixelMetric(),
333 {QStyle::}{PM_LayoutLeftMargin},
334 {QStyle::}{PM_LayoutTopMargin},
335 {QStyle::}{PM_LayoutRightMargin},
336 {QStyle::}{PM_LayoutBottomMargin}
337*/
338void QLayout::getContentsMargins(int *left, int *top, int *right, int *bottom) const
339{
340 Q_D(const QLayout);
341 d->getMargin(left, d->userLeftMargin, QStyle::PM_LayoutLeftMargin);
342 d->getMargin(top, d->userTopMargin, QStyle::PM_LayoutTopMargin);
343 d->getMargin(right, d->userRightMargin, QStyle::PM_LayoutRightMargin);
344 d->getMargin(bottom, d->userBottomMargin, QStyle::PM_LayoutBottomMargin);
345}
346
347/*!
348 \property QLayout::contentsMargins
349 \since 4.6
350 \brief the margins used around the layout
351
352 By default, QLayout uses the values provided by the style. On
353 most platforms, the margin is 11 pixels in all directions.
354
355 \sa setContentsMargins(), getContentsMargins()
356*/
357
358/*!
359 \since 4.6
360
361 Returns the margins used around the layout.
362
363 By default, QLayout uses the values provided by the style. On
364 most platforms, the margin is 11 pixels in all directions.
365
366 \sa setContentsMargins()
367*/
368QMargins QLayout::contentsMargins() const
369{
370 int left, top, right, bottom;
371 getContentsMargins(&left, &top, &right, &bottom);
372 return QMargins(left, top, right, bottom);
373}
374
375/*!
376 \since 4.3
377
378 Returns the layout's geometry() rectangle, but taking into account the
379 contents margins.
380
381 \sa setContentsMargins(), getContentsMargins()
382*/
383QRect QLayout::contentsRect() const
384{
385 Q_D(const QLayout);
386 int left, top, right, bottom;
387 getContentsMargins(&left, &top, &right, &bottom);
388 return d->rect.adjusted(+left, +top, -right, -bottom);
389}
390
391
392/*!
393 Returns the parent widget of this layout, or \nullptr if this
394 layout is not installed on any widget.
395
396 If the layout is a sub-layout, this function returns the parent
397 widget of the parent layout.
398
399 \sa parent()
400*/
401QWidget *QLayout::parentWidget() const
402{
403 Q_D(const QLayout);
404 if (!d->topLevel) {
405 if (parent()) {
406 QLayout *parentLayout = qobject_cast<QLayout*>(parent());
407 if (Q_UNLIKELY(!parentLayout)) {
408 qWarning("QLayout::parentWidget: A layout can only have another layout as a parent.");
409 return nullptr;
410 }
411 return parentLayout->parentWidget();
412 } else {
413 return nullptr;
414 }
415 } else {
416 Q_ASSERT(parent() && parent()->isWidgetType());
417 return static_cast<QWidget *>(parent());
418 }
419}
420
421/*!
422 \reimp
423*/
424bool QLayout::isEmpty() const
425{
426 int i = 0;
427 QLayoutItem *item = itemAt(i);
428 while (item) {
429 if (!item->isEmpty())
430 return false;
431 ++i;
432 item = itemAt(i);
433 }
434 return true;
435}
436
437/*!
438 \reimp
439*/
440QSizePolicy::ControlTypes QLayout::controlTypes() const
441{
442 if (count() == 0)
443 return QSizePolicy::DefaultType;
444 QSizePolicy::ControlTypes types;
445 for (int i = count() - 1; i >= 0; --i)
446 types |= itemAt(i)->controlTypes();
447 return types;
448}
449
450/*!
451 \reimp
452*/
453void QLayout::setGeometry(const QRect &r)
454{
455 Q_D(QLayout);
456 d->rect = r;
457}
458
459/*!
460 \reimp
461*/
462QRect QLayout::geometry() const
463{
464 Q_D(const QLayout);
465 return d->rect;
466}
467
468/*!
469 \reimp
470*/
471void QLayout::invalidate()
472{
473 Q_D(QLayout);
474 d->rect = QRect();
475 update();
476}
477
478static bool removeWidgetRecursively(QLayoutItem *li, QObject *w)
479{
480 QLayout *lay = li->layout();
481 if (!lay)
482 return false;
483 int i = 0;
484 QLayoutItem *child;
485 while ((child = lay->itemAt(i))) {
486 if (child->widget() == w) {
487 delete lay->takeAt(i);
488 lay->invalidate();
489 return true;
490 } else if (removeWidgetRecursively(child, w)) {
491 return true;
492 } else {
493 ++i;
494 }
495 }
496 return false;
497}
498
499
500void QLayoutPrivate::doResize()
501{
502 Q_Q(QLayout);
503 QWidget *mw = q->parentWidget();
504 QRect rect = mw->testAttribute(Qt::WA_LayoutOnEntireRect) ? mw->rect() : mw->contentsRect();
505 const int mbh = menuBarHeightForWidth(menubar, rect.width());
506 const int mbTop = rect.top();
507 rect.setTop(mbTop + mbh);
508 q->setGeometry(rect);
509 if (menubar)
510 menubar->setGeometry(rect.left(), mbTop, rect.width(), mbh);
511}
512
513
514/*!
515 \internal
516 Performs child widget layout when the parent widget is
517 resized. Also handles removal of widgets. \a e is the
518 event
519*/
520void QLayout::widgetEvent(QEvent *e)
521{
522 Q_D(QLayout);
523 const QEvent::Type type = e->type();
524 if (!d->enabled && type != QEvent::ChildRemoved)
525 return;
526
527 switch (type) {
528 case QEvent::Resize:
529 if (d->activated)
530 d->doResize();
531 else
532 activate();
533 break;
534 case QEvent::ChildRemoved:
535 {
536 QChildEvent *c = (QChildEvent *)e;
537 QObject *child = c->child();
538 QObjectPrivate *op = QObjectPrivate::get(child);
539 if (op->wasWidget) {
540 if (child == d->menubar)
541 d->menubar = nullptr;
542 removeWidgetRecursively(this, child);
543 }
544 }
545 break;
546 case QEvent::LayoutRequest:
547 if (static_cast<QWidget *>(parent())->isVisible())
548 activate();
549 break;
550 default:
551 break;
552 }
553}
554
555/*!
556 \reimp
557*/
558void QLayout::childEvent(QChildEvent *e)
559{
560 Q_D(QLayout);
561 if (!d->enabled)
562 return;
563
564 if (e->type() != QEvent::ChildRemoved)
565 return;
566
567 if (QLayout *childLayout = qobject_cast<QLayout *>(e->child()))
568 removeItem(childLayout);
569}
570
571/*!
572 \internal
573 Also takes contentsMargins and menu bar into account.
574*/
575int QLayout::totalMinimumHeightForWidth(int w) const
576{
577 Q_D(const QLayout);
578 int side=0, top=0;
579 if (d->topLevel) {
580 QWidget *parent = parentWidget();
581 parent->ensurePolished();
582 QWidgetPrivate *wd = parent->d_func();
583 side += wd->leftmargin + wd->rightmargin;
584 top += wd->topmargin + wd->bottommargin;
585 }
586 int h = minimumHeightForWidth(w - side) + top +
587 menuBarHeightForWidth(d->menubar, w);
588 return h;
589}
590
591/*!
592 \internal
593 Also takes contentsMargins and menu bar into account.
594*/
595int QLayout::totalHeightForWidth(int w) const
596{
597 Q_D(const QLayout);
598 int side=0, top=0;
599 if (d->topLevel) {
600 QWidget *parent = parentWidget();
601 parent->ensurePolished();
602 QWidgetPrivate *wd = parent->d_func();
603 side += wd->leftmargin + wd->rightmargin;
604 top += wd->topmargin + wd->bottommargin;
605 }
606 int h = heightForWidth(w - side) + top +
607 menuBarHeightForWidth(d->menubar, w);
608 return h;
609}
610
611/*!
612 \internal
613 Also takes contentsMargins and menu bar into account.
614*/
615QSize QLayout::totalMinimumSize() const
616{
617 Q_D(const QLayout);
618 int side=0, top=0;
619 if (d->topLevel) {
620 QWidget *pw = parentWidget();
621 pw->ensurePolished();
622 QWidgetPrivate *wd = pw->d_func();
623 side += wd->leftmargin + wd->rightmargin;
624 top += wd->topmargin + wd->bottommargin;
625 }
626
627 QSize s = minimumSize();
628 top += menuBarHeightForWidth(d->menubar, s.width() + side);
629 return s + QSize(side, top);
630}
631
632/*!
633 \internal
634 Also takes contentsMargins and menu bar into account.
635*/
636QSize QLayout::totalSizeHint() const
637{
638 Q_D(const QLayout);
639 int side=0, top=0;
640 if (d->topLevel) {
641 QWidget *pw = parentWidget();
642 pw->ensurePolished();
643 QWidgetPrivate *wd = pw->d_func();
644 side += wd->leftmargin + wd->rightmargin;
645 top += wd->topmargin + wd->bottommargin;
646 }
647
648 QSize s = sizeHint();
649 if (hasHeightForWidth())
650 s.setHeight(heightForWidth(s.width() + side));
651 top += menuBarHeightForWidth(d->menubar, s.width());
652 return s + QSize(side, top);
653}
654
655/*!
656 \internal
657 Also takes contentsMargins and menu bar into account.
658*/
659QSize QLayout::totalMaximumSize() const
660{
661 Q_D(const QLayout);
662 int side=0, top=0;
663 if (d->topLevel) {
664 QWidget *pw = parentWidget();
665 pw->ensurePolished();
666 QWidgetPrivate *wd = pw->d_func();
667 side += wd->leftmargin + wd->rightmargin;
668 top += wd->topmargin + wd->bottommargin;
669 }
670
671 QSize s = maximumSize();
672 top += menuBarHeightForWidth(d->menubar, s.width());
673
674 if (d->topLevel)
675 s = QSize(qMin(s.width() + side, QLAYOUTSIZE_MAX),
676 qMin(s.height() + top, QLAYOUTSIZE_MAX));
677 return s;
678}
679
680/*!
681 \internal
682 Destroys the layout, deleting all child layouts.
683 Geometry management stops when a top-level layout is deleted.
684
685 The layout classes will probably be fatally confused if you delete
686 a sublayout.
687*/
688QLayout::~QLayout()
689{
690 Q_D(QLayout);
691 if (d->topLevel && parent() && parent()->isWidgetType() && parentWidget()->layout() == this)
692 parentWidget()->d_func()->layout = nullptr;
693 else if (QLayout *parentLayout = qobject_cast<QLayout *>(parent()))
694 parentLayout->removeItem(this);
695}
696
697
698/*!
699 This function is called from \c addLayout() or \c insertLayout() functions in
700 subclasses to add layout \a childLayout as a sub-layout.
701
702 The only scenario in which you need to call it directly is if you
703 implement a custom layout that supports nested layouts.
704
705 \sa QBoxLayout::addLayout(), QBoxLayout::insertLayout(), QGridLayout::addLayout()
706*/
707void QLayout::addChildLayout(QLayout *childLayout)
708{
709 if (Q_UNLIKELY(childLayout->parent())) {
710 qWarning("QLayout::addChildLayout: layout %s \"%ls\" already has a parent",
711 childLayout->metaObject()->className(), qUtf16Printable(childLayout->objectName()));
712 return;
713 }
714 childLayout->setParent(this);
715
716 if (QWidget *mw = parentWidget()) {
717 childLayout->d_func()->reparentChildWidgets(mw);
718 }
719
720}
721
722/*!
723 \internal
724 */
725bool QLayout::adoptLayout(QLayout *layout)
726{
727 const bool ok = !layout->parent();
728 addChildLayout(layout);
729 return ok;
730}
731
732#ifdef QT_DEBUG
733static bool layoutDebug()
734{
735 static int checked_env = -1;
736 if (checked_env == -1)
737 checked_env = !!qEnvironmentVariableIntValue("QT_LAYOUT_DEBUG");
738
739 return checked_env;
740}
741#endif
742
743void QLayoutPrivate::reparentChildWidgets(QWidget *mw)
744{
745 Q_Q(QLayout);
746 int n = q->count();
747
748 if (menubar && menubar->parentWidget() != mw)
749 menubar->setParent(mw);
750
751 bool mwVisible = mw && mw->isVisible();
752 for (int i = 0; i < n; ++i) {
753 QLayoutItem *item = q->itemAt(i);
754 if (QWidget *w = item->widget()) {
755 QWidget *pw = w->parentWidget();
756#ifdef QT_DEBUG
757 if (Q_UNLIKELY(pw && pw != mw && layoutDebug())) {
758 qWarning("QLayout::addChildLayout: widget %s \"%ls\" in wrong parent; moved to correct parent",
759 w->metaObject()->className(), qUtf16Printable(w->objectName()));
760 }
761#endif
762 bool needShow = mwVisible && !QWidgetPrivate::get(w)->isExplicitlyHidden();
763 if (pw != mw)
764 w->setParent(mw);
765 if (needShow)
766 QMetaObject::invokeMethod(w, "_q_showIfNotHidden", Qt::QueuedConnection); //show later
767 } else if (QLayout *l = item->layout()) {
768 l->d_func()->reparentChildWidgets(mw);
769 }
770 }
771}
772
773/*!
774 \class QLayoutPrivate
775 \inmodule QtWidgets
776 \internal
777*/
778
779/*!
780 Returns \c true if the \a widget can be added to the \a layout;
781 otherwise returns \c false.
782*/
783bool QLayoutPrivate::checkWidget(QWidget *widget) const
784{
785 Q_Q(const QLayout);
786 if (Q_UNLIKELY(!widget)) {
787 qWarning("QLayout: Cannot add a null widget to %s/%ls", q->metaObject()->className(),
788 qUtf16Printable(q->objectName()));
789 return false;
790 }
791 if (Q_UNLIKELY(widget == q->parentWidget())) {
792 qWarning("QLayout: Cannot add parent widget %s/%ls to its child layout %s/%ls",
793 widget->metaObject()->className(), qUtf16Printable(widget->objectName()),
794 q->metaObject()->className(), qUtf16Printable(q->objectName()));
795 return false;
796 }
797 return true;
798}
799
800/*!
801 Returns \c true if the \a otherLayout can be added to the \a layout;
802 otherwise returns \c false.
803*/
804bool QLayoutPrivate::checkLayout(QLayout *otherLayout) const
805{
806 Q_Q(const QLayout);
807 if (Q_UNLIKELY(!otherLayout)) {
808 qWarning("QLayout: Cannot add a null layout to %s/%ls",
809 q->metaObject()->className(), qUtf16Printable(q->objectName()));
810 return false;
811 }
812 if (Q_UNLIKELY(otherLayout == q)) {
813 qWarning("QLayout: Cannot add layout %s/%ls to itself",
814 q->metaObject()->className(), qUtf16Printable(q->objectName()));
815 return false;
816 }
817 return true;
818}
819
820/*!
821 This function is called from \c addWidget() functions in
822 subclasses to add \a w as a managed widget of a layout.
823
824 If \a w is already managed by a layout, this function will produce
825 a warning, and remove \a w from that layout. This function must
826 therefore be called before adding \a w to the layout's data
827 structure.
828*/
829void QLayout::addChildWidget(QWidget *w)
830{
831 QWidget *mw = parentWidget();
832 QWidget *pw = w->parentWidget();
833
834 //Qt::WA_LaidOut is never reset. It only means that the widget at some point has
835 //been in a layout.
836 if (pw && w->testAttribute(Qt::WA_LaidOut)) {
837 QLayout *l = pw->layout();
838 if (l && removeWidgetRecursively(l, w)) {
839#ifdef QT_DEBUG
840 if (Q_UNLIKELY(layoutDebug()))
841 qWarning("QLayout::addChildWidget: %s \"%ls\" is already in a layout; moved to new layout",
842 w->metaObject()->className(), qUtf16Printable(w->objectName()));
843#endif
844 }
845 }
846 if (pw && mw && pw != mw) {
847#ifdef QT_DEBUG
848 if (Q_UNLIKELY(layoutDebug()))
849 qWarning("QLayout::addChildWidget: %s \"%ls\" in wrong parent; moved to correct parent",
850 w->metaObject()->className(), qUtf16Printable(w->objectName()));
851#endif
852 pw = nullptr;
853 }
854 bool needShow = mw && mw->isVisible() && !QWidgetPrivate::get(w)->isExplicitlyHidden();
855 if (!pw && mw)
856 w->setParent(mw);
857 w->setAttribute(Qt::WA_LaidOut);
858 if (needShow)
859 QMetaObject::invokeMethod(w, "_q_showIfNotHidden", Qt::QueuedConnection); //show later
860}
861
862/*!
863 Tells the geometry manager to place the menu bar \a widget at the
864 top of parentWidget(), outside QWidget::contentsMargins(). All
865 child widgets are placed below the bottom edge of the menu bar.
866*/
867void QLayout::setMenuBar(QWidget *widget)
868{
869 Q_D(QLayout);
870 if (widget)
871 addChildWidget(widget);
872 d->menubar = widget;
873}
874
875/*!
876 Returns the menu bar set for this layout, or \nullptr if no
877 menu bar is set.
878*/
879
880QWidget *QLayout::menuBar() const
881{
882 Q_D(const QLayout);
883 return d->menubar;
884}
885
886
887/*!
888 Returns the minimum size of this layout. This is the smallest
889 size that the layout can have while still respecting the
890 specifications.
891
892 The returned value doesn't include the space required by
893 QWidget::setContentsMargins() or menuBar().
894
895 The default implementation allows unlimited resizing.
896*/
897QSize QLayout::minimumSize() const
898{
899 return QSize(0, 0);
900}
901
902/*!
903 Returns the maximum size of this layout. This is the largest size
904 that the layout can have while still respecting the
905 specifications.
906
907 The returned value doesn't include the space required by
908 QWidget::setContentsMargins() or menuBar().
909
910 The default implementation allows unlimited resizing.
911*/
912QSize QLayout::maximumSize() const
913{
914 return QSize(QLAYOUTSIZE_MAX, QLAYOUTSIZE_MAX);
915}
916
917/*!
918 Returns whether this layout can make use of more space than
919 sizeHint(). A value of Qt::Vertical or Qt::Horizontal means that
920 it wants to grow in only one dimension, whereas Qt::Vertical |
921 Qt::Horizontal means that it wants to grow in both dimensions.
922
923 The default implementation returns Qt::Horizontal | Qt::Vertical.
924 Subclasses reimplement it to return a meaningful value based on
925 their child widgets's \l{QSizePolicy}{size policies}.
926
927 \sa sizeHint()
928*/
929Qt::Orientations QLayout::expandingDirections() const
930{
931 return Qt::Horizontal | Qt::Vertical;
932}
933
934void QLayout::activateRecursiveHelper(QLayoutItem *item)
935{
936 item->invalidate();
937 QLayout *layout = item->layout();
938 if (layout) {
939 QLayoutItem *child;
940 int i=0;
941 while ((child = layout->itemAt(i++)))
942 activateRecursiveHelper(child);
943 layout->d_func()->activated = true;
944 }
945}
946
947/*!
948 Updates the layout for parentWidget().
949
950 You should generally not need to call this because it is
951 automatically called at the most appropriate times.
952
953 \sa activate(), invalidate()
954*/
955
956void QLayout::update()
957{
958 QLayout *layout = this;
959 while (layout && layout->d_func()->activated) {
960 layout->d_func()->activated = false;
961 if (layout->d_func()->topLevel) {
962 Q_ASSERT(layout->parent()->isWidgetType());
963 QWidget *mw = static_cast<QWidget*>(layout->parent());
964 QCoreApplication::postEvent(mw, new QEvent(QEvent::LayoutRequest));
965 break;
966 }
967 layout = static_cast<QLayout*>(layout->parent());
968 }
969}
970
971/*!
972 Redoes the layout for parentWidget() if necessary.
973
974 You should generally not need to call this because it is
975 automatically called at the most appropriate times. It returns
976 true if the layout was redone.
977
978 \sa update(), QWidget::updateGeometry()
979*/
980bool QLayout::activate()
981{
982 Q_D(QLayout);
983 if (!d->enabled || !parent())
984 return false;
985 if (!d->topLevel)
986 return static_cast<QLayout*>(parent())->activate();
987 if (d->activated)
988 return false;
989 QWidget *mw = static_cast<QWidget*>(parent());
990 if (Q_UNLIKELY(!mw)) {
991 qWarning("QLayout::activate: %s \"%ls\" does not have a main widget",
992 metaObject()->className(), qUtf16Printable(objectName()));
993 return false;
994 }
995 activateRecursiveHelper(this);
996
997 QWidgetPrivate *md = mw->d_func();
998 uint explMin = md->extra ? md->extra->explicitMinSize : 0;
999 uint explMax = md->extra ? md->extra->explicitMaxSize : 0;
1000
1001 // Do actual calculation
1002 // Result values (needs to be zero or greater to be considered valid/set)
1003 // We make some illegal values different from each other due a later compare.
1004 // ### In the future we may want minSize(0, 0) and maxSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)
1005 // ### Also see comment below.
1006 QSize minSize(-1, -1);
1007 QSize maxSize(-2, -2);
1008
1009 // Potentially cached values to avoid calling the same function more times.
1010 constexpr QSize empty(0, 0);
1011 QSize totalSzH = empty;
1012 QSize totalMinSz = empty;
1013 QSize totalMaxSz = empty;
1014
1015 switch (d->verticalConstraint) {
1016 case SetFixedSize:
1017 totalSzH = totalSizeHint();
1018 minSize.setHeight(totalSzH.height());
1019 maxSize.setHeight(totalSzH.height());
1020 break;
1021 case SetMinimumSize:
1022 totalMinSz = totalMinimumSize();
1023 minSize.setHeight(totalMinSz.height());
1024 break;
1025 case SetMaximumSize:
1026 totalMaxSz = totalMaximumSize();
1027 maxSize.setHeight(totalMaxSz.height());
1028 break;
1029 case SetMinAndMaxSize:
1030 totalMinSz = totalMinimumSize();
1031 totalMaxSz = totalMaximumSize();
1032 minSize.setHeight(totalMinSz.height());
1033 maxSize.setHeight(totalMaxSz.height());
1034 break;
1035 case SetDefaultConstraint: {
1036 bool heightSet = explMin & Qt::Vertical;
1037 if (mw->isWindow()) {
1038 if (!heightSet) {
1039 totalMinSz = totalMinimumSize();
1040 minSize.setHeight(totalMinSz.height());
1041 } else {
1042 minSize.setHeight(mw->minimumHeight());
1043 }
1044 } else {
1045 minSize.setHeight(heightSet ? mw->minimumHeight() : 0);
1046 }
1047 break;
1048 }
1049 case SetNoConstraint:
1050 break;
1051 }
1052 switch (d->horizontalConstraint) {
1053 case SetFixedSize:
1054 if (totalSzH == empty)
1055 totalSzH = totalSizeHint();
1056 minSize.setWidth(totalSzH.width());
1057 maxSize.setWidth(totalSzH.width());
1058 break;
1059 case SetMinimumSize:
1060 if (totalMinSz == empty)
1061 totalMinSz = totalMinimumSize();
1062 minSize.setWidth(totalMinSz.width());
1063 break;
1064 case SetMaximumSize:
1065 if (totalMaxSz == empty)
1066 totalMaxSz = totalMaximumSize();
1067 maxSize.setWidth(totalMaxSz.width());
1068 break;
1069 case SetMinAndMaxSize:
1070 if (totalMinSz == empty)
1071 totalMinSz = totalMinimumSize();
1072 if (totalMaxSz == empty)
1073 totalMaxSz = totalMaximumSize();
1074
1075 minSize.setWidth(totalMinSz.width());
1076 maxSize.setWidth(totalMaxSz.width());
1077 break;
1078 case SetDefaultConstraint: {
1079 const bool widthSet = explMin & Qt::Horizontal;
1080 if (mw->isWindow()) {
1081 if (!widthSet) {
1082 if (totalMinSz == empty)
1083 totalMinSz = totalMinimumSize();
1084 minSize.setWidth(totalMinSz.width());
1085 } else {
1086 minSize.setWidth(mw->minimumWidth());
1087 }
1088 } else {
1089 minSize.setWidth(widthSet ? mw->minimumWidth() : 0);
1090 }
1091 break;
1092 }
1093 case SetNoConstraint:
1094 break;
1095 }
1096 if (minSize == maxSize) {
1097 mw->setFixedSize(minSize);
1098 }
1099 else {
1100 // ### To preserve backward compatibility with behavior prior to introducing separate
1101 // ### horizontal and vertical constraints, we only update the specific size properties
1102 // ### dictated by the constraints. For example, if only minimum width is specified
1103 // ### by the constraint, we leave the minimum height untouched.
1104 // ### Like before we leave unconstrained values unchanged though it can
1105 // ### (unintentionally?) retain stale values.
1106
1107 // handle min-size
1108 if (minSize.isValid())
1109 mw->setMinimumSize(minSize);
1110 else if (minSize.width() >= 0)
1111 mw->setMinimumWidth(minSize.width());
1112 else if (minSize.height() >= 0)
1113 mw->setMinimumHeight(minSize.height());
1114
1115 // handle max-size
1116 if (maxSize.isValid())
1117 mw->setMaximumSize(maxSize);
1118 else if (maxSize.width() >= 0)
1119 mw->setMaximumWidth(maxSize.width());
1120 else if (maxSize.height() >= 0)
1121 mw->setMaximumHeight(maxSize.height());
1122 }
1123
1124 d->doResize();
1125
1126 if (md->extra) {
1127 md->extra->explicitMinSize = explMin;
1128 md->extra->explicitMaxSize = explMax;
1129 }
1130 // ideally only if sizeHint() or sizePolicy() has changed
1131 mw->updateGeometry();
1132 return true;
1133}
1134
1135/*!
1136 \since 5.2
1137
1138 Searches for widget \a from and replaces it with widget \a to if found.
1139 Returns the layout item that contains the widget \a from on success.
1140 Otherwise \nullptr is returned.
1141 If \a options contains \c Qt::FindChildrenRecursively (the default),
1142 sub-layouts are searched for doing the replacement.
1143 Any other flag in \a options is ignored.
1144
1145 Notice that the returned item therefore might not belong to this layout,
1146 but to a sub-layout.
1147
1148 The returned layout item is no longer owned by the layout and should be
1149 either deleted or inserted to another layout. The widget \a from is no
1150 longer managed by the layout and may need to be deleted or hidden. The
1151 parent of widget \a from is left unchanged.
1152
1153 This function works for the built-in Qt layouts, but might not work for
1154 custom layouts.
1155
1156 \sa indexOf()
1157*/
1158
1159QLayoutItem *QLayout::replaceWidget(QWidget *from, QWidget *to, Qt::FindChildOptions options)
1160{
1161 Q_D(QLayout);
1162 if (!from || !to)
1163 return nullptr;
1164 if (from == to) // Do not return a QLayoutItem for \a from, since ownership still
1165 return nullptr; // belongs to the layout (since nothing was changed)
1166
1167 int index = -1;
1168 QLayoutItem *item = nullptr;
1169 for (int u = 0; u < count(); ++u) {
1170 item = itemAt(u);
1171 if (!item)
1172 continue;
1173
1174 if (item->widget() == from) {
1175 index = u;
1176 break;
1177 }
1178
1179 if (item->layout() && (options & Qt::FindChildrenRecursively)) {
1180 QLayoutItem *r = item->layout()->replaceWidget(from, to, options);
1181 if (r)
1182 return r;
1183 }
1184 }
1185 if (index == -1)
1186 return nullptr;
1187
1188 addChildWidget(to);
1189 QLayoutItem *newitem = new QWidgetItem(to);
1190 newitem->setAlignment(item->alignment());
1191 QLayoutItem *r = d->replaceAt(index, newitem);
1192 if (!r)
1193 delete newitem;
1194 return r;
1195}
1196
1197/*!
1198 \fn QLayoutItem *QLayout::itemAt(int index) const
1199
1200 Must be implemented in subclasses to return the layout item at \a
1201 index. If there is no such item, the function must return \nullptr.
1202 Items are numbered consecutively from 0. If an item is deleted, other items will be renumbered.
1203
1204 This function can be used to iterate over a layout. The following
1205 code will draw a rectangle for each layout item in the layout structure of the widget.
1206
1207 \snippet code/src_gui_kernel_qlayout.cpp 0
1208
1209 \sa count(), takeAt()
1210*/
1211
1212/*!
1213 \fn QLayoutItem *QLayout::takeAt(int index)
1214
1215 Must be implemented in subclasses to remove the layout item at \a
1216 index from the layout, and return the item. If there is no such
1217 item, the function must do nothing and return 0. Items are numbered
1218 consecutively from 0. If an item is removed, other items will be
1219 renumbered.
1220
1221 The following code fragment shows a safe way to remove all items
1222 from a layout:
1223
1224 \snippet code/src_gui_kernel_qlayout.cpp 1
1225
1226 \sa itemAt(), count()
1227*/
1228
1229/*!
1230 \fn int *QLayout::count() const
1231
1232 Must be implemented in subclasses to return the number of items
1233 in the layout.
1234
1235 \sa itemAt()
1236*/
1237
1238/*!
1239 Searches for widget \a widget in this layout (not including child
1240 layouts).
1241
1242 Returns the index of \a widget, or -1 if \a widget is not found.
1243
1244 The default implementation iterates over all items using itemAt().
1245*/
1246int QLayout::indexOf(const QWidget *widget) const
1247{
1248 const int c = count();
1249
1250 for (int i = 0; i < c; ++i) {
1251 if (itemAt(i)->widget() == widget)
1252 return i;
1253 }
1254
1255 return -1;
1256}
1257
1258/*!
1259 \since 5.12
1260 Searches for layout item \a layoutItem in this layout (not including child
1261 layouts).
1262
1263 Returns the index of \a layoutItem, or -1 if \a layoutItem is not found.
1264*/
1265int QLayout::indexOf(const QLayoutItem *layoutItem) const
1266{
1267 const int c = count();
1268
1269 for (int i = 0; i < c; ++i) {
1270 if (itemAt(i) == layoutItem)
1271 return i;
1272 }
1273
1274 return -1;
1275}
1276
1277/*!
1278 \enum QLayout::SizeConstraint
1279 Describes how the layout constrains the size of the widget.
1280
1281 A vertical constraint affects the widget's height, while a horizontal constraint affects its width.
1282
1283 The possible values are:
1284
1285 \value SetDefaultConstraint
1286 In the constrained orientation(s), the widget’s minimum extent
1287 is set to \l minimumSize(), unless a minimum size has already been set.
1288
1289 \value SetFixedSize
1290 In the constrained orientation(s), the widget’s extent is set to
1291 \l sizeHint(), and it cannot be resized in that direction.
1292
1293 \value SetMinimumSize
1294 In the constrained orientation(s), the widget’s minimum extent
1295 is set to \l minimumSize().
1296
1297 \value SetMaximumSize
1298 In the constrained orientation(s), the widget’s maximum extent
1299 is set to \l maximumSize().
1300
1301 \value SetMinAndMaxSize
1302 In the constrained orientation(s), the widget’s minimum extent
1303 is set to \l minimumSize(), and the maximum extent is set to \l maximumSize().
1304
1305 \value SetNoConstraint
1306 No size constraints are applied to the widget.
1307
1308 \sa setSizeConstraint(), setSizeConstraints(), horizontalSizeConstraint(), setHorizontalSizeConstraint(), setVerticalSizeConstraint()
1309*/
1310
1311/*!
1312 \property QLayout::sizeConstraint
1313 \brief the resize mode of the layout.
1314 Setting the size constraint for the dialog.
1315 Setting a vertical or horizontal size constraint will override this.
1316
1317 The default mode is \l {QLayout::SetDefaultConstraint}
1318 {SetDefaultConstraint}.
1319
1320 \sa horizontalSizeConstraint(), verticalSizeConstraint()
1321*/
1322
1323void QLayout::setSizeConstraint(SizeConstraint constraint)
1324{
1325 setSizeConstraints(constraint, constraint);
1326}
1327
1328/*!
1329 \since 6.10
1330
1331 Sets both the \a horizontal and \a vertical size constraints.
1332
1333 \sa sizeConstraint(), horizontalSizeConstraint(), verticalSizeConstraint()
1334 */
1335void QLayout::setSizeConstraints(SizeConstraint horizontal, SizeConstraint vertical)
1336{
1337 Q_D(QLayout);
1338 if (horizontal == d->horizontalConstraint && vertical == d->verticalConstraint)
1339 return;
1340 d->horizontalConstraint = horizontal;
1341 d->verticalConstraint = vertical;
1342 invalidate();
1343}
1344
1345QLayout::SizeConstraint QLayout::sizeConstraint() const
1346{
1347 Q_D(const QLayout);
1348 return d->horizontalConstraint;
1349}
1350
1351/*!
1352 \property QLayout::horizontalSizeConstraint
1353 \since 6.10
1354 \brief The horizontal size constraint.
1355
1356 The default mode is \l {QLayout::SetDefaultConstraint}
1357
1358 \sa verticalSizeConstraint(), sizeConstraint()
1359*/
1360
1361void QLayout::setHorizontalSizeConstraint(SizeConstraint constraint)
1362{
1363 Q_D(QLayout);
1364 if (constraint == d->horizontalConstraint)
1365 return;
1366 d->horizontalConstraint = constraint;
1367 invalidate();
1368}
1369
1370
1371QLayout::SizeConstraint QLayout::horizontalSizeConstraint() const
1372{
1373 Q_D(const QLayout);
1374 return d->horizontalConstraint;
1375}
1376
1377/*!
1378 \property QLayout::verticalSizeConstraint
1379 \since 6.10
1380 \brief The vertical size constraint.
1381
1382 The default mode is \l {QLayout::SetDefaultConstraint}
1383
1384 \sa horizontalSizeConstraint(), sizeConstraint()
1385*/
1386
1387void QLayout::setVerticalSizeConstraint(SizeConstraint constraint)
1388{
1389 Q_D(QLayout);
1390 if (constraint == d->verticalConstraint)
1391 return;
1392 d->verticalConstraint = constraint;
1393 invalidate();
1394}
1395
1396QLayout::SizeConstraint QLayout::verticalSizeConstraint() const
1397{
1398 Q_D(const QLayout);
1399 return d->verticalConstraint;
1400}
1401
1402/*!
1403 Returns the rectangle that should be covered when the geometry of
1404 this layout is set to \a r, provided that this layout supports
1405 setAlignment().
1406
1407 The result is derived from sizeHint() and expandingDirections(). It is never
1408 larger than \a r.
1409*/
1410QRect QLayout::alignmentRect(const QRect &r) const
1411{
1412 QSize s = sizeHint();
1413 Qt::Alignment a = alignment();
1414
1415 /*
1416 This is a hack to obtain the real maximum size, not
1417 QSize(QLAYOUTSIZE_MAX, QLAYOUTSIZE_MAX), the value consistently
1418 returned by QLayoutItems that have an alignment.
1419 */
1420 QLayout *that = const_cast<QLayout *>(this);
1421 that->setAlignment({ });
1422 QSize ms = that->maximumSize();
1423 that->setAlignment(a);
1424
1425 if ((expandingDirections() & Qt::Horizontal) ||
1426 !(a & Qt::AlignHorizontal_Mask)) {
1427 s.setWidth(qMin(r.width(), ms.width()));
1428 }
1429 if ((expandingDirections() & Qt::Vertical) ||
1430 !(a & Qt::AlignVertical_Mask)) {
1431 s.setHeight(qMin(r.height(), ms.height()));
1432 } else if (hasHeightForWidth()) {
1433 int hfw = heightForWidth(s.width());
1434 if (hfw < s.height())
1435 s.setHeight(qMin(hfw, ms.height()));
1436 }
1437
1438 s = s.boundedTo(r.size());
1439 int x = r.x();
1440 int y = r.y();
1441
1442 if (a & Qt::AlignBottom)
1443 y += (r.height() - s.height());
1444 else if (!(a & Qt::AlignTop))
1445 y += (r.height() - s.height()) / 2;
1446
1447 QWidget *parent = parentWidget();
1448 a = QStyle::visualAlignment(parent ? parent->layoutDirection() : QGuiApplication::layoutDirection(), a);
1449 if (a & Qt::AlignRight)
1450 x += (r.width() - s.width());
1451 else if (!(a & Qt::AlignLeft))
1452 x += (r.width() - s.width()) / 2;
1453
1454 return QRect(x, y, s.width(), s.height());
1455}
1456
1457/*!
1458 Removes the widget \a widget from the layout. After this call, it
1459 is the caller's responsibility to give the widget a reasonable
1460 geometry or to put the widget back into a layout or to explicitly
1461 hide it if necessary.
1462
1463 \b{Note:} The ownership of \a widget remains the same as
1464 when it was added.
1465
1466 \sa removeItem(), QWidget::setGeometry(), addWidget()
1467*/
1468void QLayout::removeWidget(QWidget *widget)
1469{
1470 if (Q_UNLIKELY(!widget)) {
1471 qWarning("QLayout::removeWidget: Cannot remove a null widget.");
1472 return;
1473 }
1474
1475 int i = 0;
1476 QLayoutItem *child;
1477 while ((child = itemAt(i))) {
1478 if (child->widget() == widget) {
1479 delete takeAt(i);
1480 invalidate();
1481 } else {
1482 ++i;
1483 }
1484 }
1485}
1486
1487/*!
1488 Removes the layout item \a item from the layout. It is the
1489 caller's responsibility to delete the item.
1490
1491 Notice that \a item can be a layout (since QLayout inherits
1492 QLayoutItem).
1493
1494 \sa removeWidget(), addItem()
1495*/
1496void QLayout::removeItem(QLayoutItem *item)
1497{
1498 int i = 0;
1499 QLayoutItem *child;
1500 while ((child = itemAt(i))) {
1501 if (child == item) {
1502 takeAt(i);
1503 invalidate();
1504 } else {
1505 ++i;
1506 }
1507 }
1508}
1509
1510/*!
1511 Enables this layout if \a enable is true, otherwise disables it.
1512
1513 An enabled layout adjusts dynamically to changes; a disabled
1514 layout acts as if it did not exist.
1515
1516 By default all layouts are enabled.
1517
1518 \sa isEnabled()
1519*/
1520void QLayout::setEnabled(bool enable)
1521{
1522 Q_D(QLayout);
1523 d->enabled = enable;
1524}
1525
1526/*!
1527 Returns \c true if the layout is enabled; otherwise returns \c false.
1528
1529 \sa setEnabled()
1530*/
1531bool QLayout::isEnabled() const
1532{
1533 Q_D(const QLayout);
1534 return d->enabled;
1535}
1536
1537/*!
1538 Returns a size that satisfies all size constraints on \a widget,
1539 including heightForWidth() and that is as close as possible to \a
1540 size.
1541*/
1542
1543QSize QLayout::closestAcceptableSize(const QWidget *widget, const QSize &size)
1544{
1545 QSize result = size.boundedTo(qSmartMaxSize(widget));
1546 result = result.expandedTo(qSmartMinSize(widget));
1547 QLayout *l = widget->layout();
1548 if (l && l->hasHeightForWidth() && result.height() < l->minimumHeightForWidth(result.width()) ) {
1549 QSize current = widget->size();
1550 int currentHfw = l->minimumHeightForWidth(current.width());
1551 int newHfw = l->minimumHeightForWidth(result.width());
1552 if (current.height() < currentHfw || currentHfw == newHfw) {
1553 //handle the constant hfw case and the vertical-only case, as well as the
1554 // current-size-is-not-correct case
1555 result.setHeight(newHfw);
1556 } else {
1557 // binary search; assume hfw is decreasing ###
1558
1559 int maxw = qMax(widget->width(),result.width());
1560 int maxh = qMax(widget->height(), result.height());
1561 int minw = qMin(widget->width(),result.width());
1562 int minh = qMin(widget->height(), result.height());
1563
1564 int minhfw = l->minimumHeightForWidth(minw);
1565 int maxhfw = l->minimumHeightForWidth(maxw);
1566 while (minw < maxw) {
1567 if (minhfw > maxh) { //assume decreasing
1568 minw = maxw - (maxw-minw)/2;
1569 minhfw = l->minimumHeightForWidth(minw);
1570 } else if (maxhfw < minh ) { //assume decreasing
1571 maxw = minw + (maxw-minw)/2;
1572 maxhfw = l->minimumHeightForWidth(maxw);
1573 } else {
1574 break;
1575 }
1576 }
1577 result = result.expandedTo(QSize(minw, minhfw));
1578 }
1579 }
1580 return result;
1581}
1582
1583QT_END_NAMESPACE
1584
1585#include "moc_qlayout.cpp"
Combined button and popup list for selecting options.
static QT_BEGIN_NAMESPACE int menuBarHeightForWidth(QWidget *menubar, int w)
Definition qlayout.cpp:16
static bool removeWidgetRecursively(QLayoutItem *li, QObject *w)
Definition qlayout.cpp:478