VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/extensions/QIFlowLayout.cpp

Last change on this file was 98103, checked in by vboxsync, 16 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.9 KB
Line 
1/* $Id: QIFlowLayout.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - Qt extensions: QIFlowLayout class implementation.
4 */
5
6/*
7 * Copyright (C) 2017-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28/* Qt includes: */
29#include <QWidget>
30
31/* GUI includes: */
32#include "QIFlowLayout.h"
33
34
35QIFlowLayout::QIFlowLayout(QWidget *pParent, int iMargin /* = -1 */, int iSpacingH /* = -1 */, int iSpacingV /* = -1 */)
36 : QLayout(pParent)
37 , m_iSpacingH(iSpacingH)
38 , m_iSpacingV(iSpacingV)
39{
40 setContentsMargins(iMargin, iMargin, iMargin, iMargin);
41}
42
43QIFlowLayout::QIFlowLayout(int iMargin, int iSpacingH, int iSpacingV)
44 : m_iSpacingH(iSpacingH)
45 , m_iSpacingV(iSpacingV)
46{
47 setContentsMargins(iMargin, iMargin, iMargin, iMargin);
48}
49
50QIFlowLayout::~QIFlowLayout()
51{
52 /* Delete all the children: */
53 QLayoutItem *pItem = 0;
54 while ((pItem = takeAt(0)))
55 delete pItem;
56}
57
58int QIFlowLayout::count() const
59{
60 return m_items.size();
61}
62
63void QIFlowLayout::addItem(QLayoutItem *pItem)
64{
65 m_items.append(pItem);
66}
67
68QLayoutItem *QIFlowLayout::itemAt(int iIndex) const
69{
70 return m_items.value(iIndex);
71}
72
73QLayoutItem *QIFlowLayout::takeAt(int iIndex)
74{
75 return iIndex >= 0 && iIndex < m_items.size() ? m_items.takeAt(iIndex) : 0;
76}
77
78Qt::Orientations QIFlowLayout::expandingDirections() const
79{
80 return Qt::Horizontal;
81}
82
83bool QIFlowLayout::hasHeightForWidth() const
84{
85 return true;
86}
87
88int QIFlowLayout::heightForWidth(int iWidth) const
89{
90 return relayout(QRect(0, 0, iWidth, 0), false);
91}
92
93QSize QIFlowLayout::minimumSize() const
94{
95 /* Walk through all the children: */
96 QSize size;
97 foreach (QLayoutItem *pItem, m_items)
98 size = size.expandedTo(pItem->minimumSize());
99
100 /* Do not forget the margins: */
101 int iLeft, iTop, iRight, iBottom;
102 getContentsMargins(&iLeft, &iTop, &iRight, &iBottom);
103 size += QSize(iLeft + iRight, iTop + iBottom);
104
105 /* Return resulting size: */
106 return size;
107}
108
109QSize QIFlowLayout::sizeHint() const
110{
111 return minimumSize();
112}
113
114void QIFlowLayout::setGeometry(const QRect &rect)
115{
116 QLayout::setGeometry(rect);
117 relayout(rect, true);
118}
119
120int QIFlowLayout::relayout(const QRect &rect, bool fDoLayout) const
121{
122 /* Acquire contents margins: */
123 int iLeft, iTop, iRight, iBottom;
124 getContentsMargins(&iLeft, &iTop, &iRight, &iBottom);
125
126 /* Calculate available contents rectangle: */
127 const QRect contentsRect = rect.adjusted(iLeft, iTop, -iRight, -iBottom);
128
129 /* Acquire horizontal/vertical spacings: */
130 const int iSpaceX = horizontalSpacing();
131 //if (iSpaceX == -1)
132 // iSpaceX = pWidged->style()->layoutSpacing(
133 // QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Horizontal);
134 const int iSpaceY = verticalSpacing();
135 //if (iSpaceY == -1)
136 // iSpaceY = pWidged->style()->layoutSpacing(
137 // QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Vertical);
138
139 /* Split items to rows: */
140 int iLastX = contentsRect.x();
141 LayoutDataTable rows;
142 LayoutDataList row;
143 foreach (QLayoutItem *pItem, m_items)
144 {
145 /* Skip items of zero width: */
146 if (pItem->sizeHint().width() == 0)
147 continue;
148
149 /* Get item policy and width: */
150 const ExpandPolicy enmPolicy = pItem->expandingDirections() & Qt::Horizontal ? ExpandPolicy_Dynamic : ExpandPolicy_Fixed;
151 const int iWidth = pItem->sizeHint().width();
152
153 /* Check whether it's possible to insert this item to current row: */
154 int iNextX = iLastX + iWidth + iSpaceX;
155 if (iNextX - iSpaceX <= contentsRect.right())
156 {
157 /* Append item to current row: */
158 row << LayoutData(pItem, enmPolicy, iWidth);
159 }
160 else
161 {
162 /* Flush the row to rows: */
163 rows << row;
164 row.clear();
165 /* Move the caret to the next row: */
166 iLastX = contentsRect.x();
167 iNextX = iLastX + iWidth + iSpaceX;
168 /* Append item to new row: */
169 row << LayoutData(pItem, enmPolicy, iWidth);
170 }
171
172 /* Remember the last caret position: */
173 iLastX = iNextX;
174 }
175 /* Flush the row to rows: */
176 rows << row;
177 row.clear();
178
179 /* Iterate through all the rows: */
180 for (int i = 0; i < rows.count(); ++i)
181 {
182 /* Acquire current row: */
183 LayoutDataList &row = rows[i];
184 /* Width expand delta is equal to total-width minus all spacing widths ... */
185 int iExpandingWidth = contentsRect.width() - (row.size() - 1) * iSpaceX;
186
187 /* Iterate through whole the row: */
188 int cExpandingItems = 0;
189 for (int j = 0; j < row.count(); ++j)
190 {
191 /* Acquire current record: */
192 const LayoutData &record = row.at(j);
193 /* Calcualte the amount of expandable items: */
194 if (record.policy == ExpandPolicy_Dynamic)
195 ++cExpandingItems;
196 /* ... minus all item widths ... */
197 iExpandingWidth -= record.width;
198 }
199
200 /* If there are expandable items: */
201 if (cExpandingItems > 0)
202 {
203 /* ... devided by the amount of ExpandPolicy_Dynamic items: */
204 iExpandingWidth /= cExpandingItems;
205 /* Expand all the expandable item widths with delta: */
206 for (int j = 0; j < row.count(); ++j)
207 if (row.at(j).policy == ExpandPolicy_Dynamic)
208 row[j].width += iExpandingWidth;
209 }
210 }
211
212 /* Iterate through all the items: */
213 int iX = contentsRect.x();
214 int iY = contentsRect.y();
215 for (int i = 0; i < rows.count(); ++i)
216 {
217 /* Acquire current row: */
218 const LayoutDataList &row = rows.at(i);
219 int iRowHeight = 0;
220 for (int j = 0; j < row.count(); ++j)
221 {
222 /* Acquire current record: */
223 const LayoutData &record = row.at(j);
224 /* Acquire the desired width/height: */
225 const int iDesiredWidth = record.width;
226 const int iDesiredHeight = record.item->sizeHint().height();
227
228 /* Do the layout if requested: */
229 if (fDoLayout)
230 record.item->setGeometry(QRect(QPoint(iX, iY), QSize(iDesiredWidth, iDesiredHeight)));
231
232 /* Acquire the next item location: */
233 iX = iX + iDesiredWidth + iSpaceX;
234 /* Remember the maximum row height: */
235 iRowHeight = qMax(iRowHeight, iDesiredHeight);
236 }
237 /* Move the caret to the next row: */
238 iX = contentsRect.x();
239 iY = iY + iRowHeight + iSpaceY;
240 }
241
242 /* Return effective layout height: */
243 return iY - iSpaceY - rect.y() + iBottom;
244}
245
246int QIFlowLayout::smartSpacing(QStyle::PixelMetric pm) const
247{
248 QObject *pParent = this->parent();
249 if (!pParent)
250 {
251 return -1;
252 }
253 else if (pParent->isWidgetType())
254 {
255 QWidget *pParentWidget = static_cast<QWidget*>(pParent);
256 return pParentWidget->style()->pixelMetric(pm, 0, pParentWidget);
257 }
258 else
259 {
260 return static_cast<QLayout*>(pParent)->spacing();
261 }
262}
263
264int QIFlowLayout::horizontalSpacing() const
265{
266 return m_iSpacingH >= 0 ? m_iSpacingH : smartSpacing(QStyle::PM_LayoutHorizontalSpacing);
267}
268
269int QIFlowLayout::verticalSpacing() const
270{
271 return m_iSpacingV >= 0 ? m_iSpacingV : smartSpacing(QStyle::PM_LayoutVerticalSpacing);
272}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use