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

Last change on this file since 347 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

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