KDDockWidgets API Documentation  1.6
LayoutWidget.cpp
Go to the documentation of this file.
1 /*
2  This file is part of KDDockWidgets.
3 
4  SPDX-FileCopyrightText: 2020-2022 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"
17 #include "FrameworkWidgetFactory.h"
18 #include "MainWindowBase.h"
19 #include "Position_p.h"
20 #include "Utils_p.h"
21 
22 #include "multisplitter/Item_p.h"
23 
24 using namespace KDDockWidgets;
25 
26 
27 LayoutWidget::LayoutWidget(QWidgetOrQuick *parent)
28  : LayoutGuestWidget(parent)
29 {
30 }
31 
32 LayoutWidget::~LayoutWidget()
33 {
34  if (m_rootItem->hostWidget()->asQObject() == this)
35  delete m_rootItem;
36  DockRegistry::self()->unregisterLayout(this);
37 }
38 
39 bool LayoutWidget::isInMainWindow(bool honourNesting) const
40 {
41  return mainWindow(honourNesting) != nullptr;
42 }
43 
44 MainWindowBase *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 
68 FloatingWindow *LayoutWidget::floatingWindow() const
69 {
70  return qobject_cast<FloatingWindow *>(QWidgetAdapter::parentWidget());
71 }
72 
73 void 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 
83 QSize LayoutWidget::layoutMinimumSize() const
84 {
85  return m_rootItem->minSize();
86 }
87 
88 QSize LayoutWidget::layoutMaximumSizeHint() const
89 {
90  return m_rootItem->maxSizeHint();
91 }
92 
93 void 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 
101 QSize LayoutWidget::size() const
102 {
103  return m_rootItem->size();
104 }
105 
106 void LayoutWidget::clearLayout()
107 {
108  m_rootItem->clear();
109 }
110 
111 bool LayoutWidget::checkSanity() const
112 {
113  return m_rootItem->checkSanity();
114 }
115 
116 void LayoutWidget::dumpLayout() const
117 {
118  m_rootItem->dumpLayout();
119 }
120 
121 void 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 
140 void 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 
149 void 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 
158 const Layouting::Item::List LayoutWidget::items() const
159 {
160  return m_rootItem->items_recursive();
161 }
162 
163 bool LayoutWidget::containsItem(const Layouting::Item *item) const
164 {
165  return m_rootItem->contains_recursive(item);
166 }
167 
168 bool LayoutWidget::containsFrame(const Frame *frame) const
169 {
170  return itemForFrame(frame) != nullptr;
171 }
172 
173 int LayoutWidget::count() const
174 {
175  return m_rootItem->count_recursive();
176 }
177 
178 int LayoutWidget::visibleCount() const
179 {
180  return m_rootItem->visibleCount_recursive();
181 }
182 
183 int LayoutWidget::placeholderCount() const
184 {
185  return count() - visibleCount();
186 }
187 
188 Layouting::Item *LayoutWidget::itemForFrame(const Frame *frame) const
189 {
190  if (!frame)
191  return nullptr;
192 
193  return m_rootItem->itemForWidget(frame);
194 }
195 
196 DockWidgetBase::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 
206 Frame::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 
217 Frame::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 
232 void 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 
242 void 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 
251 bool 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 
273 void LayoutWidget::onLayoutRequest()
274 {
275  updateSizeConstraints();
276 }
277 
278 bool 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 
290 LayoutSaver::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 
306 void 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 }
QWidget
QSize
QHash::insert
QHash::iterator insert(const Key &key, const T &value)
MainWindowBase.h
The MainWindow base-class that's shared between QtWidgets and QtQuick stack.
KDDockWidgets::LayoutSaver::restoreInProgress
static bool restoreInProgress()
returns whether a restore (restoreLayout) is in progress
Definition: LayoutSaver.cpp:427
QCloseEvent
QEvent::isAccepted
bool isAccepted() const const
KDDockWidgets::LayoutGuestWidget
LayoutGuestWidget is the type that Item will host.
Definition: QWidgetAdapter.h:76
KDDockWidgets::Config::frameworkWidgetFactory
FrameworkWidgetFactory * frameworkWidgetFactory() const
getter for the framework widget factory
Definition: Config.cpp:145
QLatin1String
KDDockWidgets::FrameworkWidgetFactory::createFrame
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...
QVector::reserve
void reserve(int size)
Config.h
Application-wide config to tune certain behaviours of the framework.
QSize::expandedTo
QSize expandedTo(const QSize &otherSize) const const
KDDockWidgets::DockWidgetBase
The DockWidget base-class. DockWidget and DockWidgetBase are only split in two so we can share some c...
Definition: DockWidgetBase.h:61
KDDockWidgets
Definition: Config.cpp:37
QScopedValueRollback
KDDockWidgets::MainWindowBase
The MainWindow base-class. MainWindow and MainWindowBase are only split in two so we can share some c...
Definition: MainWindowBase.h:56
QVector
QHash
QEvent::accept
void accept()
KDDockWidgets::Config::self
static Config & self()
returns the singleton Config instance
Definition: Config.cpp:84
FrameworkWidgetFactory.h
A factory class for allowing the user to customize some internal widgets.

© 2019-2022 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 Thu Sep 15 2022 00:16:29 for KDDockWidgets API Documentation by doxygen 1.8.20