KDDockWidgets API Documentation  1.6
DockWidgetBase.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 
12 #include "DockWidgetBase.h"
13 #include "private/DockWidgetBase_p.h"
14 #include "private/DockRegistry_p.h"
15 #include "private/FloatingWindow_p.h"
16 #include "private/Frame_p.h"
17 #include "private/LayoutSaver_p.h"
18 #include "private/Logging_p.h"
19 #include "private/MDILayoutWidget_p.h"
20 #include "private/SideBar_p.h"
21 #include "private/TitleBar_p.h"
22 #include "private/Utils_p.h"
23 #include "private/WindowBeingDragged_p.h"
24 #include "private/Position_p.h"
25 
26 #include "Config.h"
27 #include "FrameworkWidgetFactory.h"
28 
29 #include <QEvent>
30 #include <QCloseEvent>
31 #include <QTimer>
32 #include <QScopedValueRollback>
33 
41 using namespace KDDockWidgets;
42 
43 DockWidgetBase::DockWidgetBase(const QString &name, Options options,
44  LayoutSaverOptions layoutSaverOptions)
45  : QWidgetAdapter(nullptr, Qt::Tool)
46  , d(new Private(name, options, layoutSaverOptions, this))
47 {
48  d->init();
49  DockRegistry::self()->registerDockWidget(this);
50 
51  if (name.isEmpty())
52  qWarning() << Q_FUNC_INFO << "Name can't be null";
53 
54  setAttribute(Qt::WA_PendingMoveEvent, false);
55 }
56 
58 {
59  DockRegistry::self()->unregisterDockWidget(this);
60  delete d;
61 }
62 
64 {
65  if (other == this) {
66  qWarning() << Q_FUNC_INFO << "Refusing to add dock widget into itself" << other;
67  return;
68  }
69 
70  if (!other) {
71  qWarning() << Q_FUNC_INFO << "dock widget is null";
72  return;
73  }
74 
75  if (!DockRegistry::self()->affinitiesMatch(other->affinities(), d->affinities)) {
76  qWarning() << Q_FUNC_INFO << "Refusing to dock widget with incompatible affinity."
77  << other->affinities() << affinities();
78  return;
79  }
80 
82  qWarning() << Q_FUNC_INFO << "Refusing to dock non-dockable widget" << other;
83  return;
84  }
85 
87  qWarning() << Q_FUNC_INFO << "Not supported with MainWindowOption_HasCentralWidget."
88  << "MainWindowOption_HasCentralWidget can only have 1 widget in the center."
89  << "Use MainWindowOption_HasCentralFrame instead, which is similar but supports tabbing.";
90  return;
91  }
92 
93  Frame *frame = d->frame();
94 
95  if (frame) {
96  if (frame->containsDockWidget(other)) {
97  qWarning() << Q_FUNC_INFO << "Already contains" << other;
98  return;
99  }
100  } else {
101  if (isWindow()) {
102  // Doesn't have a frame yet
103  d->morphIntoFloatingWindow();
104  frame = d->frame();
105  } else {
106  // Doesn't happen
107  qWarning() << Q_FUNC_INFO << "null frame";
108  return;
109  }
110  }
111 
112  other->setParent(nullptr);
113  frame->addWidget(other, option);
114 }
115 
117  Location location,
118  DockWidgetBase *relativeTo,
119  InitialOption initialOption)
120 {
121  if (auto mainWindow = qobject_cast<MainWindowBase *>(window())) {
122  // It's inside a main window. Simply use the main window API.
123  mainWindow->addDockWidget(other, location, relativeTo, initialOption);
124  return;
125  }
126 
127  if (!DockRegistry::self()->affinitiesMatch(other->affinities(), d->affinities)) {
128  qWarning() << Q_FUNC_INFO << "Refusing to dock widget with incompatible affinity."
129  << other->affinities() << affinities();
130  return;
131  }
132 
134  qWarning() << Q_FUNC_INFO << "Refusing to dock non-dockable widget" << other;
135  return;
136  }
137 
138  if (isWindow())
139  d->morphIntoFloatingWindow();
140 
141  if (auto fw = floatingWindow()) {
142  fw->addDockWidget(other, location, relativeTo, initialOption);
143  } else {
144  qWarning() << Q_FUNC_INFO << "Couldn't find floating nested window";
145  }
146 }
147 
149 {
150  if (w == d->widget)
151  return;
152 
153  if (d->widget) {
154  // Unparent the old widget, we're giving back ownership
155  d->widget->setParent(nullptr);
156  }
157 
158  d->widget = w;
159  if (w)
160  setSizePolicy(w->sizePolicy());
161 
162  Q_EMIT widgetChanged(w);
163 }
164 
166 {
167  return d->widget;
168 }
169 
171 {
172  if (isWindow())
173  return true;
174 
175  auto fw = floatingWindow();
176  return fw && fw->hasSingleDockWidget();
177 }
178 
180 {
181  const bool alreadyFloating = isFloating();
182 
183  if (floats == alreadyFloating)
184  return true; // Nothing to do
185 
186  if (!floats && (Config::self().internalFlags() & Config::InternalFlag_DontShowWhenUnfloatingHiddenWindow) && !isVisible()) {
187  // Mimics behaviour of QDockWidget, which you might need during porting.
188  // Not something we suggest though. For KDDW, setFloating(false) means dock, and that implies showing.
189  return false;
190  }
191 
192  if (floats && isPersistentCentralDockWidget())
193  return false;
194 
195  if (floats) {
196  d->saveTabIndex();
197  if (isTabbed()) {
198  auto frame = d->frame();
199  if (!frame) {
200  qWarning() << "DockWidget::setFloating: Tabbed but no frame exists"
201  << this;
202  Q_ASSERT(false);
203  return false;
204  }
205 
206  frame->detachTab(this);
207  } else {
208  titleBar()->makeWindow();
209  }
210 
211  auto lastGeo = d->lastPosition()->lastFloatingGeometry();
212  if (lastGeo.isValid()) {
213  if (auto fw = floatingWindow())
214  fw->setSuggestedGeometry(lastGeo, SuggestedGeometryHint_PreserveCenter);
215  }
216  return true;
217  } else {
218  d->saveLastFloatingGeometry();
219  return d->restoreToPreviousPosition();
220  }
221 }
222 
224 {
225  return d->toggleAction;
226 }
227 
229 {
230  return d->floatAction;
231 }
232 
234 {
235  return d->name;
236 }
237 
239 {
240  if (d->isMDIWrapper()) {
241  // It's just a wrapper to help implementing Option_MDINestable. Return the title of the real dock widget we're hosting.
242  auto dropAreaGuest = qobject_cast<DropArea *>(widget());
243  Q_ASSERT(dropAreaGuest);
244  if (dropAreaGuest->hasSingleFrame()) {
245  return dropAreaGuest->frames().constFirst()->title();
246  } else {
247  return qApp->applicationName();
248  }
249  }
250 
251  return d->title;
252 }
253 
255 {
256  if (title != d->title) {
257  d->title = title;
258  d->updateTitle();
259  Q_EMIT titleChanged(title);
260  }
261 }
262 
264 {
265  if (Frame *f = d->frame())
266  return f->QWidgetAdapter::geometry();
267 
268  // Means the dock widget isn't visible. Just fallback to its own geometry
269  return QWidgetAdapter::geometry();
270 }
271 
272 DockWidgetBase::Options DockWidgetBase::options() const
273 {
274  return d->options;
275 }
276 
277 DockWidgetBase::LayoutSaverOptions DockWidgetBase::layoutSaverOptions() const
278 {
279  return d->layoutSaverOptions;
280 }
281 
282 void DockWidgetBase::setOptions(Options options)
283 {
284  if ((d->options & Option_NotDockable) != (options & Option_NotDockable)) {
285  qWarning() << Q_FUNC_INFO << "Option_NotDockable not allowed to change. Pass via ctor only.";
286  return;
287  }
288 
289  if (options != d->options) {
290  d->options = options;
291  Q_EMIT optionsChanged(options);
292  if (auto tb = titleBar())
293  tb->updateButtons();
294  }
295 }
296 
298 {
299  if (Frame *frame = d->frame()) {
300  return frame->alwaysShowsTabs() || frame->dockWidgetCount() > 1;
301  } else {
302  if (!isFloating())
303  qWarning() << "DockWidget::isTabbed() Couldn't find any tab widget.";
304  return false;
305  }
306 }
307 
309 {
310  if (Frame *frame = d->frame()) {
311  return frame->currentIndex() == frame->indexOfDockWidget(const_cast<DockWidgetBase *>(this));
312  } else {
313  return true;
314  }
315 }
316 
318 {
319  if (Frame *frame = d->frame())
320  frame->setCurrentDockWidget(this);
321 }
322 
324 {
325  if (Frame *frame = d->frame())
326  return frame->indexOfDockWidget(this);
327 
328  return 0;
329 }
330 
332 {
333  if (Frame *frame = d->frame())
334  return frame->currentTabIndex();
335 
336  return 0;
337 }
338 
339 void DockWidgetBase::setIcon(const QIcon &icon, IconPlaces places)
340 {
341  if (places & IconPlace::TitleBar)
342  d->titleBarIcon = icon;
343 
344  if (places & IconPlace::TabBar)
345  d->tabBarIcon = icon;
346 
347  if (places & IconPlace::ToggleAction)
348  d->toggleAction->setIcon(icon);
349 
350  Q_EMIT iconChanged();
351 }
352 
354 {
355  if (place == IconPlace::TitleBar)
356  return d->titleBarIcon;
357 
358  if (place == IconPlace::TabBar)
359  return d->tabBarIcon;
360 
361  if (place == IconPlace::ToggleAction)
362  return d->toggleAction->icon();
363 
364  return {};
365 }
366 
368 {
369  d->forceClose();
370 }
371 
372 TitleBar *DockWidgetBase::titleBar() const
373 {
374  if (Frame *f = d->frame())
375  return f->actualTitleBar();
376 
377  return nullptr;
378 }
379 
381 {
382  return d->toggleAction->isChecked();
383 }
384 
386 {
387  return d->affinities;
388 }
389 
391 {
392  if (isWindow() && (d->m_lastPosition->wasFloating() || !d->m_lastPosition->isValid())) {
393  // Create the FloatingWindow already, instead of waiting for the show event.
394  // This reduces flickering on some platforms
395  d->morphIntoFloatingWindow();
396  } else {
398  }
399 }
400 
402 {
403  if (!isOpen())
404  return;
405 
406  setAsCurrentTab();
407 
408  if (auto fw = floatingWindow()) {
409  fw->raise();
410  fw->activateWindow();
411  } else if (Frame *frame = d->frame()) {
412  if (frame->isMDI())
413  frame->raise();
414  }
415 }
416 
418 {
419  return qobject_cast<MainWindowBase *>(widget());
420 }
421 
423 {
424  return d->mainWindow() != nullptr;
425 }
426 
428 {
429  return d->mainWindow();
430 }
431 
433 {
434  auto f = d->frame();
435  return f && f->isFocused() && isCurrentTab();
436 }
437 
439 {
440  setAffinities({ affinity });
441 }
442 
443 void DockWidgetBase::setAffinities(const QStringList &affinityNames)
444 {
445  QStringList affinities = affinityNames;
447 
448  if (d->affinities == affinities)
449  return;
450 
451  if (!d->affinities.isEmpty()) {
452  qWarning() << Q_FUNC_INFO
453  << "Affinity is already set, refusing to change."
454  << "Submit a feature request with a good justification.";
455  return;
456  }
457 
458  d->affinities = affinities;
459 }
460 
462 {
463  if (MainWindowBase *m = mainWindow())
464  m->moveToSideBar(this);
465 }
466 
468 {
469  if (MainWindowBase *m = mainWindow())
470  return m->overlayedDockWidget() == this;
471 
472  return false;
473 }
474 
476 {
477  return DockRegistry::self()->sideBarLocationForDockWidget(this);
478 }
479 
481 {
483 }
484 
486 {
487  return d->m_lastPosition->isValid();
488 }
489 
491 {
492  return d->m_lastOverlayedSize;
493 }
494 
496 {
497  return DockRegistry::self()->dockByName(uniqueName);
498 }
499 
501 {
502  return d->layoutSaverOptions & LayoutSaverOption::Skip;
503 }
504 
506 {
507  if (isOpen() && isFloating()) {
508  window()->setGeometry(geometry);
509  } else {
510  d->m_lastPosition->setLastFloatingGeometry(geometry);
511  }
512 }
513 
514 FloatingWindow *DockWidgetBase::Private::morphIntoFloatingWindow()
515 {
516  if (auto fw = floatingWindow())
517  return fw; // Nothing to do
518 
519  if (q->isWindow()) {
520  QRect geo = m_lastPosition->lastFloatingGeometry();
521  if (geo.isNull()) {
522  geo = q->geometry();
523 
524  if (!q->testAttribute(Qt::WA_PendingMoveEvent)) { // If user already moved it, we don't
525  // interfere
526  const QPoint center = defaultCenterPosForFloating();
527  if (!center.isNull())
528  geo.moveCenter(center);
529  }
530  }
531 
532  auto frame = Config::self().frameworkWidgetFactory()->createFrame();
533  frame->addWidget(q);
534  geo.setSize(geo.size().boundedTo(frame->maxSizeHint()));
535  FloatingWindow::ensureRectIsOnScreen(geo);
536  auto floatingWindow =
537  Config::self().frameworkWidgetFactory()->createFloatingWindow(frame, nullptr, geo);
538  floatingWindow->show();
539 
540  return floatingWindow;
541  } else {
542  return nullptr;
543  }
544 }
545 
546 void DockWidgetBase::Private::maybeMorphIntoFloatingWindow()
547 {
548  if (q->isWindow() && q->isVisible())
549  morphIntoFloatingWindow();
550 }
551 
552 MDILayoutWidget *DockWidgetBase::Private::mdiLayout() const
553 {
554  auto p = const_cast<QObject *>(q->parent());
555  while (p) {
556  if (qobject_cast<const QWindow *>(p)) {
557  // Ignore QObject hierarchies spanning though multiple windows
558  return nullptr;
559  }
560 
561  if (qobject_cast<LayoutWidget *>(p)) {
562  // We found a layout
563  if (auto mdiLayout = qobject_cast<MDILayoutWidget *>(p)) {
564  // And it's MDI
565  return mdiLayout;
566  } else if (auto dropArea = qobject_cast<DropArea *>(p)) {
567  // It's a DropArea. But maybe it's a drop area that's just helping
568  // making the MDI windows accept drops (Option_MDINestable)
569  if (!dropArea->isMDIWrapper())
570  return nullptr;
571 
572  // It's a MDI wrapper, keep looking up.
573  }
574  }
575 
576  p = p->parent();
577  }
578 
579  return nullptr;
580 }
581 
582 bool DockWidgetBase::Private::isMDIWrapper() const
583 {
584  return mdiDropAreaWrapper() != nullptr;
585 }
586 
587 DropArea *DockWidgetBase::Private::mdiDropAreaWrapper() const
588 {
589  if (auto dropAreaGuest = qobject_cast<DropArea *>(q->widget())) {
590  if (dropAreaGuest->isMDIWrapper())
591  return dropAreaGuest;
592  }
593 
594  return nullptr;
595 }
596 
597 DockWidgetBase *DockWidgetBase::Private::mdiDockWidgetWrapper() const
598 {
599  if (isMDIWrapper()) {
600  // We are the wrapper
601  return q;
602  }
603 
604  auto p = const_cast<QObject *>(q->parent());
605  while (p) {
606  if (qobject_cast<const QWindow *>(p)) {
607  // Ignore QObject hierarchies spanning though multiple windows
608  return nullptr;
609  }
610 
611  if (qobject_cast<LayoutWidget *>(p)) {
612  if (auto dropArea = qobject_cast<DropArea *>(p)) {
613  if (dropArea->isMDIWrapper())
614  return dropArea->mdiDockWidgetWrapper();
615  }
616 
617  return nullptr;
618  }
619 
620  p = p->parent();
621  }
622 
623  return nullptr;
624 }
625 
626 DockWidgetBase::Private *DockWidgetBase::dptr() const
627 {
628  return d;
629 }
630 
631 QPoint DockWidgetBase::Private::defaultCenterPosForFloating()
632 {
633  MainWindowBase::List mainWindows = DockRegistry::self()->mainwindows();
634  // We don't care about multiple mainwindows yet. Or, let's just say that the first one is more main than the others
635  MainWindowBase *mw = mainWindows.isEmpty() ? nullptr : mainWindows.constFirst();
636  if (!mw || !q->isFloating())
637  return {};
638 
639  return mw->geometry().center();
640 }
641 
642 bool DockWidgetBase::Private::eventFilter(QObject *watched, QEvent *event)
643 {
644  const bool isWindowActivate = event->type() == QEvent::WindowActivate;
645  const bool isWindowDeactivate = event->type() == QEvent::WindowDeactivate;
646  if ((isWindowActivate || isWindowDeactivate) && watched == q->window())
647  Q_EMIT q->windowActiveAboutToChange(isWindowActivate);
648 
649  return QObject::eventFilter(watched, event);
650 }
651 
652 void DockWidgetBase::Private::updateTitle()
653 {
654  if (q->isFloating())
655  q->window()->setWindowTitle(title);
656 
657  toggleAction->setText(title);
658 }
659 
660 void DockWidgetBase::Private::toggle(bool enabled)
661 {
662  if (SideBar *sb = sideBar()) {
663  // The widget is in the sidebar, let's toggle its overlayed state
664  sb->toggleOverlay(q);
665  } else {
666  // The most common case. The dock widget is not in the sidebar. just close or open it.
667  if (enabled) {
668  show();
669  } else {
670  q->close();
671  }
672  }
673 }
674 
675 void DockWidgetBase::Private::updateToggleAction()
676 {
677  QScopedValueRollback<bool> recursionGuard(m_updatingToggleAction, true); // Guard against recursiveness
678  m_updatingToggleAction = true;
679  if ((q->isVisible() || frame()) && !toggleAction->isChecked()) {
680  toggleAction->setChecked(true);
681  } else if ((!q->isVisible() && !frame()) && toggleAction->isChecked()) {
682  toggleAction->setChecked(false);
683  }
684 }
685 
686 void DockWidgetBase::Private::updateFloatAction()
687 {
688  QScopedValueRollback<bool> recursionGuard(m_updatingFloatAction, true); // Guard against recursiveness
689 
690  if (q->isFloating()) {
691  floatAction->setEnabled(m_lastPosition->isValid());
692  floatAction->setChecked(true);
693  floatAction->setToolTip(tr("Dock"));
694  } else {
695  floatAction->setEnabled(true);
696  floatAction->setChecked(false);
697  floatAction->setToolTip(tr("Detach"));
698  }
699 }
700 
701 void DockWidgetBase::Private::onDockWidgetShown()
702 {
703  updateToggleAction();
704  updateFloatAction();
705 }
706 
707 void DockWidgetBase::Private::onDockWidgetHidden()
708 {
709  updateToggleAction();
710  updateFloatAction();
711 }
712 
713 void DockWidgetBase::Private::close()
714 {
715  if (!m_processingToggleAction && !q->isOpen()) {
716  return;
717  }
718 
719  if (m_isPersistentCentralDockWidget)
720  return;
721 
722  // If it's overlayed and we're closing, we need to close the overlay
723  if (SideBar *sb = DockRegistry::self()->sideBarForDockWidget(q)) {
724  auto mainWindow = sb->mainWindow();
725  if (mainWindow->overlayedDockWidget() == q) {
726  mainWindow->clearSideBarOverlay(/* deleteFrame=*/false);
727  }
728  }
729 
730  if (!m_isForceClosing && q->isFloating()
731  && q->isVisible()) { // only user-closing is interesting to save the geometry
732  // We check for isVisible so we don't save geometry if you call close() on an already closed
733  // dock widget
734  m_lastPosition->setLastFloatingGeometry(q->window()->geometry());
735  }
736 
737  saveTabIndex();
738 
739  // Do some cleaning. Widget is hidden, but we must hide the tab containing it.
740  if (Frame *frame = this->frame()) {
741  q->setParent(nullptr);
742  frame->removeWidget(q);
743 
744  if (SideBar *sb = DockRegistry::self()->sideBarForDockWidget(q)) {
745  sb->removeDockWidget(q);
746  }
747  }
748 
749  if (!m_isMovingToSideBar && (options & DockWidgetBase::Option_DeleteOnClose)) {
750  Q_EMIT q->aboutToDeleteOnClose();
751  q->deleteLater();
752  }
753 }
754 
755 bool DockWidgetBase::Private::restoreToPreviousPosition()
756 {
757  if (!m_lastPosition->isValid())
758  return false;
759 
760  Layouting::Item *item = m_lastPosition->lastItem();
761 
762  LayoutWidget *layout = DockRegistry::self()->layoutForItem(item);
763  Q_ASSERT(layout);
764  layout->restorePlaceholder(q, item, m_lastPosition->lastTabIndex());
765  return true;
766 }
767 
768 void DockWidgetBase::Private::maybeRestoreToPreviousPosition()
769 {
770  // This is called when we get a QEvent::Show. Let's see if we have to restore it to a previous position.
771 
772  if (!m_lastPosition->isValid())
773  return;
774 
775  Layouting::Item *layoutItem = m_lastPosition->lastItem();
776  if (!layoutItem)
777  return; // nothing to do, no last position
778 
779  if (m_lastPosition->wasFloating())
780  return; // Nothing to do, it was floating before, now it'll just get visible
781 
782  Frame *frame = this->frame();
783 
784  if (frame && frame->QWidgetAdapter::parentWidget() == DockRegistry::self()->layoutForItem(layoutItem)) {
785  // There's a frame already. Means the DockWidget was hidden instead of closed.
786  // Nothing to do, the dock widget will simply be shown
787  return;
788  }
789 
790  // Now we deal with the case where the DockWidget was close()ed. In this case it doesn't have a parent.
791 
792  if (q->parentWidget()) {
793  // The QEvent::Show is due to it being made floating. Nothing to restore.
794  return;
795  }
796 
797  // Finally, restore it
798  restoreToPreviousPosition();
799 }
800 
801 int DockWidgetBase::Private::currentTabIndex() const
802 {
803  Frame *frame = this->frame();
804  return frame ? frame->indexOfDockWidget(q) : 0;
805 }
806 
807 void DockWidgetBase::Private::saveTabIndex()
808 {
809  m_lastPosition->saveTabIndex(currentTabIndex(), q->isFloating());
810 }
811 
812 void DockWidgetBase::Private::show()
813 {
814  // Only show for now
815  q->show();
816 }
817 
819 {
820 #ifdef KDDOCKWIDGETS_QTWIDGETS
821  Q_EMIT parentChanged();
822 #else
823  Q_EMIT QQuickItem::parentChanged(parentItem());
824 #endif
825  d->updateToggleAction();
826  d->updateFloatAction();
827 
828  Q_EMIT actualTitleBarChanged();
829 }
830 
831 void DockWidgetBase::onShown(bool spontaneous)
832 {
833  d->onDockWidgetShown();
834  Q_EMIT shown();
835 
836  if (Frame *f = d->frame()) {
837  if (!spontaneous) {
838  f->onDockWidgetShown(this);
839  }
840  }
841 
842  d->maybeRestoreToPreviousPosition();
843 
844  // Transform into a FloatingWindow if this will be a regular floating dock widget.
845  QTimer::singleShot(0, d, &DockWidgetBase::Private::maybeMorphIntoFloatingWindow);
846 }
847 
848 void DockWidgetBase::onHidden(bool spontaneous)
849 {
850  d->onDockWidgetHidden();
851  Q_EMIT hidden();
852 
853  if (Frame *f = d->frame()) {
854  if (!spontaneous) {
855  f->onDockWidgetHidden(this);
856  }
857  }
858 }
859 
861 {
862  if (isOverlayed()) {
863  if (auto frame = d->frame()) {
864  d->m_lastOverlayedSize = frame->QWidgetAdapter::size();
865  } else {
866  qWarning() << Q_FUNC_INFO << "Overlayed dock widget without frame shouldn't happen";
867  }
868  }
869 
870  return QWidgetAdapter::onResize(newSize);
871 }
872 
874 {
875  e->accept(); // By default we accept, means DockWidget closes
876  if (d->widget)
877  qApp->sendEvent(d->widget, e); // Give a chance for the widget to ignore
878 
879  if (e->isAccepted())
880  d->close();
881 }
882 
883 DockWidgetBase *DockWidgetBase::deserialize(const LayoutSaver::DockWidget::Ptr &saved)
884 {
885  auto dr = DockRegistry::self();
886  DockWidgetBase *dw = dr->dockByName(saved->uniqueName, DockRegistry::DockByNameFlag::CreateIfNotFound);
887  if (dw) {
888  if (QWidgetOrQuick *w = dw->widget())
889  w->setVisible(true);
890  dw->setProperty("kddockwidget_was_restored", true);
891 
892  if (dw->affinities() != saved->affinities) {
893  qWarning() << Q_FUNC_INFO << "Affinity name changed from" << dw->affinities()
894  << "; to" << saved->affinities;
895  dw->d->affinities = saved->affinities;
896  }
897  }
898 
899  return dw;
900 }
901 
902 void DockWidgetBase::setUserType(int userType)
903 {
904  d->m_userType = userType;
905 }
906 
908 {
909  return d->m_userType;
910 }
911 
913 {
914  if (MDILayoutWidget *layout = d->mdiLayout()) {
915  if (auto wrapperDW = d->mdiDockWidgetWrapper()) {
916  // Case of using Option_MDINestable. We need to layout the actual top level DW
917  layout->moveDockWidget(wrapperDW, pos);
918  } else {
919  layout->moveDockWidget(this, pos);
920  }
921  }
922 }
923 
925 {
926  if (MDILayoutWidget *layout = d->mdiLayout()) {
927  if (auto wrapperDW = d->mdiDockWidgetWrapper()) {
928  // Case of using Option_MDINestable. We need to layout the actual top level DW
929  layout->resizeDockWidget(wrapperDW, size);
930  } else {
931  layout->resizeDockWidget(this, size);
932  }
933  }
934 }
935 
937 {
938 #ifdef KDDOCKWIDGETS_QTQUICK
939  if (Frame *frame = d->frame()) {
940  if (!frame->isMDI())
941  return;
942  frame->setZ(z);
943  }
944 #else
945  Q_UNUSED(z);
946  qWarning() << Q_FUNC_INFO << "Not implemented for QtQuick";
947 #endif
948 }
949 
951 {
952  return d->m_isPersistentCentralDockWidget;
953 }
954 
955 LayoutSaver::DockWidget::Ptr DockWidgetBase::Private::serialize() const
956 {
957  auto ptr = LayoutSaver::DockWidget::dockWidgetForName(q->uniqueName());
958  ptr->affinities = q->affinities();
959 
960  return ptr;
961 }
962 
963 void DockWidgetBase::Private::forceClose()
964 {
965  QScopedValueRollback<bool> rollback(m_isForceClosing, true);
966  close();
967 }
968 
969 DockWidgetBase::Private::Private(const QString &dockName, DockWidgetBase::Options options_,
970  LayoutSaverOptions layoutSaverOptions_, DockWidgetBase *qq)
971 
972  : name(dockName)
973  , title(dockName)
974  , q(qq)
975  , options(options_)
976  , layoutSaverOptions(layoutSaverOptions_)
977  , toggleAction(new QAction(q))
978  , floatAction(new QAction(q))
979 {
980  q->connect(toggleAction, &QAction::toggled, q, [this](bool enabled) {
981  if (!m_updatingToggleAction) { // guard against recursiveness
982  toggleAction->blockSignals(true); // and don't emit spurious toggle. Like when a dock
983  // widget is inserted into a tab widget it might get
984  // hide events, ignore those. The Dock Widget is open.
985  m_processingToggleAction = true;
986  toggle(enabled);
987  toggleAction->blockSignals(false);
988  m_processingToggleAction = false;
989  }
990  });
991 
992  q->connect(floatAction, &QAction::toggled, q, [this](bool checked) {
993  if (!m_updatingFloatAction) { // guard against recursiveness
994  q->setFloating(checked);
995  }
996 
997  Q_EMIT q->isFloatingChanged(checked);
998 
999  // When floating, we remove from the sidebar
1000  if (checked && q->isOpen()) {
1001  if (SideBar *sb = DockRegistry::self()->sideBarForDockWidget(q)) {
1002  sb->mainWindow()->clearSideBarOverlay(/* deleteFrame=*/false);
1003  sb->removeDockWidget(q);
1004  }
1005  }
1006  });
1007 
1008  toggleAction->setCheckable(true);
1009  floatAction->setCheckable(true);
1010 
1011  qApp->installEventFilter(this);
1012 }
1013 
1014 void DockWidgetBase::Private::addPlaceholderItem(Layouting::Item *item)
1015 {
1016  Q_ASSERT(item);
1017  m_lastPosition->addPlaceholderItem(item);
1018 }
1019 
1020 Position::Ptr &DockWidgetBase::Private::lastPosition()
1021 {
1022  return m_lastPosition;
1023 }
1024 
1025 Frame *DockWidgetBase::Private::frame() const
1026 {
1027  QWidgetOrQuick *p = q->parentWidget();
1028  while (p) {
1029  if (auto frame = qobject_cast<Frame *>(p))
1030  return frame;
1031  p = p->parentWidget();
1032  }
1033  return nullptr;
1034 }
1035 
1036 void DockWidgetBase::Private::saveLastFloatingGeometry()
1037 {
1038  if (q->isFloating() && q->isVisible()) {
1039  // It's getting docked, save last floating position
1040  lastPosition()->setLastFloatingGeometry(q->window()->geometry());
1041  }
1042 }
KDDockWidgets::DockWidgetBase::optionsChanged
void optionsChanged(KDDockWidgets::DockWidgetBase::Options)
emitted when the options change
KDDockWidgets::DockWidgetBase::show
Q_INVOKABLE void show()
Equivalent to QWidget::show(), but it's optimized to reduce flickering on some platforms.
Definition: DockWidgetBase.cpp:390
KDDockWidgets::SuggestedGeometryHint_PreserveCenter
@ SuggestedGeometryHint_PreserveCenter
Definition: KDDockWidgets.h:201
DockWidgetBase.h
The DockWidget base-class that's shared between QtWidgets and QtQuick stack.
QRect::setSize
void setSize(const QSize &size)
KDDockWidgets::DockWidgetBase::MDILayoutWidget
friend class MDILayoutWidget
Definition: DockWidgetBase.h:537
KDDockWidgets::DockWidgetBase::addDockWidgetAsTab
Q_INVOKABLE void addDockWidgetAsTab(KDDockWidgets::DockWidgetBase *other, KDDockWidgets::InitialOption initialOption={})
docks other widget into this one. Tabs will be shown if not already.
Definition: DockWidgetBase.cpp:63
QVector::isEmpty
bool isEmpty() const const
KDDockWidgets::MainWindowBase::addDockWidget
Q_INVOKABLE void addDockWidget(KDDockWidgets::DockWidgetBase *dockWidget, KDDockWidgets::Location location, KDDockWidgets::DockWidgetBase *relativeTo=nullptr, KDDockWidgets::InitialOption initialOption={})
Docks a DockWidget into this main window.
Definition: MainWindowBase.cpp:168
KDDockWidgets::DockWidgetBase::setAffinityName
void setAffinityName(const QString &name)
Definition: DockWidgetBase.cpp:438
KDDockWidgets::DockWidgetBase::isTabbed
bool isTabbed() const
returns if this dock widget is tabbed into another
Definition: DockWidgetBase.cpp:297
KDDockWidgets::DockWidgetBase::mainWindow
MainWindowBase * mainWindow() const
Returns the main window this dock widget is in. nullptr if it's not inside a main window Also returns...
Definition: DockWidgetBase.cpp:427
QEvent::WindowActivate
WindowActivate
KDDockWidgets::DockWidgetBase::setMDISize
void setMDISize(QSize size)
like setMDIPosition(), but for the size.
Definition: DockWidgetBase.cpp:924
KDDockWidgets::DockWidgetBase::affinities
QStringList affinities() const
Returns the affinity name. Empty by default.
Definition: DockWidgetBase.cpp:385
QRect::size
QSize size() const const
KDDockWidgets::DockWidgetBase::LayoutSaverOption::Skip
@ Skip
The dock widget won't participate in save/restore. Currently only available for floating windows.
KDDockWidgets::DockWidgetBase::byName
static DockWidgetBase * byName(const QString &uniqueName)
Returns a dock widget by its name This is the same name you passed to DockWidget CTOR....
Definition: DockWidgetBase.cpp:495
QWidget::sizePolicy
sizePolicy
QRect
KDDockWidgets::DockWidgetBase::setFloating
bool setFloating(bool floats)
setter to make the dock widget float or dock.
Definition: DockWidgetBase.cpp:179
KDDockWidgets::DockWidgetBase::isFocused
bool isFocused
Definition: DockWidgetBase.h:63
QList::removeAll
int removeAll(const T &value)
KDDockWidgets::DockWidgetBase::IconPlace::ToggleAction
@ ToggleAction
KDDockWidgets::InitialOption
Struct describing the preferred dock widget size and visibility when adding it to a layout.
Definition: KDDockWidgets.h:101
KDDockWidgets::DockWidgetBase::sideBarLocation
SideBarLocation sideBarLocation() const
Returns whether this dock widget is in a side bar, and which. SideBarLocation::None is returned if it...
Definition: DockWidgetBase.cpp:475
QTimer::singleShot
singleShot
KDDockWidgets::DockWidgetBase::forceClose
Q_INVOKABLE void forceClose()
Like QWidget::close() but the hosted widget won't be asked if we should close.
Definition: DockWidgetBase.cpp:367
QWidget
KDDockWidgets::DockWidgetBase::onResize
bool onResize(QSize newSize) override
Definition: DockWidgetBase.cpp:860
KDDockWidgets::Location
Location
Definition: KDDockWidgets.h:44
KDDockWidgets::DockWidgetBase::iconChanged
void iconChanged()
signal emitted when the icon changed
KDDockWidgets::DockWidgetBase::addDockWidgetToContainingWindow
Q_INVOKABLE void addDockWidgetToContainingWindow(KDDockWidgets::DockWidgetBase *other, KDDockWidgets::Location location, KDDockWidgets::DockWidgetBase *relativeTo=nullptr, KDDockWidgets::InitialOption initialOption={})
docks other widget into the window that contains this one. Equivalent to MainWindow::addDockWidget() ...
Definition: DockWidgetBase.cpp:116
KDDockWidgets::DockWidgetBase::widgetChanged
void widgetChanged(KDDockWidgets::QWidgetOrQuick *)
emitted when the hosted widget changed
KDDockWidgets::DockWidgetBase::uniqueName
QString uniqueName
Definition: DockWidgetBase.h:65
QSize
KDDockWidgets::DockWidgetBase::isInMainWindow
bool isInMainWindow() const
Returns whether this dock widget is docked into a main window (as opposed to floating)
Definition: DockWidgetBase.cpp:422
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
KDDockWidgets::DockWidgetBase::Option_NotDockable
@ Option_NotDockable
The DockWidget can't be docked, it's always floating.
Definition: DockWidgetBase.h:77
KDDockWidgets::DockWidgetBase::setMDIZ
void setMDIZ(int z)
like setMDIPosition(), but for the Z only implemented for QtQuick
Definition: DockWidgetBase.cpp:936
KDDockWidgets::DockWidgetBase::isOverlayed
bool isOverlayed() const
Returns whether this dock widget is overlayed from the side-bar.
Definition: DockWidgetBase.cpp:467
KDDockWidgets::DockWidgetBase::title
QString title
Definition: DockWidgetBase.h:66
KDDockWidgets::DockWidgetBase::widget
QObject * widget
Definition: DockWidgetBase.h:67
KDDockWidgets::DockWidgetBase::onCloseEvent
void onCloseEvent(QCloseEvent *e) override
Definition: DockWidgetBase.cpp:873
KDDockWidgets::DockWidgetBase::isOpen
Q_INVOKABLE bool isOpen() const
Returns whether this dock widget is open. Equivalent to calling toggleAction().isChecked() or isVisib...
Definition: DockWidgetBase.cpp:380
KDDockWidgets::DockWidgetBase::isFloating
bool isFloating
Definition: DockWidgetBase.h:64
KDDockWidgets::DockWidgetBase::isInSideBar
bool isInSideBar() const
Returns where this dockwidget is in a sidebar Similar to sideBarLocation(), but returns a bool.
Definition: DockWidgetBase.cpp:480
QObject::eventFilter
virtual bool eventFilter(QObject *watched, QEvent *event)
KDDockWidgets::DockWidgetBase::titleChanged
void titleChanged(const QString &title)
signal emitted when the title changed
KDDockWidgets::DockWidgetBase::raise
Q_INVOKABLE void raise()
Brings the dock widget to the front.
Definition: DockWidgetBase.cpp:401
KDDockWidgets::DockWidgetBase::DockWidgetBase
DockWidgetBase(const QString &uniqueName, Options options=KDDockWidgets::DockWidgetBase::Options(), LayoutSaverOptions layoutSaverOptions=KDDockWidgets::DockWidgetBase::LayoutSaverOptions())
constructs a new DockWidget
Definition: DockWidgetBase.cpp:43
KDDockWidgets::DockWidgetBase::setWidget
virtual void setWidget(QWidgetOrQuick *widget)
sets the widget which this dock widget hosts.
Definition: DockWidgetBase.cpp:148
KDDockWidgets::DockWidgetBase::setAsCurrentTab
Q_INVOKABLE void setAsCurrentTab()
Makes this dock widget current in its tab group.
Definition: DockWidgetBase.cpp:317
QCloseEvent
QObject
QVector::constFirst
const T & constFirst() const const
KDDockWidgets::DockWidgetBase::currentTabIndex
int currentTabIndex() const
Returns the index of the current tab of the tab group this dock widget is in.
Definition: DockWidgetBase.cpp:331
KDDockWidgets::SideBarLocation::None
@ None
QObject::blockSignals
bool blockSignals(bool block)
QAction::toggled
void toggled(bool checked)
KDDockWidgets::DockWidgetBase::skipsRestore
bool skipsRestore() const
Returns whether this widget has the LayoutSaverOption::Skip flag.
Definition: DockWidgetBase.cpp:500
QString
Qt
QEvent::isAccepted
bool isAccepted() const const
KDDockWidgets::Config::InternalFlag_DontShowWhenUnfloatingHiddenWindow
@ InternalFlag_DontShowWhenUnfloatingHiddenWindow
DockWidget::setFloating(false) won't do anything if the window is hidden.
Definition: Config.h:134
QString::isEmpty
bool isEmpty() const const
KDDockWidgets::DockWidgetBase::IconPlace::TitleBar
@ TitleBar
KDDockWidgets::DockWidgetBase::~DockWidgetBase
~DockWidgetBase() override
destructor
Definition: DockWidgetBase.cpp:57
QSize::boundedTo
QSize boundedTo(const QSize &otherSize) const const
KDDockWidgets::DockWidgetBase::isMainWindow
bool isMainWindow() const
Returns whether widget() is a KDDockWidget::MainWindow.
Definition: DockWidgetBase.cpp:417
KDDockWidgets::DockWidgetBase::onHidden
void onHidden(bool spontaneous)
Definition: DockWidgetBase.cpp:848
KDDockWidgets::DockWidgetBase::IconPlace
IconPlace
Definition: DockWidgetBase.h:93
KDDockWidgets::Config::frameworkWidgetFactory
FrameworkWidgetFactory * frameworkWidgetFactory() const
getter for the framework widget factory
Definition: Config.cpp:145
KDDockWidgets::DockWidgetBase::actualTitleBarChanged
void actualTitleBarChanged()
Emitted when the title bar that serves this dock widget changes.
QIcon
KDDockWidgets::DockWidgetBase::userType
int userType() const
Definition: DockWidgetBase.cpp:907
QRect::isNull
bool isNull() const const
KDDockWidgets::DockWidgetBase::Option_DeleteOnClose
@ Option_DeleteOnClose
Deletes the DockWidget when closed.
Definition: DockWidgetBase.h:78
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...
KDDockWidgets::SideBarLocation
SideBarLocation
Each main window supports 4 sidebars.
Definition: KDDockWidgets.h:208
QAction::setCheckable
void setCheckable(bool)
KDDockWidgets::DockWidgetBase::toggleAction
Q_INVOKABLE QAction * toggleAction() const
Returns the QAction that allows to hide/show the dock widget Useful to put in menus.
Definition: DockWidgetBase.cpp:223
KDDockWidgets::DockWidgetBase::lastOverlayedSize
QSize lastOverlayedSize() const
returns the last size the widget has when overlayed Empty otherwise
Definition: DockWidgetBase.cpp:490
QRect::moveCenter
void moveCenter(const QPoint &position)
QWidget::show
void show()
KDDockWidgets::FrameworkWidgetFactory::createFloatingWindow
virtual FloatingWindow * createFloatingWindow(MainWindowBase *parent=nullptr) const =0
Called internally by the framework to create a FloatingWindow Override to provide your own FloatingWi...
KDDockWidgets::DockWidgetBase::frameGeometry
QRect frameGeometry() const
Returns the size of the dock widget's parent frame.
Definition: DockWidgetBase.cpp:263
Config.h
Application-wide config to tune certain behaviours of the framework.
KDDockWidgets::DockWidgetBase::icon
QIcon icon(IconPlace place=IconPlace::TitleBar) const
Returns the dock widget's titlebar, tabbar, or toggle action icon (depending on the passed place)
Definition: DockWidgetBase.cpp:353
KDDockWidgets::DockWidgetBase::setMDIPosition
void setMDIPosition(QPoint pos)
Sets this dock widgets position to pos within the MDI layout This only applies if the main window is ...
Definition: DockWidgetBase.cpp:912
KDDockWidgets::DockWidgetBase::titleBar
TitleBar * titleBar() const
Returns this dock widget's title bar.
Definition: DockWidgetBase.cpp:372
KDDockWidgets::DockWidgetBase::moveToSideBar
Q_INVOKABLE void moveToSideBar()
Minimizes this dock widget to the MainWindow's side-bar.
Definition: DockWidgetBase.cpp:461
KDDockWidgets::DockWidgetBase::setAffinities
void setAffinities(const QStringList &)
Sets the affinity names. Dock widgets can only dock into dock widgets of the same affinity.
Definition: DockWidgetBase.cpp:443
QEvent
KDDockWidgets::DockWidgetBase::Frame
friend class Frame
Definition: DockWidgetBase.h:539
KDDockWidgets::DockWidgetBase::setTitle
void setTitle(const QString &title)
setter for the dock widget's title
Definition: DockWidgetBase.cpp:254
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::DockWidgetBase::hasPreviousDockedLocation
bool hasPreviousDockedLocation() const
Returns whether this floating dock widget knows its previous docked location Result only makes sense ...
Definition: DockWidgetBase.cpp:485
QAction
KDDockWidgets::DockWidgetBase::hidden
void hidden()
signal emitted when the DockWidget is hidden. As in QEvent::Hide.
KDDockWidgets
Definition: Config.cpp:37
QScopedValueRollback
KDDockWidgets::DockWidgetBase::setFloatingGeometry
void setFloatingGeometry(QRect geo)
If this dock widget is floating, then sets its geometry to geo.
Definition: DockWidgetBase.cpp:505
QWidget::geometry
geometry
KDDockWidgets::DockWidgetBase::setUserType
void setUserType(int userType)
Allows the user to set a type on this dock widget The type is opaque and will not be interpreted by K...
Definition: DockWidgetBase.cpp:902
KDDockWidgets::DockWidgetBase::parentChanged
void parentChanged()
signal emitted when the parent changed QtQuick already has QQuickItem::parentChanged(),...
KDDockWidgets::DockWidgetBase::tabIndex
int tabIndex() const
Returns the tab index this dock widget occupies Note that dock widgets are almost always tabbed,...
Definition: DockWidgetBase.cpp:323
KDDockWidgets::MainWindowBase
The MainWindow base-class. MainWindow and MainWindowBase are only split in two so we can share some c...
Definition: MainWindowBase.h:56
KDDockWidgets::DockWidgetBase::setIcon
void setIcon(const QIcon &icon, IconPlaces places=IconPlace::All)
Sets an icon to show on title bars and tab bars.
Definition: DockWidgetBase.cpp:339
KDDockWidgets::DockWidgetBase::floatAction
Q_INVOKABLE QAction * floatAction() const
Returns the QAction that allows to dock/undock the dock widget Useful to put in menus.
Definition: DockWidgetBase.cpp:228
QVector
KDDockWidgets::DockWidgetBase::shown
void shown()
signal emitted when the DockWidget is shown. As in QEvent::Show.
KDDockWidgets::DockWidgetBase::layoutSaverOptions
KDDockWidgets::DockWidgetBase::LayoutSaverOptions layoutSaverOptions() const
returns the per-dockwidget options which will affect LayoutSaver These are the options which were pas...
Definition: DockWidgetBase.cpp:277
KDDockWidgets::DockWidgetBase::options
KDDockWidgets::DockWidgetBase::Options options
Definition: DockWidgetBase.h:69
KDDockWidgets::DockWidgetBase::isCurrentTab
bool isCurrentTab() const
Returns true if this dock widget is the current one in the tab widget that contains it....
Definition: DockWidgetBase.cpp:308
QWidget::parentWidget
QWidget * parentWidget() const const
KDDockWidgets::DockWidgetBase::setOptions
void setOptions(Options)
Setter for the options. Only Option_NotClosable is allowed to change after construction....
Definition: DockWidgetBase.cpp:282
KDDockWidgets::DockWidgetBase::IconPlace::TabBar
@ TabBar
QObject::parent
QObject * parent() const const
Qt::WA_PendingMoveEvent
WA_PendingMoveEvent
KDDockWidgets::DockWidgetBase::onShown
void onShown(bool spontaneous)
Definition: DockWidgetBase.cpp:831
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
KDDockWidgets::DockWidgetBase::onParentChanged
void onParentChanged()
Definition: DockWidgetBase.cpp:818

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