Branch data Line data Source code
1 : : #include "FlowLayout.h"
2 : : #include <QWidget>
3 : :
4 : 66 : FlowLayout::FlowLayout(QWidget *parent, int margin, int hSpacing, int vSpacing)
5 : 66 : : QLayout(parent), m_hSpace(hSpacing), m_vSpace(vSpacing)
6 : : {
7 [ + - ]: 66 : setContentsMargins(margin, margin, margin, margin);
8 : 66 : }
9 : :
10 : 0 : FlowLayout::FlowLayout(int margin, int hSpacing, int vSpacing)
11 : 0 : : m_hSpace(hSpacing), m_vSpace(vSpacing)
12 : : {
13 [ # # ]: 0 : setContentsMargins(margin, margin, margin, margin);
14 : 0 : }
15 : :
16 : 36 : FlowLayout::~FlowLayout()
17 : : {
18 : : QLayoutItem *item;
19 [ + + ]: 69 : while ((item = takeAt(0)))
20 [ + - ]: 51 : delete item;
21 : 36 : }
22 : :
23 : 225 : void FlowLayout::addItem(QLayoutItem *item)
24 : : {
25 : 225 : itemList.append(item);
26 : 225 : }
27 : :
28 : 160 : int FlowLayout::horizontalSpacing() const
29 : : {
30 [ + - ]: 160 : if (m_hSpace >= 0) {
31 : 160 : return m_hSpace;
32 : : } else {
33 : 0 : return smartSpacing(QStyle::PM_LayoutHorizontalSpacing);
34 : : }
35 : : }
36 : :
37 : 160 : int FlowLayout::verticalSpacing() const
38 : : {
39 [ + - ]: 160 : if (m_vSpace >= 0) {
40 : 160 : return m_vSpace;
41 : : } else {
42 : 0 : return smartSpacing(QStyle::PM_LayoutVerticalSpacing);
43 : : }
44 : : }
45 : :
46 : 62 : int FlowLayout::count() const
47 : : {
48 : 62 : return itemList.size();
49 : : }
50 : :
51 : 389 : QLayoutItem *FlowLayout::itemAt(int index) const
52 : : {
53 : 389 : return itemList.value(index);
54 : : }
55 : :
56 : 147 : QLayoutItem *FlowLayout::takeAt(int index)
57 : : {
58 [ + - + + : 147 : if (index >= 0 && index < itemList.size())
+ + ]
59 : 129 : return itemList.takeAt(index);
60 : 18 : return nullptr;
61 : : }
62 : :
63 : 34 : Qt::Orientations FlowLayout::expandingDirections() const
64 : : {
65 : 34 : return { };
66 : : }
67 : :
68 : 79 : bool FlowLayout::hasHeightForWidth() const
69 : : {
70 : 79 : return true;
71 : : }
72 : :
73 : 52 : int FlowLayout::heightForWidth(int width) const
74 : : {
75 [ + - ]: 52 : int height = doLayout(QRect(0, 0, width, 0), true);
76 : 52 : return height;
77 : : }
78 : :
79 : 12 : void FlowLayout::setGeometry(const QRect &rect)
80 : : {
81 : 12 : QLayout::setGeometry(rect);
82 : 12 : doLayout(rect, false);
83 : 12 : }
84 : :
85 : 15 : QSize FlowLayout::sizeHint() const
86 : : {
87 : 15 : return minimumSize();
88 : : }
89 : :
90 : 30 : QSize FlowLayout::minimumSize() const
91 : : {
92 : 30 : QSize size;
93 : : #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
94 [ + + ]: 110 : for (const QLayoutItem *item : std::as_const(itemList))
95 : : #else
96 : : for (const QLayoutItem *item : qAsConst(itemList))
97 : : #endif
98 [ + - ]: 80 : size = size.expandedTo(item->minimumSize());
99 : :
100 : : int left, top, right, bottom;
101 [ + - ]: 30 : getContentsMargins(&left, &top, &right, &bottom);
102 : 30 : size += QSize(left + right, top + bottom);
103 : 30 : return size;
104 : : }
105 : :
106 : 64 : int FlowLayout::doLayout(const QRect &rect, bool testOnly) const
107 : : {
108 : : int left, top, right, bottom;
109 [ + - ]: 64 : getContentsMargins(&left, &top, &right, &bottom);
110 : 64 : QRect effectiveRect = rect.adjusted(+left, +top, -right, -bottom);
111 : 64 : int x = effectiveRect.x();
112 : 64 : int y = effectiveRect.y();
113 : 64 : int lineHeight = 0;
114 : :
115 : : #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
116 [ + + ]: 224 : for (QLayoutItem *item : std::as_const(itemList)) {
117 : : #else
118 : : for (QLayoutItem *item : qAsConst(itemList)) {
119 : : #endif
120 [ + - ]: 160 : const QWidget *wid = item->widget();
121 [ + - ]: 160 : int spaceX = horizontalSpacing();
122 [ - + ]: 160 : if (spaceX == -1)
123 [ # # # # ]: 0 : spaceX = wid->style()->layoutSpacing(
124 : : QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Horizontal);
125 [ + - ]: 160 : int spaceY = verticalSpacing();
126 [ - + ]: 160 : if (spaceY == -1)
127 [ # # # # ]: 0 : spaceY = wid->style()->layoutSpacing(
128 : : QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Vertical);
129 : :
130 [ + - ]: 160 : int nextX = x + item->sizeHint().width() + spaceX;
131 [ + + + + : 160 : if (nextX - spaceX > effectiveRect.right() && lineHeight > 0) {
+ + ]
132 : 64 : x = effectiveRect.x();
133 : 64 : y = y + lineHeight + spaceY;
134 [ + - ]: 64 : nextX = x + item->sizeHint().width() + spaceX;
135 : 64 : lineHeight = 0;
136 : : }
137 : :
138 [ + + ]: 160 : if (!testOnly) {
139 [ + - ]: 36 : QRect itemRect(QPoint(x, y), item->sizeHint());
140 : : // If the item has Expanding horizontal policy, stretch it to the right edge
141 [ + - + - : 36 : if (item->widget() && item->widget()->sizePolicy().horizontalPolicy() & QSizePolicy::ExpandFlag) {
+ - + - +
+ + + ]
142 : : // Find next item to see if we are the last in row. For simplicity, just stretch
143 : : // to effectiveRect.right() if there are no other items after us that need space.
144 : : // In SearchPanel, the QLineEdit is followed by the popover button.
145 : : // We'll let it stretch to the right edge MINUS the size of the remaining items.
146 : : // But FlowLayout isn't naturally great at this. Let's just do a simple greedy stretch
147 : : // if there's available space and we are marked Expanding.
148 : :
149 : 12 : int remainingWidth = effectiveRect.right() - x;
150 : : // Calculate space needed for remaining items
151 : 12 : int neededForRest = 0;
152 : 12 : bool foundSelf = false;
153 : : #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
154 [ + + ]: 48 : for (QLayoutItem *restItem : std::as_const(itemList)) {
155 : : #else
156 : : for (QLayoutItem *restItem : qAsConst(itemList)) {
157 : : #endif
158 [ + + ]: 36 : if (foundSelf) {
159 [ + - ]: 12 : neededForRest += restItem->sizeHint().width() + spaceX;
160 : : }
161 [ + + ]: 36 : if (restItem == item) foundSelf = true;
162 : : }
163 : :
164 [ + + ]: 12 : if (remainingWidth - neededForRest > itemRect.width()) {
165 : 5 : itemRect.setWidth(remainingWidth - neededForRest);
166 : : }
167 : : }
168 [ + - ]: 36 : item->setGeometry(itemRect);
169 : : }
170 : :
171 [ + + + - : 160 : x += (!testOnly) ? item->geometry().width() + spaceX : item->sizeHint().width() + spaceX;
+ - ]
172 [ + + + - : 160 : lineHeight = qMax(lineHeight, (!testOnly) ? item->geometry().height() : item->sizeHint().height());
+ - ]
173 : : }
174 : 128 : return y + lineHeight - rect.y() + bottom;
175 : : }
176 : :
177 : 0 : int FlowLayout::smartSpacing(QStyle::PixelMetric pm) const
178 : : {
179 : 0 : QObject *parent = this->parent();
180 [ # # ]: 0 : if (!parent) {
181 : 0 : return -1;
182 [ # # ]: 0 : } else if (parent->isWidgetType()) {
183 : 0 : QWidget *pw = static_cast<QWidget *>(parent);
184 : 0 : return pw->style()->pixelMetric(pm, nullptr, pw);
185 : : } else {
186 : 0 : return static_cast<QLayout *>(parent)->spacing();
187 : : }
188 : : }
|