Qt 4.8
qlayoutitem.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtGui 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 Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qlayout.h"
43 
44 #include "qapplication.h"
45 #include "qlayoutengine_p.h"
46 #include "qmenubar.h"
47 #include "qtoolbar.h"
48 #include "qevent.h"
49 #include "qstyle.h"
50 #include "qvariant.h"
51 #include "qwidget_p.h"
52 
54 
55 inline static QRect fromLayoutItemRect(QWidgetPrivate *priv, const QRect &rect)
56 {
57  return rect.adjusted(priv->leftLayoutItemMargin, priv->topLayoutItemMargin,
59 }
60 
61 inline static QSize fromLayoutItemSize(QWidgetPrivate *priv, const QSize &size)
62 {
63  return fromLayoutItemRect(priv, QRect(QPoint(0, 0), size)).size();
64 }
65 
66 inline static QRect toLayoutItemRect(QWidgetPrivate *priv, const QRect &rect)
67 {
68  return rect.adjusted(-priv->leftLayoutItemMargin, -priv->topLayoutItemMargin,
70 }
71 
72 inline static QSize toLayoutItemSize(QWidgetPrivate *priv, const QSize &size)
73 {
74  return toLayoutItemRect(priv, QRect(QPoint(0, 0), size)).size();
75 }
76 
80 QSizePolicy::operator QVariant() const
81 {
82  return QVariant(QVariant::SizePolicy, this);
83 }
84 
207 void QLayoutItem::setAlignment(Qt::Alignment alignment)
208 {
209  align = alignment;
210 }
211 
311 void QSpacerItem::changeSize(int w, int h, QSizePolicy::Policy hPolicy,
312  QSizePolicy::Policy vPolicy)
313 {
314  width = w;
315  height = h;
316  sizeP = QSizePolicy(hPolicy, vPolicy);
317 }
318 
329 {
330 }
331 
336 {
337 }
338 
344 {
345  return 0;
346 }
347 
353 {
354  return 0;
355 }
356 
361 {
362  return this;
363 }
364 
369 {
370  return this;
371 }
372 
378 {
379  return 0;
380 }
381 
386 {
387  return wid;
388 }
389 
401 {
402  return false;
403 }
404 
411 {
412  return heightForWidth(w);
413 }
414 
415 
434 int QLayoutItem::heightForWidth(int /* w */) const
435 {
436  return -1;
437 }
438 
447 QSizePolicy::ControlTypes QLayoutItem::controlTypes() const
448 {
449  // ### Qt 5: This function should probably be virtual instead
450  if (const QWidget *widget = const_cast<QLayoutItem*>(this)->widget()) {
451  return widget->sizePolicy().controlType();
452  } else if (const QLayout *layout = const_cast<QLayoutItem*>(this)->layout()) {
453  if (layout->count() == 0)
455  QSizePolicy::ControlTypes types;
456  for (int i = layout->count() - 1; i >= 0; --i)
457  types |= layout->itemAt(i)->controlTypes();
458  return types;
459  }
461 }
462 
467 {
468  rect = r;
469 }
470 
475 {
476  if (isEmpty())
477  return;
478 
479  QRect r = !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
480  ? fromLayoutItemRect(wid->d_func(), rect)
481  : rect;
482  const QSize widgetRectSurplus = r.size() - rect.size();
483 
484  /*
485  For historical reasons, this code is done using widget rect
486  coordinates, not layout item rect coordinates. However,
487  QWidgetItem's sizeHint(), maximumSize(), and heightForWidth()
488  all work in terms of layout item rect coordinates, so we have to
489  add or subtract widgetRectSurplus here and there. The code could
490  be much simpler if we did everything using layout item rect
491  coordinates and did the conversion right before the call to
492  QWidget::setGeometry().
493  */
494 
495  QSize s = r.size().boundedTo(maximumSize() + widgetRectSurplus);
496  int x = r.x();
497  int y = r.y();
499  QSize pref(sizeHint());
500  QSizePolicy sp = wid->sizePolicy();
502  pref.setWidth(wid->sizeHint().expandedTo(wid->minimumSize()).width());
504  pref.setHeight(wid->sizeHint().expandedTo(wid->minimumSize()).height());
505  pref += widgetRectSurplus;
507  s.setWidth(qMin(s.width(), pref.width()));
509  if (hasHeightForWidth())
510  s.setHeight(qMin(s.height(),
511  heightForWidth(s.width() - widgetRectSurplus.width())
512  + widgetRectSurplus.height()));
513  else
514  s.setHeight(qMin(s.height(), pref.height()));
515  }
516  }
517  Qt::Alignment alignHoriz = QStyle::visualAlignment(wid->layoutDirection(), align);
518  if (alignHoriz & Qt::AlignRight)
519  x = x + (r.width() - s.width());
520  else if (!(alignHoriz & Qt::AlignLeft))
521  x = x + (r.width() - s.width()) / 2;
522 
523  if (align & Qt::AlignBottom)
524  y = y + (r.height() - s.height());
525  else if (!(align & Qt::AlignTop))
526  y = y + (r.height() - s.height()) / 2;
527 
528  wid->setGeometry(x, y, s.width(), s.height());
529 }
530 
535 {
536  return rect;
537 }
538 
543 {
544  return !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
545  ? toLayoutItemRect(wid->d_func(), wid->geometry())
546  : wid->geometry();
547 }
548 
549 
554 {
555  if (isEmpty())
556  return false;
557  return wid->d_func()->hasHeightForWidth();
558 }
559 
564 {
565  if (isEmpty())
566  return -1;
567 
568  w = !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
569  ? fromLayoutItemSize(wid->d_func(), QSize(w, 0)).width()
570  : w;
571 
572  int hfw;
573  if (wid->layout())
574  hfw = wid->layout()->totalHeightForWidth(w);
575  else
576  hfw = wid->heightForWidth(w);
577 
578  if (hfw > wid->maximumHeight())
579  hfw = wid->maximumHeight();
580  if (hfw < wid->minimumHeight())
581  hfw = wid->minimumHeight();
582 
583  hfw = !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
584  ? toLayoutItemSize(wid->d_func(), QSize(0, hfw)).height()
585  : hfw;
586 
587  if (hfw < 0)
588  hfw = 0;
589  return hfw;
590 }
591 
595 Qt::Orientations QSpacerItem::expandingDirections() const
596 {
597  return sizeP.expandingDirections();
598 }
599 
603 Qt::Orientations QWidgetItem::expandingDirections() const
604 {
605  if (isEmpty())
606  return Qt::Orientations(0);
607 
608  Qt::Orientations e = wid->sizePolicy().expandingDirections();
609  /*
610  ### Qt 4.0:
611  If the layout is expanding, we make the widget expanding, even if
612  its own size policy isn't expanding. This behavior should be
613  reconsidered.
614  */
615  if (wid->layout()) {
616  if (wid->sizePolicy().horizontalPolicy() & QSizePolicy::GrowFlag
617  && (wid->layout()->expandingDirections() & Qt::Horizontal))
618  e |= Qt::Horizontal;
619  if (wid->sizePolicy().verticalPolicy() & QSizePolicy::GrowFlag
620  && (wid->layout()->expandingDirections() & Qt::Vertical))
621  e |= Qt::Vertical;
622  }
623 
625  e &= ~Qt::Horizontal;
627  e &= ~Qt::Vertical;
628  return e;
629 }
630 
635 {
636  return QSize(sizeP.horizontalPolicy() & QSizePolicy::ShrinkFlag ? 0 : width,
637  sizeP.verticalPolicy() & QSizePolicy::ShrinkFlag ? 0 : height);
638 }
639 
644 {
645  if (isEmpty())
646  return QSize(0, 0);
647  return !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
648  ? toLayoutItemSize(wid->d_func(), qSmartMinSize(this))
649  : qSmartMinSize(this);
650 }
651 
656 {
657  return QSize(sizeP.horizontalPolicy() & QSizePolicy::GrowFlag ? QLAYOUTSIZE_MAX : width,
658  sizeP.verticalPolicy() & QSizePolicy::GrowFlag ? QLAYOUTSIZE_MAX : height);
659 }
660 
665 {
666  if (isEmpty()) {
667  return QSize(0, 0);
668  } else {
669  return !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
670  ? toLayoutItemSize(wid->d_func(), qSmartMaxSize(this, align))
671  : qSmartMaxSize(this, align);
672  }
673 }
674 
679 {
680  return QSize(width, height);
681 }
682 
687 {
688  QSize s(0, 0);
689  if (!isEmpty()) {
690  s = wid->sizeHint().expandedTo(wid->minimumSizeHint());
691  s = s.boundedTo(wid->maximumSize())
692  .expandedTo(wid->minimumSize());
693  s = !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
694  ? toLayoutItemSize(wid->d_func(), s)
695  : s;
696 
697  if (wid->sizePolicy().horizontalPolicy() == QSizePolicy::Ignored)
698  s.setWidth(0);
699  if (wid->sizePolicy().verticalPolicy() == QSizePolicy::Ignored)
700  s.setHeight(0);
701  }
702  return s;
703 }
704 
709 {
710  return true;
711 }
712 
719 {
720  return wid->isHidden() || wid->isWindow();
721 }
722 
728 inline bool QWidgetItemV2::useSizeCache() const
729 {
730  return wid->d_func()->widgetItem == this;
731 }
732 
734 {
735  if (q_cachedMinimumSize.width() != Dirty)
736  return;
737 
738  const QSize sizeHint(wid->sizeHint());
739  const QSize minimumSizeHint(wid->minimumSizeHint());
740  const QSize minimumSize(wid->minimumSize());
741  const QSize maximumSize(wid->maximumSize());
742  const QSizePolicy sizePolicy(wid->sizePolicy());
743  const QSize expandedSizeHint(sizeHint.expandedTo(minimumSizeHint));
744 
745  const QSize smartMinSize(qSmartMinSize(sizeHint, minimumSizeHint, minimumSize, maximumSize, sizePolicy));
746  const QSize smartMaxSize(qSmartMaxSize(expandedSizeHint, minimumSize, maximumSize, sizePolicy, align));
747 
748  const bool useLayoutItemRect = !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect);
749 
750  q_cachedMinimumSize = useLayoutItemRect
751  ? toLayoutItemSize(wid->d_func(), smartMinSize)
752  : smartMinSize;
753 
754  q_cachedSizeHint = expandedSizeHint;
755  q_cachedSizeHint = q_cachedSizeHint.boundedTo(maximumSize)
757  q_cachedSizeHint = useLayoutItemRect
758  ? toLayoutItemSize(wid->d_func(), q_cachedSizeHint)
759  : q_cachedSizeHint;
760 
761  if (wid->sizePolicy().horizontalPolicy() == QSizePolicy::Ignored)
762  q_cachedSizeHint.setWidth(0);
763  if (wid->sizePolicy().verticalPolicy() == QSizePolicy::Ignored)
764  q_cachedSizeHint.setHeight(0);
765 
766  q_cachedMaximumSize = useLayoutItemRect
767  ? toLayoutItemSize(wid->d_func(), smartMaxSize)
768  : smartMaxSize;
769 }
770 
772  : QWidgetItem(widget),
773  q_cachedMinimumSize(Dirty, Dirty),
774  q_cachedSizeHint(Dirty, Dirty),
775  q_cachedMaximumSize(Dirty, Dirty),
776  q_firstCachedHfw(0),
777  q_hfwCacheSize(0),
778  d(0)
779 {
780  QWidgetPrivate *wd = wid->d_func();
781  if (!wd->widgetItem)
782  wd->widgetItem = this;
783 }
784 
786 {
787  if (wid) {
788  QWidgetPrivate *wd = wid->d_func();
789  if (wd->widgetItem == this)
790  wd->widgetItem = 0;
791  }
792 }
793 
795 {
796  if (isEmpty())
797  return QSize(0, 0);
798 
799  if (useSizeCache()) {
801  return q_cachedSizeHint;
802  } else {
803  return QWidgetItem::sizeHint();
804  }
805 }
806 
808 {
809  if (isEmpty())
810  return QSize(0, 0);
811 
812  if (useSizeCache()) {
814  return q_cachedMinimumSize;
815  } else {
816  return QWidgetItem::minimumSize();
817  }
818 }
819 
821 {
822  if (isEmpty())
823  return QSize(0, 0);
824 
825  if (useSizeCache()) {
827  return q_cachedMaximumSize;
828  } else {
829  return QWidgetItem::maximumSize();
830  }
831 }
832 
833 /*
834  The height-for-width cache is organized as a circular buffer. The entries
835 
836  q_hfwCachedHfws[q_firstCachedHfw],
837  ...,
838  q_hfwCachedHfws[(q_firstCachedHfw + q_hfwCacheSize - 1) % HfwCacheMaxSize]
839 
840  contain the last cached values. When the cache is full, the first entry to
841  be erased is the entry before q_hfwCachedHfws[q_firstCachedHfw]. When
842  values are looked up, we try to move q_firstCachedHfw to point to that new
843  entry (unless the cache is not full, in which case it would leave the cache
844  in a broken state), so that the most recently used entry is also the last
845  to be erased.
846 */
847 
848 int QWidgetItemV2::heightForWidth(int width) const
849 {
850  if (isEmpty())
851  return -1;
852 
853  for (int i = 0; i < q_hfwCacheSize; ++i) {
854  int offset = q_firstCachedHfw + i;
855  const QSize &size = q_cachedHfws[offset % HfwCacheMaxSize];
856  if (size.width() == width) {
857  if (q_hfwCacheSize == HfwCacheMaxSize)
858  q_firstCachedHfw = offset;
859  return size.height();
860  }
861  }
862 
863  if (q_hfwCacheSize < HfwCacheMaxSize)
864  ++q_hfwCacheSize;
866 
867  int height = QWidgetItem::heightForWidth(width);
868  q_cachedHfws[q_firstCachedHfw] = QSize(width, height);
869  return height;
870 }
871 
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:92
QSize maximumSize() const
Reimplemented Function
double d
Definition: qnumeric_p.h:62
virtual QLayoutItem * itemAt(int index) const =0
Must be implemented in subclasses to return the layout item at index.
QSize sizeHint() const
Reimplemented Function
QRect adjusted(int x1, int y1, int x2, int y2) const
Returns a new rectangle with dx1, dy1, dx2 and dy2 added respectively to the existing coordinates of ...
Definition: qrect.h:431
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
Definition: qglobal.h:1215
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
Q_GUI_EXPORT QSize qSmartMinSize(const QSize &sizeHint, const QSize &minSizeHint, const QSize &minSize, const QSize &maxSize, const QSizePolicy &sizePolicy)
virtual ~QLayoutItem()
Destroys the QLayoutItem.
QSize sizeHint() const
Reimplemented Function
Qt::Orientations expandingDirections() const
Reimplemented Function
virtual bool isEmpty() const =0
Implemented in subclasses to return whether this item is empty, i.
Q_GUI_EXPORT QSize qSmartMaxSize(const QSize &sizeHint, const QSize &minSize, const QSize &maxSize, const QSizePolicy &sizePolicy, Qt::Alignment align)
Policy horizontalPolicy() const
Definition: qsizepolicy.h:118
virtual void invalidate()
Invalidates any cached information in this layout item.
The QWidget class is the base class of all user interface objects.
Definition: qwidget.h:150
QSizePolicy::ControlTypes controlTypes() const
Returns the control type(s) for the layout item.
QSize expandedTo(const QSize &) const
Returns a size holding the maximum width and height of this size and the given otherSize.
Definition: qsize.h:187
QSize sizeHint() const
Reimplemented Function
int width() const
Returns the width of the rectangle.
Definition: qrect.h:303
virtual int minimumHeightForWidth(int) const
Returns the minimum height this widget needs for the given width, w.
short q_firstCachedHfw
Definition: qlayoutitem.h:169
int height() const
Returns the height of the rectangle.
Definition: qrect.h:306
virtual QSize minimumSize() const =0
Implemented in subclasses to return the minimum size of this item.
void setHeight(int h)
Sets the height to the given height.
Definition: qsize.h:135
virtual bool hasHeightForWidth() const
Returns true if this layout&#39;s preferred height depends on its width; otherwise returns false...
int heightForWidth(int) const
Reimplemented Function
bool useSizeCache() const
static QRect toLayoutItemRect(QWidgetPrivate *priv, const QRect &rect)
Definition: qlayoutitem.cpp:66
QRect geometry() const
Reimplemented Function
QSpacerItem * spacerItem()
Returns a pointer to this object.
QSize boundedTo(const QSize &) const
Returns a size holding the minimum width and height of this size and the given otherSize.
Definition: qsize.h:192
signed char topLayoutItemMargin
Definition: qwidget_p.h:749
signed char bottomLayoutItemMargin
Definition: qwidget_p.h:751
virtual QWidget * widget()
Returns the widget managed by this item.
virtual QSpacerItem * spacerItem()
If this item is a QSpacerItem, it is returned as a QSpacerItem; otherwise 0 is returned.
QSize maximumSize() const
Reimplemented Function
void setWidth(int w)
Sets the width to the given width.
Definition: qsize.h:132
int width() const
Returns the width.
Definition: qsize.h:126
QSize minimumSize() const
Reimplemented Function
void setAlignment(Qt::Alignment a)
Sets the alignment of this item to alignment.
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
QWidgetItemV2(QWidget *widget)
Qt::Orientations expandingDirections() const
Reimplemented Function
QSize q_cachedMaximumSize
Definition: qlayoutitem.h:167
The QSpacerItem class provides blank space in a layout.
Definition: qlayoutitem.h:96
The QLayout class is the base class of geometry managers.
Definition: qlayout.h:90
static QSize toLayoutItemSize(QWidgetPrivate *priv, const QSize &size)
Definition: qlayoutitem.cpp:72
QSize size() const
Returns the size of the rectangle.
Definition: qrect.h:309
void setGeometry(const QRect &)
Reimplemented Function
bool isEmpty() const
Returns true if the widget is hidden; otherwise returns false.
The QWidgetItem class is a layout item that represents a widget.
Definition: qlayoutitem.h:122
QSize minimumSize() const
Reimplemented Function
static Qt::Alignment visualAlignment(Qt::LayoutDirection direction, Qt::Alignment alignment)
Transforms an alignment of Qt::AlignLeft or Qt::AlignRight without Qt::AlignAbsolute into Qt::AlignLe...
Definition: qstyle.cpp:2149
static QRect fromLayoutItemRect(QWidgetPrivate *priv, const QRect &rect)
Definition: qlayoutitem.cpp:55
static const struct @32 types[]
QWidgetItemV2 * widgetItem
Definition: qwidget_p.h:707
virtual int count() const =0
Must be implemented in subclasses to return the number of items in the layout.
int heightForWidth(int width) const
Reimplemented Function
int y() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:255
bool isEmpty() const
Returns true.
virtual QSize sizeHint() const =0
Implemented in subclasses to return the preferred size of this item.
virtual QLayout * layout()
If this item is a QLayout, it is returned as a QLayout; otherwise 0 is returned.
void setGeometry(const QRect &)
Reimplemented Function
int x() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:252
QSizePolicy sizePolicy
the default layout behavior of the widget
Definition: qwidget.h:171
QRect geometry() const
Reimplemented Function
virtual QSize maximumSize() const =0
Implemented in subclasses to return the maximum size of this item.
signed char rightLayoutItemMargin
Definition: qwidget_p.h:750
The QPoint class defines a point in the plane using integer precision.
Definition: qpoint.h:53
static const QMetaObjectPrivate * priv(const uint *data)
Policy verticalPolicy() const
Definition: qsizepolicy.h:119
bool hasHeightForWidth() const
Reimplemented Function
int height() const
Returns the height.
Definition: qsize.h:129
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:58
signed char leftLayoutItemMargin
Definition: qwidget_p.h:748
Definition: qnamespace.h:54
Qt::Alignment alignment() const
Returns the alignment of this item.
Definition: qlayoutitem.h:85
virtual QWidget * widget()
If this item is a QWidget, it is returned as a QWidget; otherwise 0 is returned.
virtual int heightForWidth(int) const
Returns the preferred height for this layout item, given the width w.
The QSize class defines the size of a two-dimensional object using integer point precision.
Definition: qsize.h:53
QWidget * wid
Definition: qlayoutitem.h:141
short q_hfwCacheSize
Definition: qlayoutitem.h:170
static QSize fromLayoutItemSize(QWidgetPrivate *priv, const QSize &size)
Definition: qlayoutitem.cpp:61
Qt::Alignment align
Definition: qlayoutitem.h:90
QSize q_cachedSizeHint
Definition: qlayoutitem.h:166
QSize maximumSize() const
Reimplemented Function
QSize q_cachedHfws[HfwCacheMaxSize]
Definition: qlayoutitem.h:168
QLayout * layout()
Reimplemented Function
static const int QLAYOUTSIZE_MAX
Definition: qlayoutitem.h:56
void updateCacheIfNecessary() const
ControlType controlType() const
Definition: qlayout.cpp:1670
void changeSize(int w, int h, QSizePolicy::Policy hData=QSizePolicy::Minimum, QSizePolicy::Policy vData=QSizePolicy::Minimum)
Changes this spacer item to have preferred width w, preferred height h, horizontal size policy hPolic...
QSize minimumSize() const
Reimplemented Function
QSize q_cachedMinimumSize
Definition: qlayoutitem.h:165