]> cloud.milkyroute.net Git - dolphin.git/blob - src/search/barsecondrowflowlayout.cpp
Rewrite search integration
[dolphin.git] / src / search / barsecondrowflowlayout.cpp
1 /*
2 SPDX-FileCopyrightText: 2025 Felix Ernst <felixernst@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5 */
6
7 #include "barsecondrowflowlayout.h"
8
9 #include <QWidget>
10
11 #include <vector>
12
13 using namespace Search;
14
15 namespace
16 {
17 constexpr int searchLocationButtonsCount = 2;
18 }
19
20 BarSecondRowFlowLayout::BarSecondRowFlowLayout(QWidget *parent)
21 : QLayout{parent}
22 {
23 setContentsMargins(0, 0, 0, 0);
24 }
25
26 BarSecondRowFlowLayout::~BarSecondRowFlowLayout()
27 {
28 QLayoutItem *item;
29 while ((item = takeAt(0)))
30 delete item;
31 }
32
33 void BarSecondRowFlowLayout::addItem(QLayoutItem *item)
34 {
35 itemList.append(item);
36 }
37
38 Qt::Orientations BarSecondRowFlowLayout::expandingDirections() const
39 {
40 return {};
41 }
42
43 bool BarSecondRowFlowLayout::hasHeightForWidth() const
44 {
45 return false;
46 }
47
48 int BarSecondRowFlowLayout::count() const
49 {
50 return itemList.size();
51 }
52
53 QLayoutItem *BarSecondRowFlowLayout::itemAt(int index) const
54 {
55 return itemList.value(index);
56 }
57
58 QSize BarSecondRowFlowLayout::sizeHint() const
59 {
60 const QRect rect = geometry();
61 QSize size;
62 for (const QLayoutItem *item : std::as_const(itemList)) {
63 size = size.expandedTo(QSize{item->geometry().right() - rect.x(), item->geometry().bottom() - rect.y()});
64 }
65 return size;
66 }
67
68 void BarSecondRowFlowLayout::setGeometry(const QRect &rect)
69 {
70 const int oldHeightHint = sizeHint().height();
71 QLayout::setGeometry(rect);
72 const bool isLeftToRight = itemAt(0)->widget()->layoutDirection() == Qt::LeftToRight;
73 int x = rect.left();
74 int y = rect.top();
75
76 /// The search location buttons are treated differently. They are meant to be in the same row and aligned the other way.
77 int totalLocationButtonWidth = 0;
78 for (int i = 0; i < searchLocationButtonsCount; i++) {
79 totalLocationButtonWidth += itemAt(i)->widget()->sizeHint().width();
80 }
81 if (totalLocationButtonWidth > rect.width()) {
82 /// There is not enough space so we will smush all the location buttons into the first row.
83 for (int i = 0; i < searchLocationButtonsCount; i++) {
84 QWidget *widget = itemAt(i)->widget();
85 const int targetWidth = qMin(widget->sizeHint().width(), rect.width() / searchLocationButtonsCount);
86 widget->setGeometry(isLeftToRight ? x : rect.right() - x - targetWidth, y, targetWidth, widget->sizeHint().height());
87 x += widget->width();
88 }
89 } else {
90 for (int i = 0; i < searchLocationButtonsCount; i++) {
91 QWidget *widget = itemAt(i)->widget();
92 QSize preferredSize = widget->sizeHint();
93 widget->setGeometry(isLeftToRight ? x : rect.right() - x - preferredSize.width(), y, preferredSize.width(), preferredSize.height());
94 x += widget->width() + spacing();
95 }
96 }
97
98 // We want to align all further widgets the other way. We do this by first filling up the row like usual and then moving all widgets of the current row by
99 // the remaining space.
100 std::vector<QWidget *> currentRowWidgets;
101 for (int i = searchLocationButtonsCount; i < count(); i++) {
102 QWidget *widget = itemAt(i)->widget();
103 const int remainingSpace = rect.right() - x + spacing();
104 if (widget->sizeHint().width() < remainingSpace) {
105 QSize preferredSize = widget->sizeHint();
106 widget->setGeometry(isLeftToRight ? x : rect.right() - x - preferredSize.width(), y, preferredSize.width(), preferredSize.height());
107 x += widget->width() + spacing();
108 currentRowWidgets.push_back(widget);
109 continue;
110 }
111
112 // There is not enough space for the next widget. We need to open up a new row.
113 // Right align all the widgets of the previous row.
114 for (QWidget *widget : std::as_const(currentRowWidgets)) {
115 widget->setGeometry(widget->geometry().translated(isLeftToRight ? remainingSpace : -remainingSpace, 0));
116 }
117 currentRowWidgets.clear();
118
119 x = 0;
120 y += itemAt(i - 1)->widget()->height() + spacing();
121
122 QSize preferredSize = widget->sizeHint();
123 const int targetWidth = qMin(preferredSize.width(), rect.width());
124 widget->setGeometry(isLeftToRight ? x : rect.right() - x - targetWidth, y, targetWidth, preferredSize.height());
125 x += widget->width() + spacing();
126 currentRowWidgets.push_back(widget);
127 }
128
129 // Right align all the widgets of the previous row.
130 int remainingSpace = rect.right() - x + spacing();
131 for (QWidget *widget : std::as_const(currentRowWidgets)) {
132 widget->setGeometry(widget->geometry().translated(isLeftToRight ? remainingSpace : -remainingSpace, 0));
133 }
134
135 if (sizeHint().height() != oldHeightHint) {
136 Q_EMIT heightHintChanged();
137 }
138 }
139
140 QSize BarSecondRowFlowLayout::minimumSize() const
141 {
142 return QSize{0, sizeHint().height()};
143 }
144
145 QLayoutItem *BarSecondRowFlowLayout::takeAt(int index)
146 {
147 if (index >= 0 && index < itemList.size())
148 return itemList.takeAt(index);
149 return nullptr;
150 }