KDDockWidgets API Documentation  1.6
Frame.cpp
Go to the documentation of this file.
1 /*
2  This file is part of KDDockWidgets.
3 
4  SPDX-FileCopyrightText: 2019-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 
19 #include "Frame_p.h"
20 #include "Config.h"
21 #include "DockRegistry_p.h"
22 #include "DockWidgetBase_p.h"
23 #include "FloatingWindow_p.h"
24 #include "FrameworkWidgetFactory.h"
25 #include "LayoutSaver_p.h"
26 #include "LayoutWidget_p.h"
27 #include "Logging_p.h"
28 #include "Position_p.h"
29 #include "TabWidget_p.h"
30 #include "TitleBar_p.h"
31 #include "Utils_p.h"
32 #include "WidgetResizeHandler_p.h"
33 #include "MDILayoutWidget_p.h"
34 #include "DropAreaWithCentralFrame_p.h"
35 #include "multisplitter/Item_p.h"
36 
37 #include <QCloseEvent>
38 #include <QTimer>
39 
40 #define MARGIN_THRESHOLD 100
41 
42 static int s_dbg_numFrames = 0;
43 
44 using namespace KDDockWidgets;
45 
46 namespace KDDockWidgets {
47 static FrameOptions actualOptions(FrameOptions options)
48 {
50  options |= FrameOption_AlwaysShowsTabs;
51 
52  return options;
53 }
54 
55 static TabWidgetOptions tabWidgetOptions(FrameOptions options)
56 {
57  if (options & FrameOption_NonDockable) {
60  }
61 
62  return TabWidgetOption_None;
63 }
64 }
65 
66 Frame::Frame(QWidgetOrQuick *parent, FrameOptions options, int userType)
67  : LayoutGuestWidget(parent)
68  , FocusScope(this)
69  , m_tabWidget(Config::self().frameworkWidgetFactory()->createTabWidget(this, tabWidgetOptions(options)))
70  , m_titleBar(Config::self().frameworkWidgetFactory()->createTitleBar(this))
71  , m_options(actualOptions(options))
72  , m_userType(userType)
73 {
75  DockRegistry::self()->registerFrame(this);
76 
77  connect(this, &Frame::currentDockWidgetChanged, this, &Frame::updateTitleAndIcon);
78 
79  connect(m_tabWidget->asWidget(), SIGNAL(currentTabChanged(int)), // clazy:exclude=old-style-connect
80  this, SLOT(onCurrentTabChanged(int)));
81 
82  setLayoutWidget(qobject_cast<LayoutWidget *>(QWidgetAdapter::parentWidget()));
83  m_inCtor = false;
84 }
85 
86 Frame::~Frame()
87 {
88  m_inDtor = true;
90  if (m_layoutItem)
91  m_layoutItem->unref();
92 
93  delete m_resizeHandler;
94  m_resizeHandler = nullptr;
95 
96  DockRegistry::self()->unregisterFrame(this);
97 
98  // Run some disconnects() too, so we don't receive signals during destruction:
99  setLayoutWidget(nullptr);
100 }
101 
102 void Frame::updateTitleAndIcon()
103 {
104  if (DockWidgetBase *dw = currentDockWidget()) {
105  m_titleBar->setTitle(dw->title());
106  m_titleBar->setIcon(dw->icon());
107 
108  if (auto fw = floatingWindow()) {
109  if (fw->hasSingleFrame()) {
110  fw->updateTitleAndIcon();
111  }
112  }
113 
114  setObjectName(dw->uniqueName());
115 
116  } else if (currentTabIndex() != -1) {
117  qWarning() << Q_FUNC_INFO << "Invalid dock widget for frame." << currentTabIndex();
118  }
119 }
120 
121 void Frame::onDockWidgetTitleChanged()
122 {
123  updateTitleAndIcon();
124 
125  if (!m_inCtor) { // don't call pure virtual in ctor
126  if (auto dw = qobject_cast<DockWidgetBase *>(sender())) {
127  int index = indexOfDockWidget(dw);
128  renameTab(index, dw->title());
129  changeTabIcon(index, dw->icon(DockWidgetBase::IconPlace::TabBar));
130  }
131  }
132 }
133 
134 void Frame::addWidget(DockWidgetBase *dockWidget, InitialOption addingOption)
135 {
136  insertWidget(dockWidget, dockWidgetCount(), addingOption); // append
137 }
138 
139 void Frame::addWidget(Frame *frame, InitialOption addingOption)
140 {
141  if (frame->isEmpty()) {
142  qWarning() << "Frame::addWidget: frame is empty." << frame;
143  return;
144  }
145 
146  const auto &docks = frame->dockWidgets();
147  for (DockWidgetBase *dockWidget : docks)
148  addWidget(dockWidget, addingOption);
149 }
150 
151 void Frame::addWidget(FloatingWindow *floatingWindow, InitialOption addingOption)
152 {
153  Q_ASSERT(floatingWindow);
154  for (Frame *f : floatingWindow->frames())
155  addWidget(f, addingOption);
156 }
157 
158 void Frame::insertWidget(DockWidgetBase *dockWidget, int index, InitialOption addingOption)
159 {
160  Q_ASSERT(dockWidget);
161  if (containsDockWidget(dockWidget)) {
162  if (!dockWidget->isPersistentCentralDockWidget())
163  qWarning() << "Frame::addWidget dockWidget already exists. this=" << this << "; dockWidget=" << dockWidget;
164  return;
165  }
166  if (m_layoutItem)
167  dockWidget->d->addPlaceholderItem(m_layoutItem);
168 
169  const int originalCurrentIndex = currentIndex();
170 
171  insertDockWidget(dockWidget, index);
172 
173  if (addingOption.startsHidden()) {
174  dockWidget->close(); // Ensure closed
175  } else {
176  if (hasSingleDockWidget()) {
177  Q_EMIT currentDockWidgetChanged(dockWidget);
178  setObjectName(dockWidget->uniqueName());
179 
180  if (!m_layoutItem) {
181  // When adding the 1st dock widget of a fresh frame, let's give the frame the size
182  // of the dock widget, so that when adding it to the main window, the main window can
183  // use that size as the initial suggested size.
184  resize(dockWidget->size());
185  }
186  } else if (addingOption.preservesCurrentTab() && originalCurrentIndex != -1) {
187  setCurrentTabIndex(originalCurrentIndex);
188  }
189  }
190 
191  connect(dockWidget, &DockWidgetBase::titleChanged, this, &Frame::onDockWidgetTitleChanged);
192  connect(dockWidget, &DockWidgetBase::iconChanged, this, &Frame::onDockWidgetTitleChanged);
193 }
194 
195 void Frame::removeWidget(DockWidgetBase *dw)
196 {
197  disconnect(dw, &DockWidgetBase::titleChanged, this, &Frame::onDockWidgetTitleChanged);
198  disconnect(dw, &DockWidgetBase::iconChanged, this, &Frame::onDockWidgetTitleChanged);
199  removeWidget_impl(dw);
200 }
201 
202 FloatingWindow *Frame::detachTab(DockWidgetBase *dockWidget)
203 {
204  if (m_inCtor || m_inDtor)
205  return nullptr;
206 
207  dockWidget->d->saveTabIndex();
208 
209  QRect r = dockWidget->geometry();
210  removeWidget(dockWidget);
211 
212  auto newFrame = Config::self().frameworkWidgetFactory()->createFrame();
213  const QPoint globalPoint = mapToGlobal(QPoint(0, 0));
214  newFrame->addWidget(dockWidget);
215 
216  // We're potentially already dead at this point, as frames with 0 tabs auto-destruct. Don't access members from this point.
217 
218  auto floatingWindow = Config::self().frameworkWidgetFactory()->createFloatingWindow(newFrame);
219  r.moveTopLeft(globalPoint);
220  floatingWindow->setSuggestedGeometry(r, SuggestedGeometryHint_GeometryIsFromDocked);
221  floatingWindow->show();
222 
223  return floatingWindow;
224 }
225 
226 int Frame::indexOfDockWidget(const DockWidgetBase *dw)
227 {
228  if (m_inCtor || m_inDtor)
229  return -1;
230 
231  return indexOfDockWidget_impl(dw);
232 }
233 
234 int Frame::currentIndex() const
235 {
236  if (m_inCtor || m_inDtor)
237  return -1;
238 
239  return currentIndex_impl();
240 }
241 
242 void Frame::setCurrentTabIndex(int index)
243 {
244  if (m_inCtor || m_inDtor)
245  return;
246 
247  setCurrentTabIndex_impl(index);
248 }
249 
250 void Frame::setCurrentDockWidget(DockWidgetBase *dw)
251 {
252  if (m_inCtor || m_inDtor)
253  return;
254 
255  setCurrentDockWidget_impl(dw);
256 }
257 
258 void Frame::insertDockWidget(DockWidgetBase *dw, int index)
259 {
260  if (m_inCtor || m_inDtor)
261  return;
262 
263  insertDockWidget_impl(dw, index);
264 }
265 
266 DockWidgetBase *Frame::dockWidgetAt(int index) const
267 {
268  if (m_inCtor || m_inDtor)
269  return nullptr;
270 
271  return dockWidgetAt_impl(index);
272 }
273 
274 DockWidgetBase *Frame::currentDockWidget() const
275 {
276  if (m_inCtor || m_inDtor)
277  return nullptr;
278 
279  return currentDockWidget_impl();
280 }
281 
282 int Frame::dockWidgetCount() const
283 {
284  if (m_inCtor || m_inDtor)
285  return 0;
286 
287  return m_tabWidget->numDockWidgets();
288 }
289 
290 void Frame::onDockWidgetCountChanged()
291 {
292  qCDebug(docking) << "Frame::onDockWidgetCountChanged:" << this << "; widgetCount=" << dockWidgetCount();
293  if (isEmpty() && !isCentralFrame()) {
294  scheduleDeleteLater();
295  } else {
296  updateTitleBarVisibility();
297 
298  // We don't really keep track of the state, so emit even if the visibility didn't change. No biggie.
299  if (!(m_options & FrameOption_AlwaysShowsTabs))
300  Q_EMIT hasTabsVisibleChanged();
301 
302  const DockWidgetBase::List docks = dockWidgets();
303  for (DockWidgetBase *dock : docks)
304  dock->d->updateFloatAction();
305  }
306 
307  Q_EMIT numDockWidgetsChanged();
308 }
309 
310 void Frame::onCurrentTabChanged(int index)
311 {
312  if (index != -1) {
313  if (auto dock = dockWidgetAt(index)) {
314  Q_EMIT currentDockWidgetChanged(dock);
315  } else {
316  qWarning() << "dockWidgetAt" << index << "returned nullptr" << this;
317  }
318  }
319 }
320 
321 void Frame::isFocusedChangedCallback()
322 {
323  Q_EMIT isFocusedChanged();
324 }
325 
326 void Frame::focusedWidgetChangedCallback()
327 {
328  Q_EMIT focusedWidgetChanged();
329 }
330 
331 void Frame::updateTitleBarVisibility()
332 {
333  if (m_updatingTitleBar || m_beingDeleted) {
334  // To break a cyclic dependency
335  return;
336  }
337 
338  QScopedValueRollback<bool> guard(m_updatingTitleBar, true);
339 
340  bool visible = false;
341  if (isCentralFrame()) {
342  visible = false;
343  } else if ((Config::self().flags() & Config::Flag_HideTitleBarWhenTabsVisible) && hasTabsVisible()) {
344  visible = false;
345  } else if (FloatingWindow *fw = floatingWindow()) {
346  // If there's nested frames then show each Frame's title bar
347  visible = !fw->hasSingleFrame();
348  } else if (isMDIWrapper()) {
349  auto dropArea = this->mdiDropAreaWrapper();
350  visible = !dropArea->hasSingleFrame();
351  } else {
352  visible = true;
353  }
354 
355  const bool wasVisible = m_titleBar->isVisible();
356  m_titleBar->setVisible(visible);
357 
358  if (wasVisible != visible) {
359  Q_EMIT actualTitleBarChanged();
360  for (auto dw : dockWidgets())
361  Q_EMIT dw->actualTitleBarChanged();
362  }
363 
364  if (auto fw = floatingWindow()) {
365  // Update the floating window which might be using Flag_HideTitleBarWhenTabsVisible
366  // In that case it might not show title bar depending on the number of tabs that the frame has
367  fw->updateTitleBarVisibility();
368  }
369 }
370 
371 void Frame::updateFloatingActions()
372 {
373  const QVector<DockWidgetBase *> widgets = dockWidgets();
374  for (DockWidgetBase *dw : widgets)
375  dw->d->updateFloatAction();
376 }
377 
378 bool Frame::containsMouse(QPoint globalPos) const
379 {
380  return QWidgetAdapter::rect().contains(KDDockWidgets::QWidgetAdapter::mapFromGlobal(globalPos));
381 }
382 
383 TitleBar *Frame::titleBar() const
384 {
385  return m_titleBar;
386 }
387 
388 TitleBar *Frame::actualTitleBar() const
389 {
390  if (FloatingWindow *fw = floatingWindow()) {
391  // If there's nested frames then show each Frame's title bar
392  if (fw->hasSingleFrame())
393  return fw->titleBar();
394  } else if (auto mdiDropArea = mdiDropAreaWrapper()) {
395  if (mdiDropArea->hasSingleFrame()) {
396  return mdiFrame()->titleBar();
397  }
398  }
399 
400  return titleBar();
401 }
402 
403 QString Frame::title() const
404 {
405  return m_titleBar->title();
406 }
407 
408 QIcon Frame::icon() const
409 {
410  return m_titleBar->icon();
411 }
412 
413 const DockWidgetBase::List Frame::dockWidgets() const
414 {
415  if (m_inCtor || m_inDtor)
416  return {};
417 
418  DockWidgetBase::List dockWidgets;
419  const int count = dockWidgetCount();
420  dockWidgets.reserve(count);
421  for (int i = 0; i < count; ++i)
422  dockWidgets << dockWidgetAt(i);
423 
424  return dockWidgets;
425 }
426 
427 bool Frame::containsDockWidget(DockWidgetBase *dockWidget) const
428 {
429  const int count = dockWidgetCount();
430  for (int i = 0, e = count; i != e; ++i) {
431  if (dockWidget == dockWidgetAt(i))
432  return true;
433  }
434  return false;
435 }
436 
437 FloatingWindow *Frame::floatingWindow() const
438 {
439  // Returns the first FloatingWindow* parent in the hierarchy.
440  // However, if there's a MainWindow in the hierarchy it stops, which can
441  // happen with nested main windows.
442 
443  auto p = QWidgetAdapter::parentWidget();
444  while (p) {
445  if (qobject_cast<KDDockWidgets::MainWindowBase *>(p))
446  return nullptr;
447 
448  if (auto fw = qobject_cast<FloatingWindow *>(p))
449  return fw;
450 
451  if (p == window()) {
452  // We stop at the window. (top-levels can have parent, but we're not interested)
453  return nullptr;
454  }
455 
456  p = p->parentWidget();
457  }
458 
459  return nullptr;
460 }
461 
462 void Frame::restoreToPreviousPosition()
463 {
464  if (hasSingleDockWidget()) {
465  qWarning() << Q_FUNC_INFO << "Invalid usage, there's no tabs";
466  return;
467  }
468 
469  if (!m_layoutItem) {
470  qCDebug(placeholder) << Q_FUNC_INFO << "There's no previous position known";
471  return;
472  }
473 
474  if (!m_layoutItem->isPlaceholder()) {
475  // Maybe in this case just fold the frame into the placeholder, which probably has other dockwidgets which were added meanwhile. TODO
476  qCDebug(placeholder) << Q_FUNC_INFO << "Previous position isn't a placeholder";
477  return;
478  }
479 
480  m_layoutItem->restore(this);
481 }
482 
483 int Frame::currentTabIndex() const
484 {
485  return currentIndex();
486 }
487 
488 void Frame::onCloseEvent(QCloseEvent *e)
489 {
490  qCDebug(closing) << "Frame::closeEvent";
491  e->accept(); // Accepted by default (will close unless ignored)
492  const DockWidgetBase::List docks = dockWidgets();
493  for (DockWidgetBase *dock : docks) {
494  qApp->sendEvent(dock, e);
495  if (!e->isAccepted())
496  break; // Stop when the first dockwidget prevents closing
497  }
498 }
499 
500 bool Frame::anyNonClosable() const
501 {
502  for (auto dw : dockWidgets()) {
503  if ((dw->options() & DockWidgetBase::Option_NotClosable) && !DockRegistry::self()->isProcessingAppQuitEvent())
504  return true;
505  }
506 
507  return false;
508 }
509 
510 bool Frame::anyNonDockable() const
511 {
512  for (auto dw : dockWidgets()) {
513  if (dw->options() & DockWidgetBase::Option_NotDockable)
514  return true;
515  }
516 
517  return false;
518 }
519 
520 void Frame::onDockWidgetShown(DockWidgetBase *w)
521 {
522  if (hasSingleDockWidget() && containsDockWidget(w)) { // We have to call contains because it might be being in process of being reparented
523  if (!QWidgetAdapter::isVisible()) {
524  qCDebug(hiding) << "Widget" << w << " was shown, we're="
525  << "; visible="
526  << QWidgetAdapter::isVisible();
527  QWidgetAdapter::setVisible(true);
528  }
529  }
530 }
531 
532 void Frame::onDockWidgetHidden(DockWidgetBase *w)
533 {
534  if (!isCentralFrame() && hasSingleDockWidget() && containsDockWidget(w)) { // We have to call contains because it might be being in process of being reparented
535  if (QWidgetAdapter::isVisible()) {
536  qCDebug(hiding) << "Widget" << w << " was hidden, we're="
537  << "; visible=" << QWidgetAdapter::isVisible()
538  << "; dockWidgets=" << dockWidgets();
539  QWidgetAdapter::setVisible(false);
540  }
541  }
542 }
543 
544 void Frame::setLayoutItem(Layouting::Item *item)
545 {
546  if (item == m_layoutItem)
547  return;
548 
549  if (m_layoutItem)
550  m_layoutItem->unref();
551 
552  if (item)
553  item->ref();
554 
555  m_layoutItem = item;
556  if (item) {
557  for (DockWidgetBase *dw : dockWidgets())
558  dw->d->addPlaceholderItem(item);
559  } else {
560  for (DockWidgetBase *dw : dockWidgets())
561  dw->d->lastPosition()->removePlaceholders();
562  }
563 }
564 
565 Layouting::Item *Frame::layoutItem() const
566 {
567  return m_layoutItem;
568 }
569 
570 int Frame::dbg_numFrames()
571 {
572  return s_dbg_numFrames;
573 }
574 
575 bool Frame::beingDeletedLater() const
576 {
577  return m_beingDeleted;
578 }
579 
580 bool Frame::hasTabsVisible() const
581 {
582  if (m_beingDeleted)
583  return false;
584 
585  return alwaysShowsTabs() || dockWidgetCount() > 1;
586 }
587 
588 QStringList Frame::affinities() const
589 {
590  if (isEmpty()) {
591  if (auto m = mainWindow())
592  return m->affinities();
593  return {};
594  } else {
595  return dockWidgetAt(0)->affinities();
596  }
597 }
598 
599 void Frame::setLayoutWidget(LayoutWidget *dt)
600 {
601  if (dt == m_layoutWidget)
602  return;
603 
604  const bool wasInMainWindow = dt && isInMainWindow();
605  const bool wasMDI = isMDI();
606  if (m_layoutWidget)
607  disconnect(m_visibleWidgetCountChangedConnection);
608 
609  m_layoutWidget = dt;
610  delete m_resizeHandler;
611  m_resizeHandler = nullptr;
612 
613  if (m_layoutWidget) {
614  if (isMDI())
615  m_resizeHandler = new WidgetResizeHandler(WidgetResizeHandler::EventFilterMode::Global, WidgetResizeHandler::WindowMode::MDI, this);
616 
617  // We keep the connect result so we don't dereference m_layoutWidget at shutdown
618  m_visibleWidgetCountChangedConnection =
619  connect(m_layoutWidget, &LayoutWidget::visibleWidgetCountChanged, this,
620  &Frame::updateTitleBarVisibility);
621  updateTitleBarVisibility();
622  if (wasInMainWindow != isInMainWindow())
623  Q_EMIT isInMainWindowChanged();
624  }
625 
626  if (wasMDI != isMDI())
627  Q_EMIT isMDIChanged();
628 }
629 
630 bool Frame::isTheOnlyFrame() const
631 {
632  return m_layoutWidget && m_layoutWidget->visibleCount() == 1;
633 }
634 
635 bool Frame::isOverlayed() const
636 {
637  return m_options & FrameOption_IsOverlayed;
638 }
639 
640 void Frame::unoverlay()
641 {
642  m_options &= ~FrameOption_IsOverlayed;
643 }
644 
645 bool Frame::isFloating() const
646 {
647  if (isInMainWindow() || isMDI())
648  return false;
649 
650  return isTheOnlyFrame();
651 }
652 
653 bool Frame::isInFloatingWindow() const
654 {
655  return floatingWindow() != nullptr;
656 }
657 
658 bool Frame::isInMainWindow() const
659 {
660  return mainWindow() != nullptr;
661 }
662 
663 bool Frame::event(QEvent *e)
664 {
665  if (e->type() == QEvent::ParentChange) {
666  if (auto layoutWidget = qobject_cast<LayoutWidget *>(QWidgetAdapter::parentWidget())) {
667  setLayoutWidget(layoutWidget);
668  } else {
669  setLayoutWidget(nullptr);
670  }
671  }
672 
673  return QWidgetAdapter::event(e);
674 }
675 
676 Frame *Frame::deserialize(const LayoutSaver::Frame &f)
677 {
678  if (!f.isValid())
679  return nullptr;
680 
681  const FrameOptions options = FrameOptions(f.options);
682  Frame *frame = nullptr;
683  const bool isPersistentCentralFrame = options & FrameOption::FrameOption_IsCentralFrame;
684  auto widgetFactory = Config::self().frameworkWidgetFactory();
685 
686  if (isPersistentCentralFrame) {
687  // Don't create a new Frame if we're restoring the Persistent Central frame (the one created
688  // by MainWindowOption_HasCentralFrame). It already exists.
689 
690  if (f.mainWindowUniqueName.isEmpty()) {
691  // Can happen with older serialization formats
692  qWarning() << Q_FUNC_INFO << "Frame is the persistent central frame but doesn't have"
693  << "an associated window name";
694  } else {
695  if (MainWindowBase *mw = DockRegistry::self()->mainWindowByName(f.mainWindowUniqueName)) {
696  frame = mw->dropArea()->m_centralFrame;
697  if (!frame) {
698  // Doesn't happen...
699  qWarning() << "Main window" << f.mainWindowUniqueName << "doesn't have central frame";
700  }
701  } else {
702  // Doesn't happen...
703  qWarning() << Q_FUNC_INFO << "Couldn't find main window"
704  << f.mainWindowUniqueName;
705  }
706  }
707  }
708 
709  if (!frame)
710  frame = widgetFactory->createFrame(/*parent=*/nullptr, options);
711 
712  frame->setObjectName(f.objectName);
713 
714  for (const auto &savedDock : qAsConst(f.dockWidgets)) {
715  if (DockWidgetBase *dw = DockWidgetBase::deserialize(savedDock)) {
716  frame->addWidget(dw);
717  }
718  }
719 
720  frame->setCurrentTabIndex(f.currentTabIndex);
721  frame->QWidgetAdapter::setGeometry(f.geometry);
722 
723  return frame;
724 }
725 
726 LayoutSaver::Frame Frame::serialize() const
727 {
728  LayoutSaver::Frame frame;
729  frame.isNull = false;
730 
731  const DockWidgetBase::List docks = dockWidgets();
732 
733  frame.objectName = objectName();
734  frame.geometry = QWidgetAdapter::geometry();
735  frame.options = options();
736  frame.currentTabIndex = currentTabIndex();
737  frame.id = id(); // for coorelation purposes
738 
739  if (MainWindowBase *mw = mainWindow())
740  frame.mainWindowUniqueName = mw->uniqueName();
741 
742  for (DockWidgetBase *dock : docks)
743  frame.dockWidgets.push_back(dock->d->serialize());
744 
745  return frame;
746 }
747 
748 void Frame::scheduleDeleteLater()
749 {
750  qCDebug(creation) << Q_FUNC_INFO << this;
751  m_beingDeleted = true;
752  QTimer::singleShot(0, this, [this] {
753  // Can't use deleteLater() here due to QTBUG-83030 (deleteLater() never delivered if triggered by a sendEvent() before event loop starts)
754  delete this;
755  });
756 }
757 
758 QSize Frame::dockWidgetsMinSize() const
759 {
760  QSize size = Layouting::Item::hardcodedMinimumSize;
761  for (DockWidgetBase *dw : dockWidgets())
763 
764  return size;
765 }
766 
767 QSize Frame::biggestDockWidgetMaxSize() const
768 {
769  QSize size = Layouting::Item::hardcodedMaximumSize;
770  for (DockWidgetBase *dw : dockWidgets()) {
771  const QSize dwMax = widgetMaxSize(dw);
772  if (size == Layouting::Item::hardcodedMaximumSize) {
773  size = dwMax;
774  continue;
775  }
776 
777  const bool hasMaxSize = dwMax != Layouting::Item::hardcodedMaximumSize;
778  if (hasMaxSize)
779  size = dw->maximumSize().expandedTo(size);
780  }
781 
782  // Interpret 0 max-size as not having one too.
783  if (size.width() == 0)
784  size.setWidth(Layouting::Item::hardcodedMaximumSize.width());
785  if (size.height() == 0)
786  size.setHeight(Layouting::Item::hardcodedMaximumSize.height());
787 
788  return size;
789 }
790 
791 QRect Frame::dragRect() const
792 {
793  QRect rect;
794  if (m_titleBar->isVisible()) {
795  rect = m_titleBar->rect();
796  rect.moveTopLeft(m_titleBar->mapToGlobal(QPoint(0, 0)));
797  }
798 
799  return rect;
800 }
801 
802 MainWindowBase *Frame::mainWindow() const
803 {
804  return m_layoutWidget ? m_layoutWidget->mainWindow() : nullptr;
805 }
806 
807 TabWidget *Frame::tabWidget() const
808 {
809  return m_tabWidget;
810 }
811 
813 bool Frame::allDockWidgetsHave(DockWidgetBase::Option option) const
814 {
815  const DockWidgetBase::List docks = dockWidgets();
816  return std::all_of(docks.cbegin(), docks.cend(), [option](DockWidgetBase *dw) {
817  return dw->options() & option;
818  });
819 }
820 
822 bool Frame::anyDockWidgetsHas(DockWidgetBase::Option option) const
823 {
824  const DockWidgetBase::List docks = dockWidgets();
825  return std::any_of(docks.cbegin(), docks.cend(), [option](DockWidgetBase *dw) {
826  return dw->options() & option;
827  });
828 }
829 
830 bool Frame::allDockWidgetsHave(DockWidgetBase::LayoutSaverOption option) const
831 {
832  const DockWidgetBase::List docks = dockWidgets();
833  return std::all_of(docks.cbegin(), docks.cend(), [option](DockWidgetBase *dw) {
834  return dw->layoutSaverOptions() & option;
835  });
836 }
837 
838 bool Frame::anyDockWidgetsHas(DockWidgetBase::LayoutSaverOption option) const
839 {
840  const DockWidgetBase::List docks = dockWidgets();
841  return std::any_of(docks.cbegin(), docks.cend(), [option](DockWidgetBase *dw) {
842  return dw->layoutSaverOptions() & option;
843  });
844 }
845 
846 void Frame::setAllowedResizeSides(CursorPositions sides)
847 {
848  if (sides) {
849  delete m_resizeHandler;
850  m_resizeHandler = new WidgetResizeHandler(WidgetResizeHandler::EventFilterMode::Global, WidgetResizeHandler::WindowMode::MDI, this);
851  m_resizeHandler->setAllowedResizeSides(sides);
852  } else {
853  delete m_resizeHandler;
854  m_resizeHandler = nullptr;
855  }
856 }
857 
858 bool Frame::isMDI() const
859 {
860  return mdiLayoutWidget() != nullptr;
861 }
862 
863 bool Frame::isMDIWrapper() const
864 {
865  return mdiDropAreaWrapper() != nullptr;
866 }
867 
868 Frame *Frame::mdiFrame() const
869 {
870  if (auto dwWrapper = mdiDockWidgetWrapper()) {
871  return dwWrapper->d->frame();
872  }
873 
874  return nullptr;
875 }
876 
877 DockWidgetBase *Frame::mdiDockWidgetWrapper() const
878 {
879  if (auto dropArea = mdiDropAreaWrapper()) {
880  return qobject_cast<DockWidgetBase *>(dropArea->QWidgetAdapter::parent());
881  }
882 
883  return nullptr;
884 }
885 
886 DropArea *Frame::mdiDropAreaWrapper() const
887 {
888  auto dropArea = qobject_cast<DropArea *>(QWidgetAdapter::parent());
889  if (dropArea && dropArea->isMDIWrapper())
890  return dropArea;
891  return nullptr;
892 }
893 
894 MDILayoutWidget *Frame::mdiLayoutWidget() const
895 {
896  return qobject_cast<MDILayoutWidget *>(m_layoutWidget);
897 }
898 
899 bool Frame::hasNestedMDIDockWidgets() const
900 {
901  if (!isMDI() || dockWidgetCount() == 0)
902  return false;
903 
904  if (dockWidgetCount() != 1) {
905  qWarning() << Q_FUNC_INFO << "Expected a single dock widget wrapper as frame child";
906  return false;
907  }
908 
909  return dockWidgetAt(0)->d->isMDIWrapper();
910 }
911 
912 int Frame::userType() const
913 {
914  return m_userType;
915 }
916 
917 WidgetResizeHandler *Frame::resizeHandler() const
918 {
919  return m_resizeHandler;
920 }
KDDockWidgets::TabWidgetOption_None
@ TabWidgetOption_None
Definition: KDDockWidgets.h:285
QRect::moveTopLeft
void moveTopLeft(const QPoint &position)
Layouting::Widget::widgetMinSize
static QSize widgetMinSize(const T *w)
Definition: Widget.h:152
QEvent::ParentChange
ParentChange
QRect
KDDockWidgets::InitialOption
Struct describing the preferred dock widget size and visibility when adding it to a layout.
Definition: KDDockWidgets.h:101
QTimer::singleShot
singleShot
QVector::cend
QVector::const_iterator cend() const const
QWidget
KDDockWidgets::DockWidgetBase::uniqueName
QString uniqueName
Definition: DockWidgetBase.h:65
QSize
KDDockWidgets::DockWidgetBase::isPersistentCentralDockWidget
bool isPersistentCentralDockWidget() const
Returns whether this dock widget is the main window persistent central widget This only applies when ...
Definition: DockWidgetBase.cpp:950
QSize::width
int width() const const
KDDockWidgets::InitialOption::preservesCurrentTab
bool preservesCurrentTab() const
Definition: KDDockWidgets.h:134
QSize::setWidth
void setWidth(int width)
KDDockWidgets::FocusScope
Allows to implement a similar functionality to QtQuick's FocusScope item, in QtWidgets.
Definition: FocusScope.h:28
KDDockWidgets::FrameOption_IsOverlayed
@ FrameOption_IsOverlayed
Definition: KDDockWidgets.h:277
QCloseEvent
QSize::height
int height() const const
QString
QEvent::isAccepted
bool isAccepted() const const
QVector::cbegin
QVector::const_iterator cbegin() const const
KDDockWidgets::FrameOption_AlwaysShowsTabs
@ FrameOption_AlwaysShowsTabs
Definition: KDDockWidgets.h:275
KDDockWidgets::DockWidgetBase::LayoutSaverOption
LayoutSaverOption
Options which will affect LayoutSaver save/restore.
Definition: DockWidgetBase.h:87
KDDockWidgets::FrameOption_NonDockable
@ FrameOption_NonDockable
Definition: KDDockWidgets.h:278
KDDockWidgets::Config
Singleton to allow to choose certain behaviours of the framework.
Definition: Config.h:75
KDDockWidgets::LayoutGuestWidget
LayoutGuestWidget is the type that Item will host.
Definition: QWidgetAdapter.h:76
KDDockWidgets::DockWidgetBase::actualTitleBarChanged
void actualTitleBarChanged()
Emitted when the title bar that serves this dock widget changes.
QIcon
QVector::reserve
void reserve(int size)
Config.h
Application-wide config to tune certain behaviours of the framework.
KDDockWidgets::Config::Flag_AlwaysShowTabs
@ Flag_AlwaysShowTabs
Always show tabs, even if there's only one,.
Definition: Config.h:93
QSize::expandedTo
QSize expandedTo(const QSize &otherSize) const const
QEvent::type
QEvent::Type type() const const
QEvent
KDDockWidgets::InitialOption::startsHidden
bool startsHidden() const
Definition: KDDockWidgets.h:129
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::FrameOption_IsCentralFrame
@ FrameOption_IsCentralFrame
Definition: KDDockWidgets.h:276
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
s_dbg_numFrames
static int s_dbg_numFrames
Definition: Frame.cpp:42
KDDockWidgets::DockWidgetBase::Option
Option
DockWidget options to pass at construction time.
Definition: DockWidgetBase.h:74
KDDockWidgets::tabWidgetOptions
static TabWidgetOptions tabWidgetOptions(FrameOptions options)
Definition: Frame.cpp:55
KDDockWidgets::DockWidgetBase::options
KDDockWidgets::DockWidgetBase::Options options
Definition: DockWidgetBase.h:69
KDDockWidgets::SuggestedGeometryHint_GeometryIsFromDocked
@ SuggestedGeometryHint_GeometryIsFromDocked
Definition: KDDockWidgets.h:202
KDDockWidgets::TabWidgetOption_DocumentMode
@ TabWidgetOption_DocumentMode
Definition: KDDockWidgets.h:286
QSize::setHeight
void setHeight(int height)
KDDockWidgets::actualOptions
static FrameOptions actualOptions(FrameOptions options)
Definition: Frame.cpp:47
QPoint
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.
QStringList

© 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:28 for KDDockWidgets API Documentation by doxygen 1.8.20