flowlayout.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. /****************************************************************************
  2. **
  3. ** Copyright (C) 2016 The Qt Company Ltd.
  4. ** Contact: https://www.qt.io/licensing/
  5. **
  6. ** This file is part of the examples of the Qt Toolkit.
  7. **
  8. ** $QT_BEGIN_LICENSE:BSD$
  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 The Qt Company. For licensing terms
  14. ** and conditions see https://www.qt.io/terms-conditions. For further
  15. ** information use the contact form at https://www.qt.io/contact-us.
  16. **
  17. ** BSD License Usage
  18. ** Alternatively, you may use this file under the terms of the BSD license
  19. ** as follows:
  20. **
  21. ** "Redistribution and use in source and binary forms, with or without
  22. ** modification, are permitted provided that the following conditions are
  23. ** met:
  24. ** * Redistributions of source code must retain the above copyright
  25. ** notice, this list of conditions and the following disclaimer.
  26. ** * Redistributions in binary form must reproduce the above copyright
  27. ** notice, this list of conditions and the following disclaimer in
  28. ** the documentation and/or other materials provided with the
  29. ** distribution.
  30. ** * Neither the name of The Qt Company Ltd nor the names of its
  31. ** contributors may be used to endorse or promote products derived
  32. ** from this software without specific prior written permission.
  33. **
  34. **
  35. ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  36. ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  37. ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  38. ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  39. ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40. ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41. ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  42. ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  43. ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  44. ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  45. ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
  46. **
  47. ** $QT_END_LICENSE$
  48. **
  49. ****************************************************************************/
  50. #include <QtWidgets>
  51. #include "flowlayout.h"
  52. //! [1]
  53. FlowLayout::FlowLayout(QWidget *parent, int margin, int hSpacing, int vSpacing)
  54. : QLayout(parent), m_hSpace(hSpacing), m_vSpace(vSpacing)
  55. {
  56. setContentsMargins(margin, margin, margin, margin);
  57. }
  58. FlowLayout::FlowLayout(int margin, int hSpacing, int vSpacing)
  59. : m_hSpace(hSpacing), m_vSpace(vSpacing)
  60. {
  61. setContentsMargins(margin, margin, margin, margin);
  62. }
  63. //! [1]
  64. //! [2]
  65. FlowLayout::~FlowLayout()
  66. {
  67. QLayoutItem *item;
  68. while ((item = takeAt(0)))
  69. delete item;
  70. }
  71. //! [2]
  72. //! [3]
  73. void FlowLayout::addItem(QLayoutItem *item)
  74. {
  75. itemList.append(item);
  76. }
  77. //! [3]
  78. //! [4]
  79. int FlowLayout::horizontalSpacing() const
  80. {
  81. if (m_hSpace >= 0) {
  82. return m_hSpace;
  83. } else {
  84. return smartSpacing(QStyle::PM_LayoutHorizontalSpacing);
  85. }
  86. }
  87. int FlowLayout::verticalSpacing() const
  88. {
  89. if (m_vSpace >= 0) {
  90. return m_vSpace;
  91. } else {
  92. return smartSpacing(QStyle::PM_LayoutVerticalSpacing);
  93. }
  94. }
  95. //! [4]
  96. //! [5]
  97. int FlowLayout::count() const
  98. {
  99. return itemList.size();
  100. }
  101. QLayoutItem *FlowLayout::itemAt(int index) const
  102. {
  103. return itemList.value(index);
  104. }
  105. QLayoutItem *FlowLayout::takeAt(int index)
  106. {
  107. if (index >= 0 && index < itemList.size())
  108. return itemList.takeAt(index);
  109. else
  110. return 0;
  111. }
  112. //! [5]
  113. //! [6]
  114. Qt::Orientations FlowLayout::expandingDirections() const
  115. {
  116. return 0;
  117. }
  118. //! [6]
  119. //! [7]
  120. bool FlowLayout::hasHeightForWidth() const
  121. {
  122. return true;
  123. }
  124. int FlowLayout::heightForWidth(int width) const
  125. {
  126. int height = doLayout(QRect(0, 0, width, 0), true);
  127. return height;
  128. }
  129. //! [7]
  130. //! [8]
  131. void FlowLayout::setGeometry(const QRect &rect)
  132. {
  133. QLayout::setGeometry(rect);
  134. doLayout(rect, false);
  135. }
  136. QSize FlowLayout::sizeHint() const
  137. {
  138. return minimumSize();
  139. }
  140. QSize FlowLayout::minimumSize() const
  141. {
  142. QSize size;
  143. QLayoutItem *item;
  144. foreach (item, itemList)
  145. size = size.expandedTo(item->minimumSize());
  146. size += QSize(2*margin(), 2*margin());
  147. return size;
  148. }
  149. //! [8]
  150. /**
  151. * @brief 布局item
  152. *
  153. * @param rect
  154. * @param testOnly
  155. * @return int
  156. */
  157. int FlowLayout::doLayout(const QRect &rect, bool testOnly) const
  158. {
  159. int left, top, right, bottom;
  160. /* 获取布局的margins */
  161. getContentsMargins(&left, &top, &right, &bottom);
  162. QRect effectiveRect = rect.adjusted(+left, +top, -right, -bottom);
  163. int x = effectiveRect.x();
  164. int y = effectiveRect.y();
  165. int lineHeight = 0;
  166. //! [9]
  167. //! [10]
  168. /* 挨个排列组件,如果被隐藏了,那么也去掉前面的spacing距离 */
  169. QLayoutItem *item;
  170. foreach (item, itemList)
  171. {
  172. QWidget *wid = item->widget();
  173. int spaceX = horizontalSpacing();
  174. if (spaceX == -1)
  175. spaceX = wid->style()->layoutSpacing(
  176. QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Horizontal);
  177. int spaceY = verticalSpacing();
  178. if (spaceY == -1)
  179. spaceY = wid->style()->layoutSpacing(
  180. QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Vertical);
  181. //! [10]
  182. //! [11]
  183. int nextX = x + item->sizeHint().width() + spaceX;
  184. if (nextX - spaceX > effectiveRect.right() && lineHeight > 0) {
  185. x = effectiveRect.x();
  186. y = y + lineHeight + spaceY;
  187. nextX = x + item->sizeHint().width() + spaceX;
  188. lineHeight = 0;
  189. }
  190. /* 不是test就设置位置 */
  191. if (!testOnly)
  192. item->setGeometry(QRect(QPoint(x, y), item->sizeHint()));
  193. x = nextX;
  194. lineHeight = qMax(lineHeight, item->sizeHint().height());
  195. }
  196. return y + lineHeight - rect.y() + bottom;
  197. }
  198. //! [11]
  199. //! [12]
  200. int FlowLayout::smartSpacing(QStyle::PixelMetric pm) const
  201. {
  202. QObject *parent = this->parent();
  203. if (!parent) {
  204. return -1;
  205. } else if (parent->isWidgetType()) {
  206. QWidget *pw = static_cast<QWidget *>(parent);
  207. return pw->style()->pixelMetric(pm, 0, pw);
  208. } else {
  209. return static_cast<QLayout *>(parent)->spacing();
  210. }
  211. }
  212. //! [12]