WebUI: Use Map instead of Mootools Hash in Torrents table
[qBittorrent.git] / src / gui / flowlayout.cpp
blob29eaceed52809a47f8ef6a278115209912e288f4
1 /*
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"
32 #include <QHash>
33 #include <QWidget>
35 #include "base/global.h"
37 FlowLayout::FlowLayout(QWidget *parent, const int margin, const int hSpacing, const int vSpacing)
38 : QLayout(parent)
39 , m_hSpace {hSpacing}
40 , m_vSpace {vSpacing}
42 setContentsMargins(margin, margin, margin, margin);
45 FlowLayout::FlowLayout(const int margin, const int hSpacing, const int vSpacing)
46 : m_hSpace {hSpacing}
47 , m_vSpace {vSpacing}
49 setContentsMargins(margin, margin, margin, margin);
52 FlowLayout::~FlowLayout()
54 QLayoutItem *item;
55 while ((item = takeAt(0)))
56 delete item;
59 void FlowLayout::addItem(QLayoutItem *item)
61 m_itemList.append(item);
64 int FlowLayout::horizontalSpacing() const
66 if (m_hSpace >= 0)
67 return m_hSpace;
69 return smartSpacing(QStyle::PM_LayoutHorizontalSpacing);
72 int FlowLayout::verticalSpacing() const
74 if (m_vSpace >= 0)
75 return m_vSpace;
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);
95 return nullptr;
98 Qt::Orientations FlowLayout::expandingDirections() const
100 return {};
103 bool FlowLayout::hasHeightForWidth() const
105 return true;
108 int FlowLayout::heightForWidth(const int width) const
110 const int height = doLayout(QRect(0, 0, width, 0), true);
111 return height;
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
127 QSize size;
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());
133 return size;
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();
144 int lineHeight = 0;
146 QHash<QLayoutItem *, QPoint> lineItems;
147 for (QLayoutItem *item : asConst(m_itemList))
149 const QWidget *wid = item->widget();
151 int spaceX = horizontalSpacing();
152 if (spaceX == -1)
154 spaceX = wid->style()->layoutSpacing(
155 QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Horizontal);
158 int spaceY = verticalSpacing();
159 if (spaceY == -1)
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))
168 if (!testOnly)
170 applyItemsGeometry(lineItems, lineHeight);
171 lineItems.clear();
174 x = effectiveRect.x();
175 y = y + lineHeight + spaceY;
176 nextX = x + item->sizeHint().width() + spaceX;
177 lineHeight = 0;
180 if (!testOnly)
181 lineItems[item] = QPoint(x, y);
183 x = nextX;
184 lineHeight = std::max(lineHeight, item->sizeHint().height());
187 if (!testOnly)
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();
196 if (!parent)
197 return -1;
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()));