Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_size_group_p.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2013 Juan Palacios <jpalaciosdev@gmail.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6
7#include "kis_size_group_p.h"
8
9#include <QEvent>
10#include <QTimer>
11#include <QWidget>
12#include <QLayout>
13#include <QGridLayout>
14#include <QFormLayout>
15
17 : QObject()
18 , q(q_ptr)
19 , m_mode(mode)
20 , m_ignoreHidden(ignoreHidden)
21 , m_updateTimer(new QTimer(q))
22 , m_sizeHint(0, 0)
23{
24 Q_ASSERT(q_ptr);
25
26 m_updateTimer->setSingleShot(true);
27 m_updateTimer->setInterval(0);
28 QObject::connect(m_updateTimer, SIGNAL(timeout()), this, SLOT(updateSize()));
29}
30
31void KisSizeGroupPrivate::addWidget(QWidget *widget)
32{
33 Q_ASSERT(widget);
34
35 QWidget *parent = widget->parentWidget();
36 if (parent) {
37 QLayout *layout = parent->layout();
38 if (layout) {
39 // Search for the widget index and the QLayoutItem inside of the layout
40 QLayoutItem *layoutItem = 0;
41 int layoutWidgetIndex = 0;
42 for(int i = 0; i < layout->count(); ++i) {
43 layoutItem = layout->itemAt(layoutWidgetIndex);
44 if (layoutItem->widget() == widget) break;
45 ++layoutWidgetIndex;
46 }
47
48 // We need to replace the layoutItem with an instance of GroupItem
49 GroupItem *groupItem = dynamic_cast<GroupItem*>(layoutItem);
50 if (groupItem) {
51 // This widget is already inside of a group
52 // One widget inside multiple groups is not supported
53 Q_ASSERT(groupItem->getGroup() == this);
54 } else {
55 // LayoutItem is not an instance of WidgetItem
56 // We need to create a new one
57
58 groupItem = new GroupItem(widget);
59 groupItem->setGroup(this);
60
61 // Now we need to replace the layoutItem with the groupItem.
62 // This step depends on the actual layout specialization.
63
64 // Widget within a QFormLayout
65 QFormLayout* formLayout = qobject_cast<QFormLayout*>(layout);
66 if (formLayout) {
67 int row;
68 QFormLayout::ItemRole role;
69 formLayout->getItemPosition(layoutWidgetIndex, &row, &role);
70 formLayout->removeItem(layoutItem);
71 delete layoutItem;
72 formLayout->setItem(row, role, groupItem);
73 m_groupItems.append(groupItem);
74
75 return;
76 }
77
78 // Widget within a QGridLayout
79 QGridLayout *gridLayout = qobject_cast<QGridLayout*>(layout);
80 if (gridLayout) {
81 int row, column, rowspan, columnspan;
82 gridLayout->getItemPosition(layoutWidgetIndex, &row, &column, &rowspan, &columnspan);
83 gridLayout->removeItem(layoutItem);
84 delete layoutItem;
85 gridLayout->addItem(groupItem, row, column, rowspan, columnspan);
86 m_groupItems.append(groupItem);
87
88 return;
89 }
90
91 // Widget within a QBoxLayout
92 QBoxLayout *boxLayout = qobject_cast<QBoxLayout*>(layout);
93 if (boxLayout) {
94 boxLayout->removeItem(layoutItem);
95 delete layoutItem;
96 boxLayout->insertItem(layoutWidgetIndex, groupItem);
97 m_groupItems.append(groupItem);
98
99 return;
100 }
101 }
102 }
103 }
104
105}
106
108{
109 Q_ASSERT(widget);
110
111 QWidget *parent = widget->parentWidget();
112 if (parent) {
113 QLayout *layout = parent->layout();
114 if (layout) {
115 // Search the GroupItem of the widget inside of the GroupItem list
116 GroupItem *widgetGroupItem = 0;
117 Q_FOREACH(GroupItem * groupItem, m_groupItems) {
118 if (groupItem->widget() == widget) {
119 widgetGroupItem = groupItem;
120 break;
121 }
122 }
123
124 if (widgetGroupItem) {
125 m_groupItems.removeAll(widgetGroupItem);
126
127 int layoutWidgetIndex = layout->indexOf(widget);
128
129 // Now we need to replace the GroupItem with a QWidgetItem for the widget.
130 // This step depends on the actual layout specialization.
131
132 // Widget within a QFormLayout
133 QFormLayout* formLayout = qobject_cast<QFormLayout*>(layout);
134 if (formLayout) {
135 int row;
136 QFormLayout::ItemRole role;
137 formLayout->getItemPosition(layoutWidgetIndex, &row, &role);
138 formLayout->removeItem(widgetGroupItem);
139 delete widgetGroupItem;
140 formLayout->setWidget(row, role, widget);
141
142 return;
143 }
144
145 // Widget within a QGridLayout
146 QGridLayout *gridLayout = qobject_cast<QGridLayout*>(layout);
147 if (gridLayout) {
148 int row, column, rowspan, columnspan;
149 gridLayout->getItemPosition(layoutWidgetIndex, &row, &column, &rowspan, &columnspan);
150 gridLayout->removeItem(widgetGroupItem);
151 delete widgetGroupItem;
152 QWidgetItem *widgetItem = new QWidgetItem(widget);
153 gridLayout->addItem(widgetItem, row, column, rowspan, columnspan);
154
155 return;
156 }
157
158 // Widget within a QBoxLayout
159 QBoxLayout *boxLayout = qobject_cast<QBoxLayout*>(layout);
160 if (boxLayout) {
161 boxLayout->removeItem(widgetGroupItem);
162 delete widgetGroupItem;
163 QWidgetItem *widgetItem = new QWidgetItem(widget);
164 boxLayout->insertItem(layoutWidgetIndex, widgetItem);
165
166 return;
167 }
168 }
169 }
170 }
171}
172
177
179{
181 // restore original widget size in each GroupItem
182 Q_FOREACH(GroupItem *groupItem, m_groupItems) {
183 groupItem->setSize(groupItem->widget()->sizeHint());
184 groupItem->widget()->updateGeometry();
185 }
186 } else {
187 // compute widgets size
188 int width = 0;
189 int height = 0;
190 Q_FOREACH(GroupItem *groupItem, m_groupItems) {
191 if (m_ignoreHidden && groupItem->hidden())
192 continue;
193
194 const QWidget *widget = groupItem->widget();
195 width = qMax(widget->sizeHint().width(), width);
196 height = qMax(widget->sizeHint().height(), height);
197 }
198
199 m_sizeHint.setWidth(width);
200 m_sizeHint.setHeight(height);
201
202 // update groupItem size
203 Q_FOREACH(GroupItem *groupItem, m_groupItems) {
204 if (m_ignoreHidden && groupItem->hidden())
205 continue;
206
207 switch(m_mode) {
209 groupItem->setWidth(width);
210 break;
211
213 groupItem->setHeight(height);
214 break;
215
217 groupItem->setWidth(width);
218 groupItem->setHeight(height);
219 break;
220
221 default:
222 break;
223 }
224
225 // update layout to the new groupItem size
226 groupItem->widget()->updateGeometry();
227
228 }
229 }
230}
231
232GroupItem::GroupItem(QWidget* widget)
233 : QObject()
234 , QWidgetItem(widget)
235{
236 Q_ASSERT(widget);
237 m_size = widget->sizeHint();
238 m_hidden = !widget->isVisible();
239 widget->installEventFilter(this);
240}
241
243{
244 return m_size;
245}
246
248{
249 QSize size = QWidgetItem::minimumSize();
251 size = m_group->getSizeHint();
252 }
253 return size;
254}
255
256
257bool GroupItem::eventFilter(QObject*, QEvent *event)
258{
259 switch (event->type()) {
260 case QEvent::Hide:
261 if (!event->spontaneous()) {
262 m_hidden = true;
264 }
265 break;
266
267 case QEvent::Show:
268 if (!event->spontaneous()) {
269 m_hidden = false;
271 }
272 break;
273
274 case QEvent::Resize:
276 break;
277
278 default:
279 break;
280 }
281
282 return false;
283}
bool hidden() const
KisSizeGroupPrivate * getGroup()
void setSize(const QSize &size)
QSize sizeHint() const override
QSize minimumSize() const override
KisSizeGroupPrivate * m_group
void setGroup(KisSizeGroupPrivate *group)
void setHeight(int height)
GroupItem(QWidget *widget)
bool eventFilter(QObject *, QEvent *event) override
void setWidth(int width)
KisSizeGroup::mode m_mode
KisSizeGroupPrivate(KisSizeGroup *q_ptr, KisSizeGroup::mode mode, bool ignoreHidden)
QList< GroupItem * > m_groupItems
void addWidget(QWidget *widget)
const QSize getSizeHint() const
Returns the size hint for the widgets contained in the size group.
void scheduleSizeUpdate()
Schedules an update of all widgets size.
void removeWidget(QWidget *widget)
@ KIS_SIZE_GROUP_BOTH
group affects vertical size
@ KIS_SIZE_GROUP_VERTICAL
group affects horizontal size
@ KIS_SIZE_GROUP_HORIZONTAL
group has no effect