2 * Bittorrent Client using Qt and libtorrent.
3 * Copyright (C) 2023 Vladimir Golovnev <glassez@yandex.ru>
4 * Copyright (C) 2016 The Qt Company Ltd.
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * In addition, as a special exception, the copyright holders give permission to
21 * link this program with the OpenSSL project's "OpenSSL" library (or with
22 * modified versions of it that use the same license as the "OpenSSL" library),
23 * and distribute the linked executables. You must obey the GNU General Public
24 * License in all respects for all of the code used other than "OpenSSL". If you
25 * modify file(s), you may extend this exception to your version of the file(s),
26 * but you are not obligated to do so. If you do not wish to do so, delete this
27 * exception statement from your version.
30 #include "flowlayout.h"
35 #include "base/global.h"
37 FlowLayout::FlowLayout(QWidget
*parent
, const int margin
, const int hSpacing
, const int vSpacing
)
42 setContentsMargins(margin
, margin
, margin
, margin
);
45 FlowLayout::FlowLayout(const int margin
, const int hSpacing
, const int vSpacing
)
49 setContentsMargins(margin
, margin
, margin
, margin
);
52 FlowLayout::~FlowLayout()
55 while ((item
= takeAt(0)))
59 void FlowLayout::addItem(QLayoutItem
*item
)
61 m_itemList
.append(item
);
64 int FlowLayout::horizontalSpacing() const
69 return smartSpacing(QStyle::PM_LayoutHorizontalSpacing
);
72 int FlowLayout::verticalSpacing() const
77 return smartSpacing(QStyle::PM_LayoutVerticalSpacing
);
80 int FlowLayout::count() const
82 return m_itemList
.size();
85 QLayoutItem
*FlowLayout::itemAt(const int index
) const
87 return m_itemList
.value(index
);
90 QLayoutItem
*FlowLayout::takeAt(const int index
)
92 if ((index
>= 0) && (index
< m_itemList
.size()))
93 return m_itemList
.takeAt(index
);
98 Qt::Orientations
FlowLayout::expandingDirections() const
103 bool FlowLayout::hasHeightForWidth() const
108 int FlowLayout::heightForWidth(const int width
) const
110 const int height
= doLayout(QRect(0, 0, width
, 0), true);
114 void FlowLayout::setGeometry(const QRect
&rect
)
116 QLayout::setGeometry(rect
);
117 doLayout(rect
, false);
120 QSize
FlowLayout::sizeHint() const
122 return minimumSize();
125 QSize
FlowLayout::minimumSize() const
128 for (const QLayoutItem
*item
: asConst(m_itemList
))
129 size
= size
.expandedTo(item
->minimumSize());
131 const QMargins margins
= contentsMargins();
132 size
+= QSize(margins
.left() + margins
.right(), margins
.top() + margins
.bottom());
136 int FlowLayout::doLayout(const QRect
&rect
, const bool testOnly
) const
138 int left
, top
, right
, bottom
;
139 getContentsMargins(&left
, &top
, &right
, &bottom
);
141 const QRect effectiveRect
= rect
.adjusted(+left
, +top
, -right
, -bottom
);
142 int x
= effectiveRect
.x();
143 int y
= effectiveRect
.y();
146 QHash
<QLayoutItem
*, QPoint
> lineItems
;
147 for (QLayoutItem
*item
: asConst(m_itemList
))
149 const QWidget
*wid
= item
->widget();
151 int spaceX
= horizontalSpacing();
154 spaceX
= wid
->style()->layoutSpacing(
155 QSizePolicy::PushButton
, QSizePolicy::PushButton
, Qt::Horizontal
);
158 int spaceY
= verticalSpacing();
161 spaceY
= wid
->style()->layoutSpacing(
162 QSizePolicy::PushButton
, QSizePolicy::PushButton
, Qt::Vertical
);
165 int nextX
= x
+ item
->sizeHint().width() + spaceX
;
166 if (((nextX
- spaceX
) > effectiveRect
.right()) && (lineHeight
> 0))
170 applyItemsGeometry(lineItems
, lineHeight
);
174 x
= effectiveRect
.x();
175 y
= y
+ lineHeight
+ spaceY
;
176 nextX
= x
+ item
->sizeHint().width() + spaceX
;
181 lineItems
[item
] = QPoint(x
, y
);
184 lineHeight
= std::max(lineHeight
, item
->sizeHint().height());
188 applyItemsGeometry(lineItems
, lineHeight
);
190 return y
+ lineHeight
- rect
.y() + bottom
;
193 int FlowLayout::smartSpacing(const QStyle::PixelMetric pm
) const
195 QObject
*parent
= this->parent();
199 if (parent
->isWidgetType())
201 auto *pw
= static_cast<QWidget
*>(parent
);
202 return pw
->style()->pixelMetric(pm
, nullptr, pw
);
205 return static_cast<QLayout
*>(parent
)->spacing();
208 void FlowLayout::applyItemsGeometry(const QHash
<QLayoutItem
*, QPoint
> &items
, const int lineHeight
) const
210 for (auto it
= items
.cbegin(); it
!= items
.cend(); ++it
)
212 QLayoutItem
*item
= it
.key();
213 QPoint point
= it
.value();
215 const auto alignment
= item
->alignment();
216 const int vSpace
= lineHeight
- item
->sizeHint().height();
217 if (alignment
& Qt::AlignVCenter
)
218 point
.ry() += vSpace
/ 2;
219 else if (alignment
& Qt::AlignBottom
)
220 point
.ry() += vSpace
;
221 item
->setGeometry(QRect(point
, item
->sizeHint()));