PageRenderTime 98ms CodeModel.GetById 8ms RepoModel.GetById 1ms app.codeStats 0ms

/src/qt/qtbase/src/widgets/kernel/qlayoutitem.cpp

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