source: trunk/src/gui/kernel/qlayoutitem.cpp@ 624

Last change on this file since 624 was 561, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.1 sources.

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