KDDockWidgets API Documentation 1.7
Loading...
Searching...
No Matches
LayoutWidget.cpp
Go to the documentation of this file.
1/*
2 This file is part of KDDockWidgets.
3
4 SPDX-FileCopyrightText: 2020-2023 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 "LayoutSaver_p.h"
13#include "Config.h"
14#include "DockWidgetBase_p.h"
15#include "FloatingWindow_p.h"
16#include "Frame_p.h"
18#include "MainWindowBase.h"
19#include "Position_p.h"
20#include "Utils_p.h"
21
22#include "multisplitter/Item_p.h"
23
24using namespace KDDockWidgets;
25
26
27LayoutWidget::LayoutWidget(QWidgetOrQuick *parent)
28 : LayoutGuestWidget(parent)
29{
30}
31
32LayoutWidget::~LayoutWidget()
33{
34 if (m_rootItem->hostWidget()->asQObject() == this)
35 delete m_rootItem;
36 DockRegistry::self()->unregisterLayout(this);
37}
38
39bool LayoutWidget::isInMainWindow(bool honourNesting) const
40{
41 return mainWindow(honourNesting) != nullptr;
42}
43
44MainWindowBase *LayoutWidget::mainWindow(bool honourNesting) const
45{
46 // QtQuick doesn't support nesting yet
47 honourNesting = honourNesting && kddwUsesQtWidgets();
48
49 if (honourNesting) {
50 // This layout might be a MDIArea, nested in DropArea, which is main window.
51 return firstParentOfType<MainWindowBase>(this);
52 } else {
53
54 if (auto pw = QWidgetAdapter::parentWidget()) {
55 // Note that if pw is a FloatingWindow then pw->parentWidget() can be a MainWindow too, as
56 // it's parented
57 if (pw->objectName() == QLatin1String("MyCentralWidget"))
58 return qobject_cast<MainWindowBase *>(pw->parentWidget());
59
60 if (auto mw = qobject_cast<MainWindowBase *>(pw))
61 return mw;
62 }
63 }
64
65 return nullptr;
66}
67
68FloatingWindow *LayoutWidget::floatingWindow() const
69{
70 return qobject_cast<FloatingWindow *>(QWidgetAdapter::parentWidget());
71}
72
73void LayoutWidget::setRootItem(Layouting::ItemContainer *root)
74{
75 delete m_rootItem;
76 m_rootItem = root;
77 connect(m_rootItem, &Layouting::ItemContainer::numVisibleItemsChanged, this,
78 &MultiSplitter::visibleWidgetCountChanged);
79 connect(m_rootItem, &Layouting::ItemContainer::minSizeChanged, this,
80 [this] { setMinimumSize(layoutMinimumSize()); });
81}
82
83QSize LayoutWidget::layoutMinimumSize() const
84{
85 return m_rootItem->minSize();
86}
87
88QSize LayoutWidget::layoutMaximumSizeHint() const
89{
90 return m_rootItem->maxSizeHint();
91}
92
93void LayoutWidget::setLayoutMinimumSize(QSize sz)
94{
95 if (sz != m_rootItem->minSize()) {
96 setLayoutSize(size().expandedTo(m_rootItem->minSize())); // Increase size in case we need to
97 m_rootItem->setMinSize(sz);
98 }
99}
100
101QSize LayoutWidget::size() const
102{
103 return m_rootItem->size();
104}
105
106void LayoutWidget::clearLayout()
107{
108 m_rootItem->clear();
109}
110
111bool LayoutWidget::checkSanity() const
112{
113 return m_rootItem->checkSanity();
114}
115
116void LayoutWidget::dumpLayout() const
117{
118 m_rootItem->dumpLayout();
119}
120
121void LayoutWidget::restorePlaceholder(DockWidgetBase *dw, Layouting::Item *item, int tabIndex)
122{
123 if (item->isPlaceholder()) {
124 Frame *newFrame = Config::self().frameworkWidgetFactory()->createFrame(this);
125 item->restore(newFrame);
126 }
127
128 auto frame = qobject_cast<Frame *>(item->guestAsQObject());
129 Q_ASSERT(frame);
130
131 if (tabIndex != -1 && frame->dockWidgetCount() >= tabIndex) {
132 frame->insertWidget(dw, tabIndex);
133 } else {
134 frame->addWidget(dw);
135 }
136
137 frame->QWidgetAdapter::setVisible(true);
138}
139
140void LayoutWidget::unrefOldPlaceholders(const Frame::List &framesBeingAdded) const
141{
142 for (Frame *frame : framesBeingAdded) {
143 for (DockWidgetBase *dw : frame->dockWidgets()) {
144 dw->d->lastPosition()->removePlaceholders(this);
145 }
146 }
147}
148
149void LayoutWidget::setLayoutSize(QSize size)
150{
151 if (size != this->size()) {
152 m_rootItem->setSize_recursive(size);
153 if (!m_inResizeEvent && !LayoutSaver::restoreInProgress())
154 resize(size);
155 }
156}
157
158const Layouting::Item::List LayoutWidget::items() const
159{
160 return m_rootItem->items_recursive();
161}
162
163bool LayoutWidget::containsItem(const Layouting::Item *item) const
164{
165 return m_rootItem->contains_recursive(item);
166}
167
168bool LayoutWidget::containsFrame(const Frame *frame) const
169{
170 return itemForFrame(frame) != nullptr;
171}
172
173int LayoutWidget::count() const
174{
175 return m_rootItem->count_recursive();
176}
177
178int LayoutWidget::visibleCount() const
179{
180 return m_rootItem->visibleCount_recursive();
181}
182
183int LayoutWidget::placeholderCount() const
184{
185 return count() - visibleCount();
186}
187
188Layouting::Item *LayoutWidget::itemForFrame(const Frame *frame) const
189{
190 if (!frame)
191 return nullptr;
192
193 return m_rootItem->itemForWidget(frame);
194}
195
196DockWidgetBase::List LayoutWidget::dockWidgets() const
197{
198 DockWidgetBase::List dockWidgets;
199 const Frame::List frames = this->frames();
200 for (Frame *frame : frames)
201 dockWidgets << frame->dockWidgets();
202
203 return dockWidgets;
204}
205
206Frame::List LayoutWidget::framesFrom(QWidgetOrQuick *frameOrMultiSplitter) const
207{
208 if (auto frame = qobject_cast<Frame *>(frameOrMultiSplitter))
209 return { frame };
210
211 if (auto msw = qobject_cast<MultiSplitter *>(frameOrMultiSplitter))
212 return msw->frames();
213
214 return {};
215}
216
217Frame::List LayoutWidget::frames() const
218{
219 const Layouting::Item::List items = m_rootItem->items_recursive();
220
221 Frame::List result;
222 result.reserve(items.size());
223
224 for (Layouting::Item *item : items) {
225 if (auto f = static_cast<Frame *>(item->guestAsQObject()))
226 result.push_back(f);
227 }
228
229 return result;
230}
231
232void LayoutWidget::removeItem(Layouting::Item *item)
233{
234 if (!item) {
235 qWarning() << Q_FUNC_INFO << "nullptr item";
236 return;
237 }
238
239 item->parentContainer()->removeItem(item);
240}
241
242void LayoutWidget::updateSizeConstraints()
243{
244 const QSize newMinSize = m_rootItem->minSize();
245 qCDebug(sizing) << Q_FUNC_INFO << "Updating size constraints from" << minimumSize() << "to"
246 << newMinSize;
247
248 setLayoutMinimumSize(newMinSize);
249}
250
251bool LayoutWidget::deserialize(const LayoutSaver::MultiSplitter &l)
252{
254 for (const LayoutSaver::Frame &frame : qAsConst(l.frames)) {
255 Frame *f = Frame::deserialize(frame);
256 Q_ASSERT(!frame.id.isEmpty());
257 frames.insert(frame.id, f);
258 }
259
260 m_rootItem->fillFromVariantMap(l.layout, frames);
261
262 updateSizeConstraints();
263
264 // This qMin() isn't needed for QtWidgets (but harmless), but it's required for QtQuick
265 // as some sizing is async
266 const QSize newLayoutSize = QWidgetAdapter::size().expandedTo(m_rootItem->minSize());
267
268 m_rootItem->setSize_recursive(newLayoutSize);
269
270 return true;
271}
272
273void LayoutWidget::onLayoutRequest()
274{
275 updateSizeConstraints();
276}
277
278bool LayoutWidget::onResize(QSize newSize)
279{
280 QScopedValueRollback<bool> resizeGuard(m_inResizeEvent, true); // to avoid re-entrancy
281
283 // don't resize anything while we're restoring the layout
284 setLayoutSize(newSize);
285 }
286
287 return false; // So QWidget::resizeEvent is called
288}
289
290LayoutSaver::MultiSplitter LayoutWidget::serialize() const
291{
292 LayoutSaver::MultiSplitter l;
293 l.layout = m_rootItem->toVariantMap();
294 const Layouting::Item::List items = m_rootItem->items_recursive();
295 l.frames.reserve(items.size());
296 for (Layouting::Item *item : items) {
297 if (!item->isContainer()) {
298 if (auto frame = qobject_cast<Frame *>(item->guestAsQObject()))
299 l.frames.insert(frame->id(), frame->serialize());
300 }
301 }
302
303 return l;
304}
305
306void LayoutWidget::onCloseEvent(QCloseEvent *e)
307{
308 e->accept(); // Accepted by default (will close unless ignored)
309
310 const Frame::List frames = this->frames();
311 for (Frame *frame : frames) {
312 qApp->sendEvent(frame, e);
313 if (!e->isAccepted())
314 break; // Stop when the first frame prevents closing
315 }
316}
Application-wide config to tune certain behaviours of the framework.
A factory class for allowing the user to customize some internal widgets.
The MainWindow base-class that's shared between QtWidgets and QtQuick stack.
FrameworkWidgetFactory * frameworkWidgetFactory() const
getter for the framework widget factory
Definition Config.cpp:145
static Config & self()
returns the singleton Config instance
Definition Config.cpp:84
The DockWidget base-class. DockWidget and DockWidgetBase are only split in two so we can share some c...
virtual Frame * createFrame(QWidgetOrQuick *parent=nullptr, FrameOptions options=FrameOption_None) const =0
Called internally by the framework to create a Frame class Override to provide your own Frame sub-cla...
LayoutGuestWidget is the type that Item will host.
static bool restoreInProgress()
returns whether a restore (restoreLayout) is in progress
The MainWindow base-class. MainWindow and MainWindowBase are only split in two so we can share some c...
void accept()
bool isAccepted() const const
QHash::iterator insert(const Key &key, const T &value)
QSize expandedTo(const QSize &otherSize) const const
void reserve(int size)

© 2019-2023 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 on Wed Nov 1 2023 00:02:31 for KDDockWidgets API Documentation by doxygen 1.9.8