|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the QtGui module of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
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 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
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 |
|
53 QT_BEGIN_NAMESPACE |
|
54 |
|
55 inline static QRect fromLayoutItemRect(QWidgetPrivate *priv, const QRect &rect) |
|
56 { |
|
57 return rect.adjusted(priv->leftLayoutItemMargin, priv->topLayoutItemMargin, |
|
58 -priv->rightLayoutItemMargin, -priv->bottomLayoutItemMargin); |
|
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, |
|
69 priv->rightLayoutItemMargin, priv->bottomLayoutItemMargin); |
|
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 |
|
77 /*! |
|
78 Returns a QVariant storing this QSizePolicy. |
|
79 */ |
|
80 QSizePolicy::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 */ |
|
193 void 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 */ |
|
273 void 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 */ |
|
290 QLayoutItem::~QLayoutItem() |
|
291 { |
|
292 } |
|
293 |
|
294 /*! |
|
295 Invalidates any cached information in this layout item. |
|
296 */ |
|
297 void 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 */ |
|
305 QLayout * 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 */ |
|
314 QSpacerItem * QLayoutItem::spacerItem() |
|
315 { |
|
316 return 0; |
|
317 } |
|
318 |
|
319 /*! |
|
320 \reimp |
|
321 */ |
|
322 QLayout * QLayout::layout() |
|
323 { |
|
324 return this; |
|
325 } |
|
326 |
|
327 /*! |
|
328 Returns a pointer to this object. |
|
329 */ |
|
330 QSpacerItem * 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 */ |
|
339 QWidget * QLayoutItem::widget() |
|
340 { |
|
341 return 0; |
|
342 } |
|
343 |
|
344 /*! |
|
345 Returns the widget managed by this item. |
|
346 */ |
|
347 QWidget *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 */ |
|
362 bool 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 */ |
|
372 int 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 */ |
|
396 int 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 */ |
|
409 QSizePolicy::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 */ |
|
428 void QSpacerItem::setGeometry(const QRect &r) |
|
429 { |
|
430 rect = r; |
|
431 } |
|
432 |
|
433 /*! |
|
434 \reimp |
|
435 */ |
|
436 void 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 */ |
|
496 QRect QSpacerItem::geometry() const |
|
497 { |
|
498 return rect; |
|
499 } |
|
500 |
|
501 /*! |
|
502 \reimp |
|
503 */ |
|
504 QRect 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 */ |
|
515 bool 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 */ |
|
527 int 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 */ |
|
559 Qt::Orientations QSpacerItem::expandingDirections() const |
|
560 { |
|
561 return sizeP.expandingDirections(); |
|
562 } |
|
563 |
|
564 /*! |
|
565 \reimp |
|
566 */ |
|
567 Qt::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 */ |
|
598 QSize 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 */ |
|
607 QSize 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 */ |
|
619 QSize 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 */ |
|
628 QSize 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 */ |
|
642 QSize QSpacerItem::sizeHint() const |
|
643 { |
|
644 return QSize(width, height); |
|
645 } |
|
646 |
|
647 /*! |
|
648 \reimp |
|
649 */ |
|
650 QSize 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 */ |
|
672 bool 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 */ |
|
682 bool QWidgetItem::isEmpty() const |
|
683 { |
|
684 return wid->isHidden() || wid->isWindow(); |
|
685 } |
|
686 |
|
687 /*! |
|
688 \class QWidgetItemV2 |
|
689 \internal |
|
690 */ |
|
691 |
|
692 inline bool QWidgetItemV2::useSizeCache() const |
|
693 { |
|
694 return wid->d_func()->widgetItem == this; |
|
695 } |
|
696 |
|
697 void 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 |
|
735 QWidgetItemV2::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 |
|
749 QWidgetItemV2::~QWidgetItemV2() |
|
750 { |
|
751 if (wid) { |
|
752 QWidgetPrivate *wd = wid->d_func(); |
|
753 if (wd->widgetItem == this) |
|
754 wd->widgetItem = 0; |
|
755 } |
|
756 } |
|
757 |
|
758 QSize 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 |
|
771 QSize 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 |
|
784 QSize 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 |
|
812 int 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 |
|
836 QT_END_NAMESPACE |