KDDockWidgets API Documentation  1.5
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) || (!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  d->frame()->titleBar()->makeWindow();
209  }
210 
211  auto lastGeo = d->lastPositions().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  return d->title;
241 }
242 
244 {
245  if (title != d->title) {
246  d->title = title;
247  d->updateTitle();
248  Q_EMIT titleChanged(title);
249  }
250 }
251 
253 {
254  if (Frame *f = d->frame())
255  return f->QWidgetAdapter::geometry();
256 
257  // Means the dock widget isn't visible. Just fallback to its own geometry
258  return QWidgetAdapter::geometry();
259 }
260 
261 DockWidgetBase::Options DockWidgetBase::options() const
262 {
263  return d->options;
264 }
265 
266 DockWidgetBase::LayoutSaverOptions DockWidgetBase::layoutSaverOptions() const
267 {
268  return d->layoutSaverOptions;
269 }
270 
271 void DockWidgetBase::setOptions(Options options)
272 {
273  if ((d->options & Option_NotDockable) != (options & Option_NotDockable)) {
274  qWarning() << Q_FUNC_INFO << "Option_NotDockable not allowed to change. Pass via ctor only.";
275  return;
276  }
277 
278  if (options != d->options) {
279  d->options = options;
280  Q_EMIT optionsChanged(options);
281  if (auto tb = titleBar())
282  tb->updateButtons();
283  }
284 }
285 
287 {
288  if (Frame *frame = d->frame()) {
289  return frame->alwaysShowsTabs() || frame->dockWidgetCount() > 1;
290  } else {
291  if (!isFloating())
292  qWarning() << "DockWidget::isTabbed() Couldn't find any tab widget.";
293  return false;
294  }
295 }
296 
298 {
299  if (Frame *frame = d->frame()) {
300  return frame->currentIndex() == frame->indexOfDockWidget(const_cast<DockWidgetBase *>(this));
301  } else {
302  return true;
303  }
304 }
305 
307 {
308  if (Frame *frame = d->frame())
309  frame->setCurrentDockWidget(this);
310 }
311 
313 {
314  if (Frame *frame = d->frame())
315  return frame->indexOfDockWidget(this);
316 
317  return 0;
318 }
319 
320 void DockWidgetBase::setIcon(const QIcon &icon, IconPlaces places)
321 {
322  if (places & IconPlace::TitleBar)
323  d->titleBarIcon = icon;
324 
325  if (places & IconPlace::TabBar)
326  d->tabBarIcon = icon;
327 
328  if (places & IconPlace::ToggleAction)
329  d->toggleAction->setIcon(icon);
330 
331  Q_EMIT iconChanged();
332 }
333 
335 {
336  if (place == IconPlace::TitleBar)
337  return d->titleBarIcon;
338 
339  if (place == IconPlace::TabBar)
340  return d->tabBarIcon;
341 
342  if (place == IconPlace::ToggleAction)
343  return d->toggleAction->icon();
344 
345  return {};
346 }
347 
349 {
350  d->forceClose();
351 }
352 
353 TitleBar *DockWidgetBase::titleBar() const
354 {
355  if (Frame *f = d->frame())
356  return f->actualTitleBar();
357 
358  return nullptr;
359 }
360 
362 {
363  return d->toggleAction->isChecked();
364 }
365 
367 {
368  return d->affinities;
369 }
370 
372 {
373  if (isWindow() && (d->m_lastPositions.wasFloating() || !d->m_lastPositions.isValid())) {
374  // Create the FloatingWindow already, instead of waiting for the show event.
375  // This reduces flickering on some platforms
376  d->morphIntoFloatingWindow();
377  } else {
379  }
380 }
381 
383 {
384  if (!isOpen())
385  return;
386 
387  setAsCurrentTab();
388 
389  if (auto fw = floatingWindow()) {
390  fw->raise();
391  fw->activateWindow();
392  } else if (Frame *frame = d->frame()) {
393  if (frame->isMDI())
394  frame->raise();
395  }
396 }
397 
399 {
400  return qobject_cast<MainWindowBase *>(widget());
401 }
402 
404 {
405  return d->mainWindow() != nullptr;
406 }
407 
409 {
410  return d->mainWindow();
411 }
412 
414 {
415  auto f = d->frame();
416  return f && f->isFocused() && isCurrentTab();
417 }
418 
420 {
421  setAffinities({ affinity });
422 }
423 
424 void DockWidgetBase::setAffinities(const QStringList &affinityNames)
425 {
426  QStringList affinities = affinityNames;
428 
429  if (d->affinities == affinities)
430  return;
431 
432  if (!d->affinities.isEmpty()) {
433  qWarning() << Q_FUNC_INFO
434  << "Affinity is already set, refusing to change."
435  << "Submit a feature request with a good justification.";
436  return;
437  }
438 
439  d->affinities = affinities;
440 }
441 
443 {
444  if (MainWindowBase *m = mainWindow())
445  m->moveToSideBar(this);
446 }
447 
449 {
450  if (MainWindowBase *m = mainWindow())
451  return m->overlayedDockWidget() == this;
452 
453  return false;
454 }
455 
457 {
458  return DockRegistry::self()->sideBarLocationForDockWidget(this);
459 }
460 
462 {
464 }
465 
467 {
468  return d->m_lastPositions.isValid();
469 }
470 
472 {
473  return d->m_lastOverlayedSize;
474 }
475 
477 {
478  return DockRegistry::self()->dockByName(uniqueName);
479 }
480 
482 {
483  return d->layoutSaverOptions & LayoutSaverOption::Skip;
484 }
485 
487 {
488  if (isOpen() && isFloating()) {
489  window()->setGeometry(geometry);
490  } else {
491  d->m_lastPositions.setLastFloatingGeometry(geometry);
492  }
493 }
494 
495 FloatingWindow *DockWidgetBase::Private::morphIntoFloatingWindow()
496 {
497  if (auto fw = floatingWindow())
498  return fw; // Nothing to do
499 
500  if (q->isWindow()) {
501  QRect geo = m_lastPositions.lastFloatingGeometry();
502  if (geo.isNull()) {
503  geo = q->geometry();
504 
505  if (!q->testAttribute(Qt::WA_PendingMoveEvent)) { // If user already moved it, we don't
506  // interfere
507  const QPoint center = defaultCenterPosForFloating();
508  if (!center.isNull())
509  geo.moveCenter(center);
510  }
511  }
512 
513  auto frame = Config::self().frameworkWidgetFactory()->createFrame();
514  frame->addWidget(q);
515  geo.setSize(geo.size().boundedTo(frame->maxSizeHint()));
516  FloatingWindow::ensureRectIsOnScreen(geo);
517  auto floatingWindow =
518  Config::self().frameworkWidgetFactory()->createFloatingWindow(frame, nullptr, geo);
519  floatingWindow->show();
520 
521  return floatingWindow;
522  } else {
523  return nullptr;
524  }
525 }
526 
527 void DockWidgetBase::Private::maybeMorphIntoFloatingWindow()
528 {
529  if (q->isWindow() && q->isVisible())
530  morphIntoFloatingWindow();
531 }
532 
533 MDILayoutWidget *DockWidgetBase::Private::mdiLayout() const
534 {
535  if (auto mw = mainWindow())
536  return mw->mdiLayoutWidget();
537 
538  return nullptr;
539 }
540 
541 DockWidgetBase::Private *DockWidgetBase::dptr() const
542 {
543  return d;
544 }
545 
546 QPoint DockWidgetBase::Private::defaultCenterPosForFloating()
547 {
548  MainWindowBase::List mainWindows = DockRegistry::self()->mainwindows();
549  // We don't care about multiple mainwindows yet. Or, let's just say that the first one is more main than the others
550  MainWindowBase *mw = mainWindows.isEmpty() ? nullptr : mainWindows.constFirst();
551  if (!mw || !q->isFloating())
552  return {};
553 
554  return mw->geometry().center();
555 }
556 
557 bool DockWidgetBase::Private::eventFilter(QObject *watched, QEvent *event)
558 {
559  const bool isWindowActivate = event->type() == QEvent::WindowActivate;
560  const bool isWindowDeactivate = event->type() == QEvent::WindowDeactivate;
561  if ((isWindowActivate || isWindowDeactivate) && watched == q->window())
562  Q_EMIT q->windowActiveAboutToChange(isWindowActivate);
563 
564  return QObject::eventFilter(watched, event);
565 }
566 
567 void DockWidgetBase::Private::updateTitle()
568 {
569  if (q->isFloating())
570  q->window()->setWindowTitle(title);
571 
572  toggleAction->setText(title);
573 }
574 
575 void DockWidgetBase::Private::toggle(bool enabled)
576 {
577  if (SideBar *sb = sideBar()) {
578  // The widget is in the sidebar, let's toggle its overlayed state
579  sb->toggleOverlay(q);
580  } else {
581  // The most common case. The dock widget is not in the sidebar. just close or open it.
582  if (enabled) {
583  show();
584  } else {
585  q->close();
586  }
587  }
588 }
589 
590 void DockWidgetBase::Private::updateToggleAction()
591 {
592  QScopedValueRollback<bool> recursionGuard(m_updatingToggleAction, true); // Guard against recursiveness
593  m_updatingToggleAction = true;
594  if ((q->isVisible() || frame()) && !toggleAction->isChecked()) {
595  toggleAction->setChecked(true);
596  } else if ((!q->isVisible() && !frame()) && toggleAction->isChecked()) {
597  toggleAction->setChecked(false);
598  }
599 }
600 
601 void DockWidgetBase::Private::updateFloatAction()
602 {
603  QScopedValueRollback<bool> recursionGuard(m_updatingFloatAction, true); // Guard against recursiveness
604 
605  if (q->isFloating()) {
606  floatAction->setEnabled(m_lastPositions.isValid());
607  floatAction->setChecked(true);
608  floatAction->setToolTip(tr("Dock"));
609  } else {
610  floatAction->setEnabled(true);
611  floatAction->setChecked(false);
612  floatAction->setToolTip(tr("Detach"));
613  }
614 }
615 
616 void DockWidgetBase::Private::onDockWidgetShown()
617 {
618  updateToggleAction();
619  updateFloatAction();
620 }
621 
622 void DockWidgetBase::Private::onDockWidgetHidden()
623 {
624  updateToggleAction();
625  updateFloatAction();
626 }
627 
628 void DockWidgetBase::Private::close()
629 {
630  if (!m_processingToggleAction && !q->isOpen()) {
631  return;
632  }
633 
634  if (m_isPersistentCentralDockWidget)
635  return;
636 
637  // If it's overlayed and we're closing, we need to close the overlay
638  if (SideBar *sb = DockRegistry::self()->sideBarForDockWidget(q)) {
639  auto mainWindow = sb->mainWindow();
640  if (mainWindow->overlayedDockWidget() == q) {
641  mainWindow->clearSideBarOverlay(/* deleteFrame=*/false);
642  }
643  }
644 
645  if (!m_isForceClosing && q->isFloating()
646  && q->isVisible()) { // only user-closing is interesting to save the geometry
647  // We check for isVisible so we don't save geometry if you call close() on an already closed
648  // dock widget
649  m_lastPositions.setLastFloatingGeometry(q->window()->geometry());
650  }
651 
652  saveTabIndex();
653 
654  // Do some cleaning. Widget is hidden, but we must hide the tab containing it.
655  if (Frame *frame = this->frame()) {
656  q->setParent(nullptr);
657  frame->removeWidget(q);
658 
659  if (SideBar *sb = DockRegistry::self()->sideBarForDockWidget(q)) {
660  sb->removeDockWidget(q);
661  }
662  }
663 
664  if (!m_isMovingToSideBar && (options & DockWidgetBase::Option_DeleteOnClose)) {
665  Q_EMIT q->aboutToDeleteOnClose();
666  q->deleteLater();
667  }
668 }
669 
670 bool DockWidgetBase::Private::restoreToPreviousPosition()
671 {
672  if (!m_lastPositions.isValid())
673  return false;
674 
675  Layouting::Item *item = m_lastPositions.lastItem();
676 
677  LayoutWidget *layout = DockRegistry::self()->layoutForItem(item);
678  Q_ASSERT(layout);
679  layout->restorePlaceholder(q, item, m_lastPositions.lastTabIndex());
680  return true;
681 }
682 
683 void DockWidgetBase::Private::maybeRestoreToPreviousPosition()
684 {
685  // This is called when we get a QEvent::Show. Let's see if we have to restore it to a previous position.
686 
687  if (!m_lastPositions.isValid())
688  return;
689 
690  Layouting::Item *layoutItem = m_lastPositions.lastItem();
691  if (!layoutItem)
692  return; // nothing to do, no last position
693 
694  if (m_lastPositions.wasFloating())
695  return; // Nothing to do, it was floating before, now it'll just get visible
696 
697  Frame *frame = this->frame();
698 
699  if (frame && frame->QWidgetAdapter::parentWidget() == DockRegistry::self()->layoutForItem(layoutItem)) {
700  // There's a frame already. Means the DockWidget was hidden instead of closed.
701  // Nothing to do, the dock widget will simply be shown
702  return;
703  }
704 
705  // Now we deal with the case where the DockWidget was close()ed. In this case it doesn't have a parent.
706 
707  if (q->parentWidget()) {
708  // The QEvent::Show is due to it being made floating. Nothing to restore.
709  return;
710  }
711 
712  // Finally, restore it
713  restoreToPreviousPosition();
714 }
715 
716 int DockWidgetBase::Private::currentTabIndex() const
717 {
718  Frame *frame = this->frame();
719  return frame ? frame->indexOfDockWidget(q) : 0;
720 }
721 
722 void DockWidgetBase::Private::saveTabIndex()
723 {
724  m_lastPositions.saveTabIndex(currentTabIndex(), q->isFloating());
725 }
726 
727 void DockWidgetBase::Private::show()
728 {
729  // Only show for now
730  q->show();
731 }
732 
734 {
735 #ifdef KDDOCKWIDGETS_QTWIDGETS
736  Q_EMIT parentChanged();
737 #else
738  Q_EMIT QQuickItem::parentChanged(parentItem());
739 #endif
740  d->updateToggleAction();
741  d->updateFloatAction();
742 
743  Q_EMIT actualTitleBarChanged();
744 }
745 
746 void DockWidgetBase::onShown(bool spontaneous)
747 {
748  d->onDockWidgetShown();
749  Q_EMIT shown();
750 
751  if (Frame *f = d->frame()) {
752  if (!spontaneous) {
753  f->onDockWidgetShown(this);
754  }
755  }
756 
757  d->maybeRestoreToPreviousPosition();
758 
759  // Transform into a FloatingWindow if this will be a regular floating dock widget.
760  QTimer::singleShot(0, d, &DockWidgetBase::Private::maybeMorphIntoFloatingWindow);
761 }
762 
763 void DockWidgetBase::onHidden(bool spontaneous)
764 {
765  d->onDockWidgetHidden();
766  Q_EMIT hidden();
767 
768  if (Frame *f = d->frame()) {
769  if (!spontaneous) {
770  f->onDockWidgetHidden(this);
771  }
772  }
773 }
774 
776 {
777  if (isOverlayed()) {
778  if (auto frame = d->frame()) {
779  d->m_lastOverlayedSize = frame->QWidgetAdapter::size();
780  } else {
781  qWarning() << Q_FUNC_INFO << "Overlayed dock widget without frame shouldn't happen";
782  }
783  }
784 
785  return QWidgetAdapter::onResize(newSize);
786 }
787 
789 {
790  e->accept(); // By default we accept, means DockWidget closes
791  if (d->widget)
792  qApp->sendEvent(d->widget, e); // Give a chance for the widget to ignore
793 
794  if (e->isAccepted())
795  d->close();
796 }
797 
798 DockWidgetBase *DockWidgetBase::deserialize(const LayoutSaver::DockWidget::Ptr &saved)
799 {
800  auto dr = DockRegistry::self();
801  DockWidgetBase *dw = dr->dockByName(saved->uniqueName, DockRegistry::DockByNameFlag::CreateIfNotFound);
802  if (dw) {
803  if (QWidgetOrQuick *w = dw->widget())
804  w->setVisible(true);
805  dw->setProperty("kddockwidget_was_restored", true);
806 
807  if (dw->affinities() != saved->affinities) {
808  qWarning() << Q_FUNC_INFO << "Affinity name changed from" << dw->affinities()
809  << "; to" << saved->affinities;
810  dw->d->affinities = saved->affinities;
811  }
812  }
813 
814  return dw;
815 }
816 
817 void DockWidgetBase::setUserType(int userType)
818 {
819  d->m_userType = userType;
820 }
821 
823 {
824  return d->m_userType;
825 }
826 
828 {
829  if (MDILayoutWidget *layout = d->mdiLayout())
830  layout->moveDockWidget(this, pos);
831 }
832 
834 {
835  if (MDILayoutWidget *layout = d->mdiLayout())
836  layout->resizeDockWidget(this, size);
837 }
838 
840 {
841 #ifdef KDDOCKWIDGETS_QTQUICK
842  if (Frame *frame = d->frame()) {
843  if (!frame->isMDI())
844  return;
845  frame->setZ(z);
846  }
847 #else
848  Q_UNUSED(z);
849  qWarning() << Q_FUNC_INFO << "Not implemented for QtQuick";
850 #endif
851 }
852 
854 {
855  return d->m_isPersistentCentralDockWidget;
856 }
857 
858 LayoutSaver::DockWidget::Ptr DockWidgetBase::Private::serialize() const
859 {
860  auto ptr = LayoutSaver::DockWidget::dockWidgetForName(q->uniqueName());
861  ptr->affinities = q->affinities();
862 
863  return ptr;
864 }
865 
866 void DockWidgetBase::Private::forceClose()
867 {
868  QScopedValueRollback<bool> rollback(m_isForceClosing, true);
869  close();
870 }
871 
872 DockWidgetBase::Private::Private(const QString &dockName, DockWidgetBase::Options options_,
873  LayoutSaverOptions layoutSaverOptions_, DockWidgetBase *qq)
874 
875  : name(dockName)
876  , title(dockName)
877  , q(qq)
878  , options(options_)
879  , layoutSaverOptions(layoutSaverOptions_)
880  , toggleAction(new QAction(q))
881  , floatAction(new QAction(q))
882 {
883  q->connect(toggleAction, &QAction::toggled, q, [this](bool enabled) {
884  if (!m_updatingToggleAction) { // guard against recursiveness
885  toggleAction->blockSignals(true); // and don't emit spurious toggle. Like when a dock
886  // widget is inserted into a tab widget it might get
887  // hide events, ignore those. The Dock Widget is open.
888  m_processingToggleAction = true;
889  toggle(enabled);
890  toggleAction->blockSignals(false);
891  m_processingToggleAction = false;
892  }
893  });
894 
895  q->connect(floatAction, &QAction::toggled, q, [this](bool checked) {
896  if (!m_updatingFloatAction) { // guard against recursiveness
897  q->setFloating(checked);
898  }
899 
900  Q_EMIT q->isFloatingChanged(checked);
901 
902  // When floating, we remove from the sidebar
903  if (checked && q->isOpen()) {
904  if (SideBar *sb = DockRegistry::self()->sideBarForDockWidget(q)) {
905  sb->mainWindow()->clearSideBarOverlay(/* deleteFrame=*/false);
906  sb->removeDockWidget(q);
907  }
908  }
909  });
910 
911  toggleAction->setCheckable(true);
912  floatAction->setCheckable(true);
913 
914  qApp->installEventFilter(this);
915 }
916 
917 void DockWidgetBase::Private::addPlaceholderItem(Layouting::Item *item)
918 {
919  Q_ASSERT(item);
920  m_lastPositions.addPosition(item);
921 }
922 
923 LastPositions &DockWidgetBase::Private::lastPositions()
924 {
925  return m_lastPositions;
926 }
927 
928 Frame *DockWidgetBase::Private::frame() const
929 {
930  QWidgetOrQuick *p = q->parentWidget();
931  while (p) {
932  if (auto frame = qobject_cast<Frame *>(p))
933  return frame;
934  p = p->parentWidget();
935  }
936  return nullptr;
937 }
938 
939 void DockWidgetBase::Private::saveLastFloatingGeometry()
940 {
941  if (q->isFloating() && q->isVisible()) {
942  // It's getting docked, save last floating position
943  lastPositions().setLastFloatingGeometry(q->window()->geometry());
944  }
945 }
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:371
KDDockWidgets::SuggestedGeometryHint_PreserveCenter
@ SuggestedGeometryHint_PreserveCenter
Definition: KDDockWidgets.h:203
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:531
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:164
KDDockWidgets::DockWidgetBase::setAffinityName
void setAffinityName(const QString &name)
Definition: DockWidgetBase.cpp:419
KDDockWidgets::DockWidgetBase::isTabbed
bool isTabbed() const
returns if this dock widget is tabbed into another
Definition: DockWidgetBase.cpp:286
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:408
QEvent::WindowActivate
WindowActivate
KDDockWidgets::DockWidgetBase::setMDISize
void setMDISize(QSize size)
like setMDIPosition(), but for the size.
Definition: DockWidgetBase.cpp:833
KDDockWidgets::DockWidgetBase::affinities
QStringList affinities() const
Returns the affinity name. Empty by default.
Definition: DockWidgetBase.cpp:366
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:476
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:105
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:456
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:348
QWidget
KDDockWidgets::DockWidgetBase::onResize
bool onResize(QSize newSize) override
Definition: DockWidgetBase.cpp:775
KDDockWidgets::Location
Location
Definition: KDDockWidgets.h:45
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:403
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:853
KDDockWidgets::DockWidgetBase::Option_NotDockable
@ Option_NotDockable
The DockWidget can't be docked, it's always floating.
Definition: DockWidgetBase.h:78
KDDockWidgets::DockWidgetBase::setMDIZ
void setMDIZ(int z)
like setMDIPosition(), but for the Z only implemented for QtQuick
Definition: DockWidgetBase.cpp:839
KDDockWidgets::DockWidgetBase::isOverlayed
bool isOverlayed() const
Returns whether this dock widget is overlayed from the side-bar.
Definition: DockWidgetBase.cpp:448
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:788
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:361
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:461
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:382
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:306
QCloseEvent
QObject
QVector::constFirst
const T & constFirst() const const
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:481
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:117
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:398
KDDockWidgets::DockWidgetBase::onHidden
void onHidden(bool spontaneous)
Definition: DockWidgetBase.cpp:763
KDDockWidgets::DockWidgetBase::IconPlace
IconPlace
Definition: DockWidgetBase.h:93
KDDockWidgets::Config::frameworkWidgetFactory
FrameworkWidgetFactory * frameworkWidgetFactory() const
getter for the framework widget factory
Definition: Config.cpp:143
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:822
QRect::isNull
bool isNull() const const
KDDockWidgets::DockWidgetBase::Option_DeleteOnClose
@ Option_DeleteOnClose
Deletes the DockWidget when closed.
Definition: DockWidgetBase.h:79
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:211
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:471
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:252
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:334
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:827
KDDockWidgets::DockWidgetBase::titleBar
TitleBar * titleBar() const
Returns this dock widget's title bar.
Definition: DockWidgetBase.cpp:353
KDDockWidgets::DockWidgetBase::moveToSideBar
Q_INVOKABLE void moveToSideBar()
Minimizes this dock widget to the MainWindow's side-bar.
Definition: DockWidgetBase.cpp:442
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:424
QEvent
KDDockWidgets::DockWidgetBase::Frame
friend class Frame
Definition: DockWidgetBase.h:532
KDDockWidgets::DockWidgetBase::setTitle
void setTitle(const QString &title)
setter for the dock widget's title
Definition: DockWidgetBase.cpp:243
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:466
QAction
KDDockWidgets::DockWidgetBase::hidden
void hidden()
signal emitted when the DockWidget is hidden. As in QEvent::Hide.
KDDockWidgets
Definition: Config.cpp:36
QScopedValueRollback
KDDockWidgets::DockWidgetBase::setFloatingGeometry
void setFloatingGeometry(QRect geo)
If this dock widget is floating, then sets its geometry to geo.
Definition: DockWidgetBase.cpp:486
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:817
KDDockWidgets::DockWidgetBase::parentChanged
void parentChanged()
signal emitted when the parent changed QtQuick already has QQuickItem::parentChanged(),...
KDDockWidgets::DockWidgetBase::tabIndex
int tabIndex() const
Returns which tab index this dock widget occupies in the tab widget it's contained in.
Definition: DockWidgetBase.cpp:312
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:320
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:266
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:297
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:271
KDDockWidgets::DockWidgetBase::IconPlace::TabBar
@ TabBar
Qt::WA_PendingMoveEvent
WA_PendingMoveEvent
KDDockWidgets::DockWidgetBase::onShown
void onShown(bool spontaneous)
Definition: DockWidgetBase.cpp:746
QPoint
QEvent::accept
void accept()
KDDockWidgets::Config::self
static Config & self()
returns the singleton Config instance
Definition: Config.cpp:82
FrameworkWidgetFactory.h
A factory class for allowing the user to customize some internal widgets.
QStringList
KDDockWidgets::DockWidgetBase::onParentChanged
void onParentChanged()
Definition: DockWidgetBase.cpp:733

© 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 Mon Mar 7 2022 02:01:20 for KDDockWidgets API Documentation by doxygen 1.8.20