QtBase  v6.3.1
qlayoutitem.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtWidgets module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #include "qlayout.h"
41 
42 #include "qapplication.h"
43 #include "qlayoutengine_p.h"
44 #if QT_CONFIG(menubar)
45 #include "qmenubar.h"
46 #endif
47 #if QT_CONFIG(toolbar)
48 #include "qtoolbar.h"
49 #endif
50 #include "qevent.h"
51 #include "qstyle.h"
52 #include "qvariant.h"
53 #include "qwidget_p.h"
54 
56 
57 inline static QRect fromLayoutItemRect(QWidgetPrivate *priv, const QRect &rect)
58 {
59  return rect.adjusted(priv->leftLayoutItemMargin, priv->topLayoutItemMargin,
61 }
62 
63 inline static QSize fromLayoutItemSize(QWidgetPrivate *priv, const QSize &size)
64 {
65  return fromLayoutItemRect(priv, QRect(QPoint(0, 0), size)).size();
66 }
67 
68 inline static QRect toLayoutItemRect(QWidgetPrivate *priv, const QRect &rect)
69 {
70  return rect.adjusted(-priv->leftLayoutItemMargin, -priv->topLayoutItemMargin,
72 }
73 
74 inline static QSize toLayoutItemSize(QWidgetPrivate *priv, const QSize &size)
75 {
76  return toLayoutItemRect(priv, QRect(QPoint(0, 0), size)).size();
77 }
78 
193 {
194  align = alignment;
195 }
196 
262 
278  QSizePolicy::Policy vPolicy)
279 {
280  width = w;
281  height = h;
282  sizeP = QSizePolicy(hPolicy, vPolicy);
283 }
284 
294 QWidgetItem::~QWidgetItem() = default;
295 
299 QLayoutItem::~QLayoutItem() = default;
300 
305 {
306 }
307 
315 {
316  return nullptr;
317 }
318 
326 {
327  return nullptr;
328 }
329 
334 {
335  return this;
336 }
337 
342 {
343  return this;
344 }
345 
364 {
365  return nullptr;
366 }
367 
372 {
373  return wid;
374 }
375 
387 {
388  return false;
389 }
390 
397 {
398  return heightForWidth(w);
399 }
400 
401 
420 int QLayoutItem::heightForWidth(int /* w */) const
421 {
422  return -1;
423 }
424 
433 QSizePolicy::ControlTypes QLayoutItem::controlTypes() const
434 {
436 }
437 
442 {
443  rect = r;
444 }
445 
450 {
451  if (isEmpty())
452  return;
453 
455  ? fromLayoutItemRect(wid->d_func(), rect)
456  : rect;
457  const QSize widgetRectSurplus = r.size() - rect.size();
458 
459  /*
460  For historical reasons, this code is done using widget rect
461  coordinates, not layout item rect coordinates. However,
462  QWidgetItem's sizeHint(), maximumSize(), and heightForWidth()
463  all work in terms of layout item rect coordinates, so we have to
464  add or subtract widgetRectSurplus here and there. The code could
465  be much simpler if we did everything using layout item rect
466  coordinates and did the conversion right before the call to
467  QWidget::setGeometry().
468  */
469 
470  QSize s = r.size().boundedTo(maximumSize() + widgetRectSurplus);
471  int x = r.x();
472  int y = r.y();
474  QSize pref(sizeHint());
476  if (sp.horizontalPolicy() == QSizePolicy::Ignored)
478  if (sp.verticalPolicy() == QSizePolicy::Ignored)
480  pref += widgetRectSurplus;
482  s.setWidth(qMin(s.width(), pref.width()));
484  if (hasHeightForWidth())
485  s.setHeight(qMin(s.height(),
486  heightForWidth(s.width() - widgetRectSurplus.width())
487  + widgetRectSurplus.height()));
488  else
489  s.setHeight(qMin(s.height(), pref.height()));
490  }
491  }
493  if (alignHoriz & Qt::AlignRight)
494  x = x + (r.width() - s.width());
495  else if (!(alignHoriz & Qt::AlignLeft))
496  x = x + (r.width() - s.width()) / 2;
497 
498  if (align & Qt::AlignBottom)
499  y = y + (r.height() - s.height());
500  else if (!(align & Qt::AlignTop))
501  y = y + (r.height() - s.height()) / 2;
502 
503  // Make sure we don't move outside of the parent, e.g when styles demand
504  // surplus space that exceeds the available margins (f.ex macOS with QGroupBox)
505  if (x < 0) {
506  s.rwidth() += x;
507  x = 0;
508  }
509  if (y < 0) {
510  s.rheight() += y;
511  y = 0;
512  }
513 
514  wid->setGeometry(x, y, s.width(), s.height());
515 }
516 
521 {
522  return rect;
523 }
524 
529 {
531  ? toLayoutItemRect(wid->d_func(), wid->geometry())
532  : wid->geometry();
533 }
534 
535 
540 {
541  if (isEmpty())
542  return false;
543  return wid->hasHeightForWidth();
544 }
545 
550 {
551  if (isEmpty())
552  return -1;
553 
555  ? fromLayoutItemSize(wid->d_func(), QSize(w, 0)).width()
556  : w;
557 
558  int hfw;
559  if (wid->layout())
560  hfw = wid->layout()->totalHeightForWidth(w);
561  else
562  hfw = wid->heightForWidth(w);
563 
564  if (hfw > wid->maximumHeight())
565  hfw = wid->maximumHeight();
566  if (hfw < wid->minimumHeight())
567  hfw = wid->minimumHeight();
568 
570  ? toLayoutItemSize(wid->d_func(), QSize(0, hfw)).height()
571  : hfw;
572 
573  if (hfw < 0)
574  hfw = 0;
575  return hfw;
576 }
577 
579 {
580  if (isEmpty())
581  return -1;
582 
584  ? fromLayoutItemSize(wid->d_func(), QSize(w, 0)).width()
585  : w;
586 
587  int hfw;
588  if (wid->layout())
590  else
591  hfw = wid->heightForWidth(w); // QWidget doesn't have minimumHeightForWidth()
592 
593  if (hfw > wid->maximumHeight())
594  hfw = wid->maximumHeight();
595  if (hfw < wid->minimumHeight())
596  hfw = wid->minimumHeight();
597 
599  ? toLayoutItemSize(wid->d_func(), QSize(0, hfw)).height()
600  : hfw;
601 
602  if (hfw < 0)
603  hfw = 0;
604  return hfw;
605 
606 }
607 
611 Qt::Orientations QSpacerItem::expandingDirections() const
612 {
613  return sizeP.expandingDirections();
614 }
615 
619 Qt::Orientations QWidgetItem::expandingDirections() const
620 {
621  if (isEmpty())
622  return {};
623 
624  Qt::Orientations e = wid->sizePolicy().expandingDirections();
625  /*
626  If the layout is expanding, we make the widget expanding, even if
627  its own size policy isn't expanding.
628  */
629  if (wid->layout()) {
632  e |= Qt::Horizontal;
635  e |= Qt::Vertical;
636  }
637 
639  e &= ~Qt::Horizontal;
641  e &= ~Qt::Vertical;
642  return e;
643 }
644 
649 {
650  return QSize(sizeP.horizontalPolicy() & QSizePolicy::ShrinkFlag ? 0 : width,
652 }
653 
658 {
659  if (isEmpty())
660  return QSize(0, 0);
662  ? toLayoutItemSize(wid->d_func(), qSmartMinSize(this))
663  : qSmartMinSize(this);
664 }
665 
670 {
673 }
674 
679 {
680  if (isEmpty()) {
681  return QSize(0, 0);
682  } else {
684  ? toLayoutItemSize(wid->d_func(), qSmartMaxSize(this, align))
685  : qSmartMaxSize(this, align);
686  }
687 }
688 
693 {
694  return QSize(width, height);
695 }
696 
701 {
702  QSize s(0, 0);
703  if (!isEmpty()) {
705  s = s.boundedTo(wid->maximumSize())
708  ? toLayoutItemSize(wid->d_func(), s)
709  : s;
710 
712  s.setWidth(0);
714  s.setHeight(0);
715  }
716  return s;
717 }
718 
723 {
724  return true;
725 }
726 
733 {
734  return (wid->isHidden() && !wid->sizePolicy().retainSizeWhenHidden()) || wid->isWindow();
735 }
736 
743 QSizePolicy::ControlTypes QWidgetItem::controlTypes() const
744 {
745  return wid->sizePolicy().controlType();
746 }
747 
753 inline bool QWidgetItemV2::useSizeCache() const
754 {
755  return wid->d_func()->widgetItem == this;
756 }
757 
758 void QWidgetItemV2::updateCacheIfNecessary() const
759 {
760  if (q_cachedMinimumSize.width() != Dirty)
761  return;
762 
763  const QSize sizeHint(wid->sizeHint());
764  const QSize minimumSizeHint(wid->minimumSizeHint());
765  const QSize minimumSize(wid->minimumSize());
766  const QSize maximumSize(wid->maximumSize());
768  const QSize expandedSizeHint(sizeHint.expandedTo(minimumSizeHint));
769 
770  const QSize smartMinSize(qSmartMinSize(sizeHint, minimumSizeHint, minimumSize, maximumSize, sizePolicy));
771  const QSize smartMaxSize(qSmartMaxSize(expandedSizeHint, minimumSize, maximumSize, sizePolicy, align));
772 
773  const bool useLayoutItemRect = !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect);
774 
775  q_cachedMinimumSize = useLayoutItemRect
776  ? toLayoutItemSize(wid->d_func(), smartMinSize)
777  : smartMinSize;
778 
779  q_cachedSizeHint = expandedSizeHint;
780  q_cachedSizeHint = q_cachedSizeHint.boundedTo(maximumSize)
782  q_cachedSizeHint = useLayoutItemRect
783  ? toLayoutItemSize(wid->d_func(), q_cachedSizeHint)
784  : q_cachedSizeHint;
785 
787  q_cachedSizeHint.setWidth(0);
789  q_cachedSizeHint.setHeight(0);
790 
791  q_cachedMaximumSize = useLayoutItemRect
792  ? toLayoutItemSize(wid->d_func(), smartMaxSize)
793  : smartMaxSize;
794 }
795 
797  : QWidgetItem(widget),
798  q_cachedMinimumSize(Dirty, Dirty),
799  q_cachedSizeHint(Dirty, Dirty),
800  q_cachedMaximumSize(Dirty, Dirty),
801  q_firstCachedHfw(0),
802  q_hfwCacheSize(0),
803  d(nullptr)
804 {
805  QWidgetPrivate *wd = wid->d_func();
806  if (!wd->widgetItem)
807  wd->widgetItem = this;
808 }
809 
811 {
812  if (wid) {
813  auto *wd = static_cast<QWidgetPrivate *>(QObjectPrivate::get(wid));
814  if (wd->widgetItem == this)
815  wd->widgetItem = nullptr;
816  }
817 }
818 
820 {
821  if (isEmpty())
822  return QSize(0, 0);
823 
824  if (useSizeCache()) {
825  updateCacheIfNecessary();
826  return q_cachedSizeHint;
827  } else {
828  return QWidgetItem::sizeHint();
829  }
830 }
831 
833 {
834  if (isEmpty())
835  return QSize(0, 0);
836 
837  if (useSizeCache()) {
838  updateCacheIfNecessary();
839  return q_cachedMinimumSize;
840  } else {
841  return QWidgetItem::minimumSize();
842  }
843 }
844 
846 {
847  if (isEmpty())
848  return QSize(0, 0);
849 
850  if (useSizeCache()) {
851  updateCacheIfNecessary();
852  return q_cachedMaximumSize;
853  } else {
854  return QWidgetItem::maximumSize();
855  }
856 }
857 
858 /*
859  The height-for-width cache is organized as a circular buffer. The entries
860 
861  q_hfwCachedHfws[q_firstCachedHfw],
862  ...,
863  q_hfwCachedHfws[(q_firstCachedHfw + q_hfwCacheSize - 1) % HfwCacheMaxSize]
864 
865  contain the last cached values. When the cache is full, the first entry to
866  be erased is the entry before q_hfwCachedHfws[q_firstCachedHfw]. When
867  values are looked up, we try to move q_firstCachedHfw to point to that new
868  entry (unless the cache is not full, in which case it would leave the cache
869  in a broken state), so that the most recently used entry is also the last
870  to be erased.
871 */
872 
874 {
875  if (isEmpty())
876  return -1;
877 
878  for (int i = 0; i < q_hfwCacheSize; ++i) {
879  int offset = q_firstCachedHfw + i;
880  const QSize &size = q_cachedHfws[offset % HfwCacheMaxSize];
881  if (size.width() == width) {
882  if (q_hfwCacheSize == HfwCacheMaxSize)
883  q_firstCachedHfw = offset % HfwCacheMaxSize;
884  return size.height();
885  }
886  }
887 
888  if (q_hfwCacheSize < HfwCacheMaxSize)
889  ++q_hfwCacheSize;
890  q_firstCachedHfw = (q_firstCachedHfw + HfwCacheMaxSize - 1) % HfwCacheMaxSize;
891 
893  q_cachedHfws[q_firstCachedHfw] = QSize(width, height);
894  return height;
895 }
896 
small capitals from c petite p scientific i
[1]
Definition: afcover.h:80
The QLayout class is the base class of geometry managers.
Definition: qlayout.h:62
int totalHeightForWidth(int w) const
Definition: qlayout.cpp:633
int totalMinimumHeightForWidth(int w) const
Definition: qlayout.cpp:611
Qt::Orientations expandingDirections() const override
Definition: qlayout.cpp:977
QLayout * layout() override
virtual QSizePolicy::ControlTypes controlTypes() const
virtual bool hasHeightForWidth() const
virtual int heightForWidth(int) const
virtual QLayout * layout()
Qt::Alignment align
Definition: qlayoutitem.h:86
virtual ~QLayoutItem()
Qt::Alignment alignment() const
Definition: qlayoutitem.h:81
virtual QSpacerItem * spacerItem()
virtual int minimumHeightForWidth(int) const
virtual QWidget * widget() const
virtual void invalidate()
void setAlignment(Qt::Alignment a)
static QObjectPrivate * get(QObject *o)
Definition: qobject_p.h:368
The QPoint class defines a point in the plane using integer precision.
Definition: qpoint.h:52
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:59
constexpr QSize size() const noexcept
Definition: qrect.h:269
The QSize class defines the size of a two-dimensional object using integer point precision.
Definition: qsize.h:55
constexpr QSize boundedTo(const QSize &) const noexcept
Definition: qsize.h:224
constexpr int height() const noexcept
Definition: qsize.h:160
constexpr int width() const noexcept
Definition: qsize.h:157
constexpr QSize expandedTo(const QSize &) const noexcept
Definition: qsize.h:219
constexpr void setWidth(int w) noexcept
Definition: qsize.h:163
constexpr void setHeight(int h) noexcept
Definition: qsize.h:166
The QSizePolicy class is a layout attribute describing horizontal and vertical resizing policy.
Definition: qsizepolicy.h:54
constexpr Policy verticalPolicy() const noexcept
Definition: qsizepolicy.h:103
ControlType controlType() const noexcept
constexpr bool retainSizeWhenHidden() const noexcept
Definition: qsizepolicy.h:133
constexpr Qt::Orientations expandingDirections() const noexcept
Definition: qsizepolicy.h:111
constexpr Policy horizontalPolicy() const noexcept
Definition: qsizepolicy.h:102
The QSpacerItem class provides blank space in a layout.
Definition: qlayoutitem.h:93
QSize sizeHint() const override
QRect geometry() const override
bool isEmpty() const override
QSpacerItem * spacerItem() override
QSize minimumSize() const override
void setGeometry(const QRect &) override
Qt::Orientations expandingDirections() const override
QSize maximumSize() const override
void changeSize(int w, int h, QSizePolicy::Policy hData=QSizePolicy::Minimum, QSizePolicy::Policy vData=QSizePolicy::Minimum)
static Qt::Alignment visualAlignment(Qt::LayoutDirection direction, Qt::Alignment alignment)
Definition: qstyle.cpp:2238
The QWidget class is the base class of all user interface objects.
Definition: qwidget.h:133
virtual bool hasHeightForWidth() const
Definition: qwidget.cpp:10295
void setGeometry(int x, int y, int w, int h)
Definition: qwidget.h:919
Qt::LayoutDirection layoutDirection
the layout direction for this widget.
Definition: qwidget.h:204
int minimumHeight
the widget's minimum height in pixels
Definition: qwidget.h:159
bool isHidden() const
Definition: qwidget.h:910
QSize minimumSize
the widget's minimum size
Definition: qwidget.h:154
QRect geometry
the geometry of the widget relative to its parent and excluding the window frame
Definition: qwidget.h:140
QLayout * layout() const
Definition: qwidget.cpp:10115
QSize maximumSize
the widget's maximum size in pixels
Definition: qwidget.h:155
QSizePolicy sizePolicy
the default layout behavior of the widget
Definition: qwidget.h:153
QSize minimumSizeHint
the recommended minimum size for the widget
Definition: qwidget.h:183
int maximumHeight
the widget's maximum height in pixels
Definition: qwidget.h:163
QSize sizeHint
the recommended size for the widget
Definition: qwidget.h:182
bool isWindow() const
Definition: qwidget.h:844
bool testAttribute(Qt::WidgetAttribute) const
Definition: qwidget.h:943
virtual int heightForWidth(int) const
Definition: qwidget.cpp:10282
The QWidgetItem class is a layout item that represents a widget.
Definition: qlayoutitem.h:122
bool isEmpty() const override
int minimumHeightForWidth(int) const override
QSize sizeHint() const override
QWidget * widget() const override
void setGeometry(const QRect &) override
QSizePolicy::ControlTypes controlTypes() const override
Qt::Orientations expandingDirections() const override
int heightForWidth(int) const override
QWidget * wid
Definition: qlayoutitem.h:143
QSize maximumSize() const override
bool hasHeightForWidth() const override
QRect geometry() const override
QSize minimumSize() const override
int heightForWidth(int width) const override
QWidgetItemV2(QWidget *widget)
QSize sizeHint() const override
QSize minimumSize() const override
QSize maximumSize() const override
signed char leftLayoutItemMargin
Definition: qwidget_p.h:716
signed char topLayoutItemMargin
Definition: qwidget_p.h:717
signed char bottomLayoutItemMargin
Definition: qwidget_p.h:719
signed char rightLayoutItemMargin
Definition: qwidget_p.h:718
QWidgetItemV2 * widgetItem
Definition: qwidget_p.h:673
QOpenGLWidget * widget
[1]
double e
rect
[4]
uint alignment
union Alignment_ Alignment
Definition: qnamespace.h:55
@ AlignRight
Definition: qnamespace.h:171
@ AlignBottom
Definition: qnamespace.h:179
@ AlignTop
Definition: qnamespace.h:178
@ AlignHorizontal_Mask
Definition: qnamespace.h:176
@ AlignVertical_Mask
Definition: qnamespace.h:186
@ AlignLeft
Definition: qnamespace.h:169
@ WA_LayoutUsesWidgetRect
Definition: qnamespace.h:390
@ Horizontal
Definition: qnamespace.h:124
@ Vertical
Definition: qnamespace.h:125
const char * sizePolicy(int v)
Definition: language.cpp:146
Q_WIDGETS_EXPORT QSize qSmartMinSize(const QSize &sizeHint, const QSize &minSizeHint, const QSize &minSize, const QSize &maxSize, const QSizePolicy &sizePolicy)
Q_WIDGETS_EXPORT QSize qSmartMaxSize(const QSize &sizeHint, const QSize &minSize, const QSize &maxSize, const QSizePolicy &sizePolicy, Qt::Alignment align)
constexpr QT_BEGIN_NAMESPACE int QLAYOUTSIZE_MAX
Definition: qlayoutitem.h:52
GLint GLint GLint GLint GLint x
[0]
GLboolean r
[2]
GLfloat GLfloat GLfloat w
[0]
GLint GLsizei GLsizei height
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLint GLsizei width
GLenum GLuint GLintptr offset
GLint y
GLfloat GLfloat GLfloat GLfloat h
GLdouble s
[6]
Definition: qopenglext.h:235
#define sp
QObject::connect nullptr