KDDockWidgets API Documentation 1.7
Loading...
Searching...
No Matches
MultiSplitter.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
20#include "MultiSplitter_p.h"
21#include "LayoutSaver_p.h"
22#include "Config.h"
23#include "DockRegistry_p.h"
24#include "DockWidgetBase.h"
25#include "DockWidgetBase_p.h"
26#include "FloatingWindow_p.h"
27#include "Frame_p.h"
29#include "LayoutSaver.h"
30#include "Logging_p.h"
31#include "MainWindowBase.h"
32#include "Position_p.h"
33#include "WindowBeingDragged_p.h"
35#include "multisplitter/Item_p.h"
36
37#include <QScopedValueRollback>
38
39using namespace KDDockWidgets;
40
41MultiSplitter::MultiSplitter(QWidgetOrQuick *parent)
42 : LayoutWidget(parent)
43{
44 Q_ASSERT(parent);
45 setRootItem(new Layouting::ItemBoxContainer(this));
46 DockRegistry::self()->registerLayout(this);
47
48 setLayoutSize(parent->size());
49
50 // Initialize min size
51 updateSizeConstraints();
52
53 setMinimumSize(minimumSize());
54}
55
56MultiSplitter::~MultiSplitter()
57{
58}
59
60bool MultiSplitter::validateInputs(QWidgetOrQuick *widget, Location location,
61 const Frame *relativeToFrame, InitialOption option) const
62{
63 if (!widget) {
64 qWarning() << Q_FUNC_INFO << "Widget is null";
65 return false;
66 }
67
68 const bool isDockWidget = qobject_cast<DockWidgetBase *>(widget);
69 const bool isStartHidden = option.startsHidden();
70
71 if (!qobject_cast<Frame *>(widget) && !qobject_cast<MultiSplitter *>(widget) && !isDockWidget) {
72 qWarning() << "Unknown widget type" << widget;
73 return false;
74 }
75
76 if (isDockWidget != isStartHidden) {
77 qWarning() << "Wrong parameters" << isDockWidget << isStartHidden;
78 return false;
79 }
80
81 if (relativeToFrame && relativeToFrame == widget) {
82 qWarning() << "widget can't be relative to itself";
83 return false;
84 }
85
86 Layouting::Item *item = itemForFrame(qobject_cast<Frame *>(widget));
87
88 if (containsItem(item)) {
89 qWarning() << "MultiSplitter::addWidget: Already contains" << widget;
90 return false;
91 }
92
93 if (location == Location_None) {
94 qWarning() << "MultiSplitter::addWidget: not adding to location None";
95 return false;
96 }
97
98 const bool relativeToThis = relativeToFrame == nullptr;
99
100 Layouting::Item *relativeToItem = itemForFrame(relativeToFrame);
101 if (!relativeToThis && !containsItem(relativeToItem)) {
102 qWarning() << "MultiSplitter::addWidget: Doesn't contain relativeTo:"
103 << "; relativeToFrame=" << relativeToFrame
104 << "; relativeToItem=" << relativeToItem
105 << "; options=" << option;
106 return false;
107 }
108
109 return true;
110}
111
112void MultiSplitter::addWidget(QWidgetOrQuick *w, Location location,
113 Frame *relativeToWidget,
114 InitialOption option)
115{
116 auto frame = qobject_cast<Frame *>(w);
117 if (itemForFrame(frame) != nullptr) {
118 // Item already exists, remove it.
119 // Changing the frame parent will make the item clean itself up. It turns into a placeholder and is removed by unrefOldPlaceholders
120 frame->QWidgetAdapter::setParent(nullptr); // so ~Item doesn't delete it
121 frame->setLayoutItem(nullptr); // so Item is destroyed, as there's no refs to it
122 }
123
124 // Make some sanity checks:
125 if (!validateInputs(w, location, relativeToWidget, option))
126 return;
127
128 Layouting::Item *relativeTo = itemForFrame(relativeToWidget);
129 if (!relativeTo)
130 relativeTo = m_rootItem;
131
132 Layouting::Item *newItem = nullptr;
133
134 Frame::List frames = framesFrom(w);
135 unrefOldPlaceholders(frames);
136 auto dw = qobject_cast<DockWidgetBase *>(w);
137
138 if (frame) {
139 newItem = new Layouting::Item(this);
140 newItem->setGuestWidget(frame);
141 } else if (dw) {
142 newItem = new Layouting::Item(this);
144 newItem->setGuestWidget(frame);
145 frame->addWidget(dw, option);
146 } else if (auto ms = qobject_cast<MultiSplitter *>(w)) {
147 newItem = ms->m_rootItem;
148 newItem->setHostWidget(this);
149
150 if (FloatingWindow *fw = ms->floatingWindow()) {
151 newItem->setSize_recursive(fw->size());
152 }
153
154 delete ms;
155 } else {
156 // This doesn't happen but let's make coverity happy.
157 // Tests will fail if this is ever printed.
158 qWarning() << Q_FUNC_INFO << "Unknown widget added" << w;
159 return;
160 }
161
162 Q_ASSERT(!newItem->geometry().isEmpty());
163 Layouting::ItemBoxContainer::insertItemRelativeTo(newItem, relativeTo, location, option);
164
165 if (dw && option.startsHidden())
166 delete frame;
167}
168
169void MultiSplitter::addMultiSplitter(MultiSplitter *sourceMultiSplitter, Location location,
170 Frame *relativeTo,
171 InitialOption option)
172{
173 qCDebug(addwidget) << Q_FUNC_INFO << sourceMultiSplitter << location << relativeTo;
174 addWidget(sourceMultiSplitter, location, relativeTo, option);
175}
176
177QVector<Layouting::Separator *> MultiSplitter::separators() const
178{
179 return m_rootItem->separators_recursive();
180}
181
182int MultiSplitter::availableLengthForOrientation(Qt::Orientation orientation) const
183{
184 if (orientation == Qt::Vertical)
185 return availableSize().height();
186 else
187 return availableSize().width();
188}
189
190QSize MultiSplitter::availableSize() const
191{
192 return m_rootItem->availableSize();
193}
194
195void MultiSplitter::layoutEqually()
196{
197 if (!checkSanity())
198 return;
199
200 layoutEqually(m_rootItem);
201}
202
203void MultiSplitter::layoutEqually(Layouting::ItemBoxContainer *container)
204{
205 if (container) {
206 container->layoutEqually_recursive();
207 } else {
208 qWarning() << Q_FUNC_INFO << "null container";
209 }
210}
211
212void MultiSplitter::setRootItem(Layouting::ItemBoxContainer *root)
213{
214 LayoutWidget::setRootItem(root);
215 m_rootItem = root;
216}
217
218Layouting::ItemBoxContainer *MultiSplitter::rootItem() const
219{
220 return m_rootItem;
221}
222
223QRect MultiSplitter::rectForDrop(const WindowBeingDragged *wbd, Location location,
224 const Layouting::Item *relativeTo) const
225{
226 Layouting::Item item(nullptr);
227 if (!wbd)
228 return {};
229
230 item.setSize(wbd->size().boundedTo(wbd->maxSize()));
231 item.setMinSize(wbd->minSize());
232 item.setMaxSizeHint(wbd->maxSize());
233
234 Layouting::ItemBoxContainer *container = relativeTo ? relativeTo->parentBoxContainer()
235 : m_rootItem;
236
237 return container->suggestedDropRect(&item, relativeTo, location);
238}
239
240bool MultiSplitter::deserialize(const LayoutSaver::MultiSplitter &l)
241{
242 setRootItem(new Layouting::ItemBoxContainer(this));
243 return LayoutWidget::deserialize(l);
244}
245
246int MultiSplitter::numSideBySide_recursive(Qt::Orientation o) const
247{
248 return m_rootItem->numSideBySide_recursive(o);
249}
Application-wide config to tune certain behaviours of the framework.
The DockWidget base-class that's shared between QtWidgets and QtQuick stack.
A factory class for allowing the user to customize some internal widgets.
Class to save and restore dockwidget layouts.
The MainWindow base-class that's shared between QtWidgets and QtQuick stack.
An abstraction/wrapper around QWidget, QtQuickItem or anything else.
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
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...
Orientation
Struct describing the preferred dock widget size and visibility when adding it to a layout.

© 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