KDDockWidgets API Documentation 2.0
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)
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 // QtQuick doesn't support nesting yet
76 honourNesting = honourNesting && Platform::instance()->isQtWidgets();
77
78 if (honourNesting) {
79 // This layout might be a MDIArea, nested in DropArea, which is main window.
80 if (Controller *c = view()->d->firstParentOfType(ViewType::MainWindow))
81 return static_cast<Core::MainWindow *>(c);
82 return nullptr;
83 } else {
84 if (auto pw = view()->parentView()) {
85 // Note that if pw is a FloatingWindow then pw->parentWidget() can be a MainWindow too,
86 // as it's parented
87 if (pw->viewName() == QLatin1String("MyCentralWidget"))
88 return pw->parentView()->asMainWindowController();
89
90 if (auto mw = pw->asMainWindowController())
91 return mw;
92 }
93 }
94
95 return nullptr;
96}
97
99{
100 auto parent = view()->rootView();
101 return parent ? parent->asFloatingWindowController() : nullptr;
102}
103
104void Layout::setRootItem(Core::ItemContainer *root)
105{
106 delete d->m_rootItem;
107 d->m_rootItem = root;
108 d->m_rootItem->numVisibleItemsChanged.connect(
109 [this](int count) { d->visibleWidgetCountChanged.emit(count); });
110
111 d->m_minSizeChangedHandler =
112 d->m_rootItem->minSizeChanged.connect([this] { view()->setMinimumSize(layoutMinimumSize()); });
113}
114
116{
117 return d->m_rootItem->minSize();
118}
119
121{
122 return d->m_rootItem->maxSizeHint();
123}
124
126{
127 if (sz != d->m_rootItem->minSize()) {
128 setLayoutSize(layoutSize().expandedTo(d->m_rootItem->minSize())); // Increase size in case we
129 // need to
130 d->m_rootItem->setMinSize(sz);
131 }
132}
133
135{
136 return d->m_rootItem->size();
137}
138
140{
141 d->m_rootItem->clear();
142}
143
145{
146 return d->m_rootItem->checkSanity();
147}
148
150{
151 d->m_rootItem->dumpLayout();
152}
153
154void Layout::restorePlaceholder(Core::DockWidget *dw, Core::Item *item, int tabIndex)
155{
156 if (item->isPlaceholder()) {
157 auto newGroup = new Core::Group(view());
158 item->restore(newGroup->asLayoutingGuest());
159 }
160
161 auto group = Group::fromItem(item);
162 assert(group);
163 if (group->inDtor() || group->beingDeletedLater()) {
164 // Known bug. Let's print diagnostics early, as this is usually difficult to debug
165 // further up the stack. Will also fatal the tests.
166 KDDW_ERROR("Layout::restorePlaceholder: Trying to use a group that's being deleted");
167 }
168
169 if (tabIndex != -1 && group->dockWidgetCount() >= tabIndex) {
170 group->insertWidget(dw, tabIndex);
171 } else {
172 group->addTab(dw);
173 }
174
175 group->Controller::setVisible(true);
176}
177
178void Layout::unrefOldPlaceholders(const Core::Group::List &groupsBeingAdded) const
179{
180 for (Core::Group *group : groupsBeingAdded) {
181 const auto dws = group->dockWidgets();
182 for (Core::DockWidget *dw : dws) {
183 dw->d->lastPosition()->removePlaceholders(d);
184 }
185 }
186}
187
189{
190 if (size != layoutSize()) {
191 d->m_rootItem->setSize_recursive(size);
192 if (!d->m_inResizeEvent && !LayoutSaver::restoreInProgress())
193 view()->resize(size);
194 }
195}
196
197Core::Item::List Layout::items() const
198{
199 return d->m_rootItem->items_recursive();
200}
201
202bool Layout::containsItem(const Core::Item *item) const
203{
204 return d->m_rootItem->contains_recursive(item);
205}
206
207bool Layout::containsFrame(const Core::Group *group) const
208{
209 return itemForFrame(group) != nullptr;
210}
211
212int Layout::count() const
213{
214 return d->m_rootItem->count_recursive();
215}
216
218{
219 return d->m_rootItem->visibleCount_recursive();
220}
221
223{
224 return count() - visibleCount();
225}
226
227Core::Item *Layout::itemForFrame(const Core::Group *group) const
228{
229 if (!group)
230 return nullptr;
231
232 return d->m_rootItem->itemForView(group->asLayoutingGuest());
233}
234
236{
238 const Core::Group::List groups = this->groups();
239 for (Core::Group *group : groups)
240 dockWidgets.append(group->dockWidgets());
241
242 return dockWidgets;
243}
244
245Core::Group::List Layout::groupsFrom(View *groupOrMultiSplitter) const
246{
247 if (auto group = groupOrMultiSplitter->asGroupController())
248 return { group };
249
250 if (auto msw = groupOrMultiSplitter->asDropAreaController())
251 return msw->groups();
252
253 return {};
254}
255
257{
258 const Core::Item::List items = d->m_rootItem->items_recursive();
259
260 Core::Group::List result;
261 result.reserve(items.size());
262
263 for (Core::Item *item : items) {
264 if (auto group = Group::fromItem(item)) {
265 result.push_back(group);
266 }
267 }
268
269 return result;
270}
271
272void Layout::removeItem(Core::Item *item)
273{
274 if (!item) {
275 KDDW_ERROR("nullptr item");
276 return;
277 }
278
279 item->parentContainer()->removeItem(item);
280}
281
283{
284 const Size newMinSize = d->m_rootItem->minSize();
285 setLayoutMinimumSize(newMinSize);
286}
287
288bool Layout::deserialize(const LayoutSaver::MultiSplitter &l)
289{
290 std::unordered_map<QString, LayoutingGuest *> groups;
291 for (const auto &it : l.groups) {
292 const LayoutSaver::Group &group = it.second;
294 if (!f)
295 return false;
296
297 assert(!group.id.isEmpty());
298 groups[group.id] = f->asLayoutingGuest();
299 }
300
301 d->m_rootItem->fillFromJson(l.layout, groups);
303
304 const Size newLayoutSize = view()->size().expandedTo(d->m_rootItem->minSize());
305
306 d->m_rootItem->setSize_recursive(newLayoutSize);
307
308 return true;
309}
310
311bool Layout::onResize(Size newSize)
312{
313 ScopedValueRollback resizeGuard(d->m_inResizeEvent, true); // to avoid re-entrancy
314
316 // don't resize anything while we're restoring the layout
317 setLayoutSize(newSize);
318 }
319
320 return false; // So QWidget::resizeEvent is called
321}
322
323LayoutSaver::MultiSplitter Layout::serialize() const
324{
325 LayoutSaver::MultiSplitter l;
326 d->m_rootItem->to_json(l.layout);
327 const Core::Item::List items = d->m_rootItem->items_recursive();
328 l.groups.reserve(size_t(items.size()));
329 for (Core::Item *item : items) {
330 if (!item->isContainer()) {
331 if (auto group = Group::fromItem(item)) {
332 l.groups[group->view()->d->id()] = group->serialize();
333 }
334 }
335 }
336
337 return l;
338}
339
341{
342 return view()->asDropAreaController();
343}
344
346{
347 if (auto v = view())
348 return v->asMDILayoutController();
349
350 return nullptr;
351}
352
353Core::ItemContainer *Layout::rootItem() const
354{
355 return d->m_rootItem;
356}
357
358void Layout::onCloseEvent(CloseEvent *e)
359{
360 e->accept(); // Accepted by default (will close unless ignored)
361
362 const Core::Group::List groups = this->groups();
363 for (Core::Group *group : groups) {
364 group->view()->d->requestClose(e);
365 if (!e->isAccepted())
366 break; // Stop when the first group prevents closing
367 }
368}
369
370LayoutingHost *Layout::asLayoutingHost() const
371{
372 return d;
373}
374
375Layout::Private *Layout::d_ptr()
376{
377 return d;
378}
379
380bool Layout::Private::supportsHonouringLayoutMinSize() const
381{
382 if (auto window = q->view()->window()) {
383 return window->supportsHonouringLayoutMinSize();
384 } else {
385 // Corner case. No reason not to honour min-size
386 return true;
387 }
388}
389
390Layout::Private::Private(Layout *qq)
391 : q(qq)
392{
393}
394
395Layout::Private::~Private() = default;
396
397
400{
401 if (auto layoutPriv = dynamic_cast<Core::Layout::Private *>(host))
402 return layoutPriv->q;
403
404 return nullptr;
405}
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:202
Vector< Core::Group * > groups() const
Returns this list of Group objects contained in this layout.
Definition Layout.cpp:256
Layout::Private * d_ptr()
Definition Layout.cpp:375
Core::MDILayout * asMDILayout() const
Definition Layout.cpp:345
void unrefOldPlaceholders(const Vector< Core::Group * > &groupsBeingAdded) const
Removes unneeded placeholder items when adding new groups.
Definition Layout.cpp:178
int visibleCount() const
Returns the number of visible Items in this layout. Which is count minus placeholderCount.
Definition Layout.cpp:217
void setRootItem(Core::ItemContainer *root)
Definition Layout.cpp:104
void onCloseEvent(CloseEvent *)
Definition Layout.cpp:358
void setLayoutSize(Size)
setter for the contents size The "contents size" is just the size() of this layout....
Definition Layout.cpp:188
int count() const
Returns the number of Item objects in this layout. This includes non-visible (placeholder) Items too.
Definition Layout.cpp:212
virtual bool deserialize(const LayoutSaver::MultiSplitter &)
Definition Layout.cpp:288
LayoutingHost * asLayoutingHost() const
Definition Layout.cpp:370
int placeholderCount() const
Returns the number of placeholder items in this layout. This is the same as count minus visibleCount.
Definition Layout.cpp:222
bool checkSanity() const
Runs some sanity checks. Returns true if everything is OK.
Definition Layout.cpp:144
Core::Item * itemForFrame(const Core::Group *group) const
returns the Item that holds group in this layout
Definition Layout.cpp:227
Size layoutSize() const
Returns the size of the contents.
Definition Layout.cpp:134
void dumpLayout() const
dumps the layout to stderr
Definition Layout.cpp:149
Vector< Core::Group * > groupsFrom(View *groupOrMultiSplitter) const
returns the groups contained in groupOrMultiSplitter- If groupOrMultiSplitter- is a Group,...
Definition Layout.cpp:245
Vector< Core::Item * > items() const
The list of items in this layout.
Definition Layout.cpp:197
Layout(ViewType, View *)
Definition Layout.cpp:36
Core::DropArea * asDropArea() const
Definition Layout.cpp:340
void removeItem(Core::Item *item)
Removes an item from this MultiSplitter.
Definition Layout.cpp:272
void restorePlaceholder(Core::DockWidget *dw, Core::Item *, int tabIndex)
restores the dockwidget dw to its previous position
Definition Layout.cpp:154
Size layoutMaximumSizeHint() const
returns the layout's maximum size hint
Definition Layout.cpp:120
void updateSizeConstraints()
Updates the min size of this layout.
Definition Layout.cpp:282
static Layout * fromLayoutingHost(LayoutingHost *)
Definition Layout.cpp:399
Core::ItemContainer * rootItem() const
Definition Layout.cpp:353
bool containsFrame(const Core::Group *) const
Returns true if this layout contains the specified group.
Definition Layout.cpp:207
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:323
Vector< Core::DockWidget * > dockWidgets() const
Returns the list of dock widgets contained in this layout.
Definition Layout.cpp:235
void setLayoutMinimumSize(Size)
setter for the minimum size minimumSize
Definition Layout.cpp:125
Size layoutMinimumSize() const
returns the layout's minimum size setLayoutMinimumSize
Definition Layout.cpp:115
void clearLayout()
clears the layout
Definition Layout.cpp:139
Core::FloatingWindow * floatingWindow() const
Definition Layout.cpp:98
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...
static Platform * instance()
Returns the platform singleton.
bool isQtWidgets() const
Returns whether this platform is QtWidgets.
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 DockRegistry * self()
void unregisterLayout(Core::Layout *)
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