KDDockWidgets API Documentation 2.1
Loading...
Searching...
No Matches
Layout.cpp
Go to the documentation of this file.
1/*
2 This file is part of KDDockWidgets.
3
4 SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
5 Author: SĂ©rgio Martins <sergio.martins@kdab.com>
6
7 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
8
9 Contact KDAB at <info@kdab.com> for commercial licensing options.
10*/
11
12#include "Layout.h"
13#include "Layout_p.h"
14#include "LayoutSaver_p.h"
15#include "Position_p.h"
16#include "Config.h"
17#include "Platform.h"
18#include "ViewFactory.h"
19#include "Utils_p.h"
20#include "View_p.h"
21#include "Logging_p.h"
22#include "ScopedValueRollback_p.h"
23#include "DropArea.h"
24#include "DockWidget_p.h"
25#include "Group.h"
26#include "FloatingWindow.h"
27#include "MainWindow.h"
28#include "layouting/Item_p.h"
29
30#include <unordered_map>
31
32using namespace KDDockWidgets;
33using namespace KDDockWidgets::Core;
34
35
37 : Controller(type, view)
38 , d(new Private(this))
39{
40 assert(view);
41 view->d->layoutInvalidated.connect([this] { updateSizeConstraints(); });
42
43 view->d->resized.connect(&Layout::onResize, this);
44}
45
47{
48 d->m_minSizeChangedHandler.disconnect();
49
50 if (d->m_rootItem && !d->m_viewDeleted)
52
53 delete d;
54}
55
57{
58 if (view()) {
59 if (d == d->m_rootItem->host()) {
60 delete d->m_rootItem;
61 d->m_rootItem = nullptr;
62 }
63
64 d->m_viewDeleted = true;
65 }
66}
67
68bool Layout::isInMainWindow(bool honourNesting) const
69{
70 return mainWindow(honourNesting) != nullptr;
71}
72
73Core::MainWindow *Layout::mainWindow(bool honourNesting) const
74{
75 if (honourNesting) {
76 // This layout might be a MDIArea, nested in DropArea, which is main window.
77 if (Controller *c = view()->d->firstParentOfType(ViewType::MainWindow))
78 return static_cast<Core::MainWindow *>(c);
79 return nullptr;
80 } else {
81 if (auto pw = view()->parentView()) {
82 // Note that if pw is a FloatingWindow then pw->parentWidget() can be a MainWindow too,
83 // as it's parented
84 if (pw->viewName() == QLatin1String("MyCentralWidget"))
85 return pw->parentView()->asMainWindowController();
86
87 if (auto mw = pw->asMainWindowController())
88 return mw;
89 }
90 }
91
92 return nullptr;
93}
94
96{
97 auto parent = view()->rootView();
98 return parent ? parent->asFloatingWindowController() : nullptr;
99}
100
101void Layout::setRootItem(Core::ItemContainer *root)
102{
103 delete d->m_rootItem;
104 d->m_rootItem = root;
105 d->m_rootItem->numVisibleItemsChanged.connect(
106 [this](int count) { d->visibleWidgetCountChanged.emit(count); });
107
108 d->m_minSizeChangedHandler =
109 d->m_rootItem->minSizeChanged.connect([this] { view()->setMinimumSize(layoutMinimumSize()); });
110}
111
113{
114 return d->m_rootItem->minSize();
115}
116
118{
119 return d->m_rootItem->maxSizeHint();
120}
121
123{
124 if (sz != d->m_rootItem->minSize()) {
125 setLayoutSize(layoutSize().expandedTo(d->m_rootItem->minSize())); // Increase size in case we
126 // need to
127 d->m_rootItem->setMinSize(sz);
128 }
129}
130
132{
133 return d->m_rootItem->size();
134}
135
137{
138 d->m_rootItem->clear();
139}
140
142{
143 return d->m_rootItem->checkSanity();
144}
145
147{
148 d->m_rootItem->dumpLayout();
149}
150
151void Layout::restorePlaceholder(Core::DockWidget *dw, Core::Item *item, int tabIndex)
152{
153 if (item->isPlaceholder()) {
154 auto newGroup = new Core::Group(view());
155 item->restore(newGroup->asLayoutingGuest());
156 }
157
158 auto group = Group::fromItem(item);
159 assert(group);
160 if (group->inDtor() || group->beingDeletedLater()) {
161 // Known bug. Let's print diagnostics early, as this is usually difficult to debug
162 // further up the stack. Will also fatal the tests.
163 KDDW_ERROR("Layout::restorePlaceholder: Trying to use a group that's being deleted");
164 }
165
166 if (tabIndex != -1 && group->dockWidgetCount() >= tabIndex) {
167 group->insertWidget(dw, tabIndex);
168 } else {
169 group->addTab(dw);
170 }
171
172 group->Controller::setVisible(true);
173}
174
175void Layout::unrefOldPlaceholders(const Core::Group::List &groupsBeingAdded) const
176{
177 for (Core::Group *group : groupsBeingAdded) {
178 const auto dws = group->dockWidgets();
179 for (Core::DockWidget *dw : dws) {
180 dw->d->lastPosition()->removePlaceholders(d);
181 }
182 }
183}
184
186{
187 if (size != layoutSize()) {
188 d->m_rootItem->setSize_recursive(size);
189 if (!d->m_inResizeEvent && !LayoutSaver::restoreInProgress())
190 view()->resize(size);
191 }
192}
193
194Core::Item::List Layout::items() const
195{
196 return d->m_rootItem->items_recursive();
197}
198
199bool Layout::containsItem(const Core::Item *item) const
200{
201 return d->m_rootItem->contains_recursive(item);
202}
203
204bool Layout::containsGroup(const Core::Group *group) const
205{
206 return itemForGroup(group) != nullptr;
207}
208
209int Layout::count() const
210{
211 return d->m_rootItem->count_recursive();
212}
213
215{
216 return d->m_rootItem->visibleCount_recursive();
217}
218
220{
221 return count() - visibleCount();
222}
223
224Core::Item *Layout::itemForGroup(const Core::Group *group) const
225{
226 if (!group)
227 return nullptr;
228
229 return d->m_rootItem->itemForView(group->asLayoutingGuest());
230}
231
233{
235 const Core::Group::List groups = this->groups();
236 for (Core::Group *group : groups)
237 dockWidgets.append(group->dockWidgets());
238
239 return dockWidgets;
240}
241
242Core::Group::List Layout::groupsFrom(View *groupOrMultiSplitter) const
243{
244 if (auto group = groupOrMultiSplitter->asGroupController())
245 return { group };
246
247 if (auto msw = groupOrMultiSplitter->asDropAreaController())
248 return msw->groups();
249
250 return {};
251}
252
254{
255 const Core::Item::List items = d->m_rootItem->items_recursive();
256
257 Core::Group::List result;
258 result.reserve(items.size());
259
260 for (Core::Item *item : items) {
261 if (auto group = Group::fromItem(item)) {
262 result.push_back(group);
263 }
264 }
265
266 return result;
267}
268
269void Layout::removeItem(Core::Item *item)
270{
271 if (!item) {
272 KDDW_ERROR("nullptr item");
273 return;
274 }
275
276 item->parentContainer()->removeItem(item);
277}
278
280{
281 const Size newMinSize = d->m_rootItem->minSize();
282 setLayoutMinimumSize(newMinSize);
283}
284
285bool Layout::deserialize(const LayoutSaver::MultiSplitter &l)
286{
287 std::unordered_map<QString, LayoutingGuest *> groups;
288 for (const auto &it : l.groups) {
289 const LayoutSaver::Group &group = it.second;
291 if (!f)
292 return false;
293
294 assert(!group.id.isEmpty());
295 groups[group.id] = f->asLayoutingGuest();
296 }
297
298 d->m_rootItem->fillFromJson(l.layout, groups);
300
301 const Size newLayoutSize = view()->size().expandedTo(d->m_rootItem->minSize());
302
303 d->m_rootItem->setSize_recursive(newLayoutSize);
304
305 return true;
306}
307
308bool Layout::onResize(Size newSize)
309{
310 ScopedValueRollback resizeGuard(d->m_inResizeEvent, true); // to avoid re-entrancy
311
313 // don't resize anything while we're restoring the layout
314 setLayoutSize(newSize);
315 }
316
317 return false; // So QWidget::resizeEvent is called
318}
319
320LayoutSaver::MultiSplitter Layout::serialize() const
321{
322 LayoutSaver::MultiSplitter l;
323 d->m_rootItem->to_json(l.layout);
324 const Core::Item::List items = d->m_rootItem->items_recursive();
325 l.groups.reserve(size_t(items.size()));
326 for (Core::Item *item : items) {
327 if (!item->isContainer()) {
328 if (auto group = Group::fromItem(item)) {
329 l.groups[group->view()->d->id()] = group->serialize();
330 }
331 }
332 }
333
334 return l;
335}
336
338{
339 return view()->asDropAreaController();
340}
341
343{
344 if (auto v = view())
345 return v->asMDILayoutController();
346
347 return nullptr;
348}
349
350Core::ItemContainer *Layout::rootItem() const
351{
352 return d->m_rootItem;
353}
354
355void Layout::onCloseEvent(CloseEvent *e)
356{
357 e->accept(); // Accepted by default (will close unless ignored)
358
359 const Core::Group::List groups = this->groups();
360 for (Core::Group *group : groups) {
361 group->view()->d->requestClose(e);
362 if (!e->isAccepted())
363 break; // Stop when the first group prevents closing
364 }
365}
366
367LayoutingHost *Layout::asLayoutingHost() const
368{
369 return d;
370}
371
372Layout::Private *Layout::d_ptr()
373{
374 return d;
375}
376
377bool Layout::Private::supportsHonouringLayoutMinSize() const
378{
379 if (auto window = q->view()->window()) {
380 return window->supportsHonouringLayoutMinSize();
381 } else {
382 // Corner case. No reason not to honour min-size
383 return true;
384 }
385}
386
387Layout::Private::Private(Layout *qq)
388 : q(qq)
389{
390}
391
392Layout::Private::~Private() = default;
393
394
397{
398 if (auto layoutPriv = dynamic_cast<Core::Layout::Private *>(host))
399 return layoutPriv->q;
400
401 return nullptr;
402}
Application-wide config to tune certain behaviours of the framework.
A widget that supports an arbitrary number of splitters (called Separators) in any combination of ver...
View * view() const
Returns the view associated with this controller, if any.
The DockWidget base-class. DockWidget and Core::DockWidget are only split in two so we can share some...
static Core::Group * fromItem(const Core::Item *)
Returns the group that's in the specified item.
static Group * deserialize(const LayoutSaver::Group &)
LayoutingGuest * asLayoutingGuest() const
The widget (QWidget or QQuickItem) which holds a layout of dock widgets.
Definition Layout.h:57
bool containsItem(const Core::Item *) const
Returns true if this layout contains the specified item.
Definition Layout.cpp:199
Vector< Core::Group * > groups() const
Returns this list of Group objects contained in this layout.
Definition Layout.cpp:253
Layout::Private * d_ptr()
Definition Layout.cpp:372
Core::MDILayout * asMDILayout() const
Definition Layout.cpp:342
void unrefOldPlaceholders(const Vector< Core::Group * > &groupsBeingAdded) const
Removes unneeded placeholder items when adding new groups.
Definition Layout.cpp:175
int visibleCount() const
Returns the number of visible Items in this layout. Which is count minus placeholderCount.
Definition Layout.cpp:214
void setRootItem(Core::ItemContainer *root)
Definition Layout.cpp:101
void onCloseEvent(CloseEvent *)
Definition Layout.cpp:355
void setLayoutSize(Size)
setter for the contents size The "contents size" is just the size() of this layout....
Definition Layout.cpp:185
int count() const
Returns the number of Item objects in this layout. This includes non-visible (placeholder) Items too.
Definition Layout.cpp:209
virtual bool deserialize(const LayoutSaver::MultiSplitter &)
Definition Layout.cpp:285
LayoutingHost * asLayoutingHost() const
Definition Layout.cpp:367
int placeholderCount() const
Returns the number of placeholder items in this layout. This is the same as count minus visibleCount.
Definition Layout.cpp:219
bool checkSanity() const
Runs some sanity checks. Returns true if everything is OK.
Definition Layout.cpp:141
Core::Item * itemForGroup(const Core::Group *group) const
returns the Item that holds group in this layout
Definition Layout.cpp:224
Size layoutSize() const
Returns the size of the contents.
Definition Layout.cpp:131
void dumpLayout() const
dumps the layout to stderr
Definition Layout.cpp:146
Vector< Core::Group * > groupsFrom(View *groupOrMultiSplitter) const
returns the groups contained in groupOrMultiSplitter- If groupOrMultiSplitter- is a Group,...
Definition Layout.cpp:242
Vector< Core::Item * > items() const
The list of items in this layout.
Definition Layout.cpp:194
Layout(ViewType, View *)
Definition Layout.cpp:36
Core::DropArea * asDropArea() const
Definition Layout.cpp:337
void removeItem(Core::Item *item)
Removes an item from this MultiSplitter.
Definition Layout.cpp:269
bool containsGroup(const Core::Group *) const
Returns true if this layout contains the specified group.
Definition Layout.cpp:204
void restorePlaceholder(Core::DockWidget *dw, Core::Item *, int tabIndex)
restores the dockwidget dw to its previous position
Definition Layout.cpp:151
Size layoutMaximumSizeHint() const
returns the layout's maximum size hint
Definition Layout.cpp:117
void updateSizeConstraints()
Updates the min size of this layout.
Definition Layout.cpp:279
static Layout * fromLayoutingHost(LayoutingHost *)
Definition Layout.cpp:396
Core::ItemContainer * rootItem() const
Definition Layout.cpp:350
bool isInMainWindow(bool honourNesting=false) const
Returns whether this layout is in a MainWindow.
Definition Layout.cpp:68
Core::MainWindow * mainWindow(bool honourNesting=false) const
Definition Layout.cpp:73
LayoutSaver::MultiSplitter serialize() const
Definition Layout.cpp:320
Vector< Core::DockWidget * > dockWidgets() const
Returns the list of dock widgets contained in this layout.
Definition Layout.cpp:232
void setLayoutMinimumSize(Size)
setter for the minimum size minimumSize
Definition Layout.cpp:122
Size layoutMinimumSize() const
returns the layout's minimum size setLayoutMinimumSize
Definition Layout.cpp:112
void clearLayout()
clears the layout
Definition Layout.cpp:136
Core::FloatingWindow * floatingWindow() const
Definition Layout.cpp:95
The MDILayout class implements a layout suitable for MDI style docking. Where dock widgets are free t...
The MainWindow base-class. MainWindow and MainWindowBase are only split in two so we can share some c...
virtual std::shared_ptr< View > rootView() const =0
Returns the top-level gui element which this view is inside It's the root view of the window.
virtual std::shared_ptr< View > parentView() const =0
Returns the gui element's parent. Like QWidget::parentWidget()
Core::Group * asGroupController() const
Core::DropArea * asDropAreaController() const
virtual void setMinimumSize(Size)=0
static bool restoreInProgress()
returns whether a restore (restoreLayout) is in progress
ViewType
Each View type also has a specific Controller associated with, except for ViewType::None.
Definition Controller.h:26
Class to abstract QAction, so code still works with QtQuick and Flutter.
A factory class for allowing the user to customize some internal widgets.
A MultiSplitter with support for drop indicators when hovering over.
QMainWindow sub-class to enable KDDockWidgets support.

© Klarälvdalens Datakonsult AB (KDAB)
"The Qt, C++ and OpenGL Experts"
https://www.kdab.com/
KDDockWidgets
Advanced Dock Widget Framework for Qt
https://www.kdab.com/development-resources/qt-tools/kddockwidgets/
Generated by doxygen 1.9.8