KDDockWidgets API Documentation 2.0
Loading...
Searching...
No Matches
core/MainWindow.cpp
Go to the documentation of this file.
1/*
2 This file is part of KDDockWidgets.
3
4 SPDX-FileCopyrightText: 2019 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
20#include "MainWindow.h"
21#include "MainWindow_p.h"
22#include "kddockwidgets/KDDockWidgets.h"
23#include "DockRegistry.h"
24#include "Layout_p.h"
25#include "core/MDILayout.h"
26#include "core/DropArea.h"
27#include "core/Utils_p.h"
28#include "core/Logging_p.h"
29#include "core/ScopedValueRollback_p.h"
30#include "core/WidgetResizeHandler_p.h"
31#include "core/ViewFactory.h"
32#include "core/LayoutSaver_p.h"
33#include "core/layouting/Item_p.h"
34#include "Platform.h"
35#include "core/DockWidget_p.h"
36#include "core/Group.h"
37#include "core/SideBar.h"
38#include "kddockwidgets/core/views/MainWindowViewInterface.h"
39
40#include <unordered_map>
41#include <algorithm>
42
43using namespace KDDockWidgets;
44using namespace KDDockWidgets::Core;
45
46static Layout *createLayout(MainWindow *mainWindow, MainWindowOptions options)
47{
48 if (options & MainWindowOption_MDI)
49 return new MDILayout(mainWindow->view());
50
51 return new DropArea(mainWindow->view(), options);
52}
53
54MainWindow::MainWindow(View *view, const QString &uniqueName, MainWindowOptions options)
56 , d(new Private(this, uniqueName, options))
57{
58}
59
60void MainWindow::init(const QString &name)
61{
62 d->init();
63 d->m_layout = createLayout(this, d->m_options);
64
65 d->m_persistentCentralDockWidget = d->createPersistentCentralDockWidget(d->name);
66
67 setUniqueName(name);
68
69 d->m_visibleWidgetCountConnection =
70 d->m_layout->d_ptr()->visibleWidgetCountChanged.connect([this](int count) { d->groupCountChanged.emit(count); });
71 view()->d->closeRequested.connect([this](CloseEvent *ev) { d->m_layout->onCloseEvent(ev); });
72}
73
75{
77 delete d;
78}
79
81{
82 assert(widget);
83 KDDW_DEBUG("dock={}", ( void * )widget);
84
85 if (!DockRegistry::self()->affinitiesMatch(d->affinities, widget->affinities())) {
86 KDDW_ERROR("Refusing to dock widget with incompatible affinity. {} {}", widget->affinities(), affinities());
87 return;
88 }
89
90 if (widget->options() & DockWidgetOption_NotDockable) {
91 KDDW_ERROR("Refusing to dock non-dockable widget {}", ( void * )widget);
92 return;
93 }
94
95 if (isMDI()) {
96 // Not applicable to MDI
97 return;
98 }
99
100 if (d->supportsPersistentCentralWidget()) {
101 KDDW_ERROR("Not supported with MainWindowOption_HasCentralWidget."
102 "MainWindowOption_HasCentralWidget can only have 1 widget in the center.",
103 "Use MainWindowOption_HasCentralFrame instead, which is similar but supports "
104 "tabbing");
105 } else if (d->supportsCentralFrame()) {
106 dropArea()->centralGroup()->addTab(widget);
107 } else {
108 KDDW_ERROR("Not supported without MainWindowOption_HasCentralFrame");
109 }
110}
111
113 Core::DockWidget *relativeTo, InitialOption option)
114{
116 KDDW_ERROR("Refusing to dock non-dockable widget dw={}", ( void * )dw);
117 return;
118 }
119
120 if (isMDI()) {
121 // Not applicable to MDI
122 return;
123 }
124
125 dropArea()->addDockWidget(dw, location, relativeTo, option);
126}
127
129{
130 return d->name;
131}
132
133MainWindowOptions MainWindow::options() const
134{
135 return d->m_options;
136}
137
139{
140 return d->m_layout->asDropArea();
141}
142
144{
145 return dropArea();
146}
147
149{
150 return d->m_layout;
151}
152
154{
155 return d->m_layout->asMDILayout();
156}
157
158void MainWindow::setAffinities(const Vector<QString> &affinityNames)
159{
160 Vector<QString> affinities = affinityNames;
162
163 if (d->affinities == affinities)
164 return;
165
166 if (!d->affinities.isEmpty()) {
167 KDDW_ERROR("Affinity is already set, refusing to change."
168 "Submit a feature request with a good justification.");
169 return;
170 }
171
172 d->affinities = affinities;
173}
174
176{
177 return d->affinities;
178}
179
181{
183}
184
186{
188}
189
190CursorPositions MainWindow::Private::allowedResizeSides(SideBarLocation loc) const
191{
192 // When a sidebar is on top, you can only resize its bottom.
193 // and so forth...
194
195 switch (loc) {
199 return CursorPosition_Left;
203 return CursorPosition_Top;
207 }
208
210}
211
212Rect MainWindow::Private::rectForOverlay(Core::Group *group, SideBarLocation location) const
213{
214 Core::SideBar *sb = q->sideBar(location);
215 if (!sb)
216 return {};
217
218 const Rect centralAreaGeo = q->centralAreaGeometry();
219 const Margins centerWidgetMargins = q->centerWidgetMargins();
220
221 Rect rect;
222 const int margin = m_overlayMargin;
223 switch (location) {
226
227 Core::SideBar *leftSideBar = q->sideBar(SideBarLocation::West);
228 Core::SideBar *rightSideBar = q->sideBar(SideBarLocation::East);
229 const int leftSideBarWidth =
230 (leftSideBar && leftSideBar->isVisible()) ? leftSideBar->width() : 0;
231 const int rightSideBarWidth =
232 (rightSideBar && rightSideBar->isVisible()) ? rightSideBar->width() : 0;
233 rect.setHeight(std::max(300, group->view()->minSize().height()));
234 rect.setWidth(centralAreaGeo.width() - margin * 2 - leftSideBarWidth - rightSideBarWidth);
235 rect.moveLeft(margin + leftSideBarWidth);
236 if (location == SideBarLocation::South) {
237 rect.moveTop(centralAreaGeo.bottom() - centerWidgetMargins.bottom() - rect.height()
238 - sb->height());
239 } else {
240 rect.moveTop(centralAreaGeo.y() + sb->height() + centerWidgetMargins.top());
241 }
242 break;
243 }
246 Core::SideBar *topSideBar = q->sideBar(SideBarLocation::North);
247 Core::SideBar *bottomSideBar = q->sideBar(SideBarLocation::South);
248 const int topSideBarHeight =
249 (topSideBar && topSideBar->isVisible()) ? topSideBar->height() : 0;
250 const int bottomSideBarHeight =
251 (bottomSideBar && bottomSideBar->isVisible()) ? bottomSideBar->height() : 0;
252 rect.setWidth(std::max(300, group->view()->minSize().width()));
253 rect.setHeight(centralAreaGeo.height() - topSideBarHeight - bottomSideBarHeight
254 - centerWidgetMargins.top() - centerWidgetMargins.bottom());
255 rect.moveTop(sb->view()->mapTo(q->view(), Point(0, 0)).y() + topSideBarHeight - 1);
256 if (location == SideBarLocation::East) {
257 rect.moveLeft(centralAreaGeo.x() + centralAreaGeo.width() - rect.width() - sb->width()
258 - centerWidgetMargins.right() - margin);
259 } else {
260 rect.moveLeft(margin + centralAreaGeo.x() + centerWidgetMargins.left() + sb->width());
261 }
262
263 break;
264 }
267 break;
268 }
269
270 return rect;
271}
272
273static SideBarLocation opposedSideBarLocationForBorder(Core::LayoutBorderLocation loc)
274{
275 switch (loc) {
276 case Core::LayoutBorderLocation_North:
278 case Core::LayoutBorderLocation_East:
280 case Core::LayoutBorderLocation_West:
282 case Core::LayoutBorderLocation_South:
284 case Core::LayoutBorderLocation_All:
285 case Core::LayoutBorderLocation_Verticals:
286 case Core::LayoutBorderLocation_Horizontals:
287 case Core::LayoutBorderLocation_None:
288 break;
289 }
290
291 KDDW_ERROR("Unknown loc={}", loc);
293}
294
295static SideBarLocation sideBarLocationForBorder(Core::LayoutBorderLocations loc)
296{
297 switch (loc) {
298 case Core::LayoutBorderLocation_North:
300 case Core::LayoutBorderLocation_East:
302 case Core::LayoutBorderLocation_West:
304 case Core::LayoutBorderLocation_South:
306 case Core::LayoutBorderLocation_All:
307 case Core::LayoutBorderLocation_Verticals:
308 case Core::LayoutBorderLocation_Horizontals:
309 case Core::LayoutBorderLocation_None:
310 break;
311 }
312
314}
315
316SideBarLocation MainWindow::Private::preferredSideBar(Core::DockWidget *dw) const
317{
318 Core::Item *item = q->layout()->itemForFrame(dw->d->group());
319 if (!item) {
320 KDDW_ERROR("No item for dock widget");
322 }
323
324 const Core::LayoutBorderLocations borders = item->adjacentLayoutBorders();
325 const double aspectRatio = dw->width() / (std::max(1, dw->height()) * 1.0);
326
328 if (borders == Core::LayoutBorderLocation_All) {
329 return aspectRatio > 1.0 ? SideBarLocation::South : SideBarLocation::East;
330 }
331
333 for (auto borderLoc :
334 { Core::LayoutBorderLocation_North, Core::LayoutBorderLocation_East,
335 Core::LayoutBorderLocation_West, Core::LayoutBorderLocation_South }) {
336 if (borders == (Core::LayoutBorderLocation_All & ~borderLoc))
337 return opposedSideBarLocationForBorder(borderLoc);
338 }
339
341 if ((borders & Core::LayoutBorderLocation_Verticals)
342 == Core::LayoutBorderLocation_Verticals) {
343 // We could measure the distance to the top though.
345 }
346
348 if ((borders & Core::LayoutBorderLocation_Horizontals)
349 == Core::LayoutBorderLocation_Horizontals) {
350 // We could measure the distance to the left though.
352 }
353
354 // 5. It's in a corner
355 if (borders == (Core::LayoutBorderLocation_West | Core::LayoutBorderLocation_South)) {
356 return aspectRatio > 1.0 ? SideBarLocation::South : SideBarLocation::West;
357 } else if (borders
358 == (Core::LayoutBorderLocation_East | Core::LayoutBorderLocation_South)) {
359 return aspectRatio > 1.0 ? SideBarLocation::South : SideBarLocation::East;
360 } else if (borders
361 == (Core::LayoutBorderLocation_West | Core::LayoutBorderLocation_North)) {
362 return aspectRatio > 1.0 ? SideBarLocation::North : SideBarLocation::West;
363 } else if (borders
364 == (Core::LayoutBorderLocation_East | Core::LayoutBorderLocation_North)) {
365 return aspectRatio > 1.0 ? SideBarLocation::North : SideBarLocation::East;
366 }
367
368
369 {
370 // 6. It's only touching 1 border
372 if (loc != SideBarLocation::None)
373 return loc;
374 }
375
376 // It's not touching any border, use aspect ratio.
377 return aspectRatio > 1.0 ? SideBarLocation::South : SideBarLocation::West;
378}
379
380void MainWindow::Private::updateOverlayGeometry(Size suggestedSize)
381{
382 if (!m_overlayedDockWidget)
383 return;
384
385 Core::SideBar *sb = q->sideBarForDockWidget(m_overlayedDockWidget);
386 if (!sb) {
387 KDDW_ERROR("Expected a sidebar");
388 return;
389 }
390
391 const Rect defaultGeometry = rectForOverlay(m_overlayedDockWidget->d->group(), sb->location());
392 Rect newGeometry = defaultGeometry;
393
394 Core::Group *group = m_overlayedDockWidget->d->group();
395
396 if (suggestedSize.isValid() && !suggestedSize.isEmpty()) {
397 // Let's try to honour the suggested overlay size
398 switch (sb->location()) {
400 const int maxHeight = q->height() - group->pos().y() - 10; // gap
401 newGeometry.setHeight(std::min(suggestedSize.height(), maxHeight));
402 break;
403 }
405 const int maxHeight = sb->pos().y() - m_layout->view()->pos().y() - 10; // gap
406 const int bottom = newGeometry.bottom();
407 newGeometry.setHeight(std::min(suggestedSize.height(), maxHeight));
408 newGeometry.moveBottom(bottom);
409 break;
410 }
412 const int maxWidth = sb->pos().x() - m_layout->view()->pos().x() - 10; // gap
413 const int right = newGeometry.right();
414 newGeometry.setWidth(std::min(suggestedSize.width(), maxWidth));
415 newGeometry.moveRight(right);
416 break;
417 }
419 const int maxWidth = q->width() - group->pos().x() - 10; // gap
420 newGeometry.setWidth(std::min(suggestedSize.width(), maxWidth));
421 break;
422 }
425 KDDW_ERROR("Unexpected sidebar value");
426 break;
427 }
428 }
429
430 m_overlayedDockWidget->d->group()->view()->setGeometry(newGeometry);
431}
432
433void MainWindow::Private::clearSideBars()
434{
437 if (Core::SideBar *sb = q->sideBar(loc))
438 sb->clear();
439 }
440}
441
442Rect MainWindow::Private::windowGeometry() const
443{
449
450 if (Core::Window::Ptr window = q->view()->window())
451 return window->geometry();
452
453 return q->window()->geometry();
454}
455
457{
458 moveToSideBar(dw, d->preferredSideBar(dw));
459}
460
462{
464 return;
465
466 if (Core::SideBar *sb = sideBar(location)) {
467 ScopedValueRollback rollback(dw->d->m_isMovingToSideBar, true);
468 dw->forceClose();
469 sb->addDockWidget(dw);
470 } else {
471 // Shouldn't happen
472 KDDW_ERROR("Minimization supported, probably disabled in Config::self().flags()");
473 }
474}
475
477{
478 // First un-overlay it, if it's overlayed
479 if (dw == d->m_overlayedDockWidget)
481
483 if (!sb) {
484 // Doesn't happen
485 KDDW_ERROR("Dock widget isn't in any sidebar");
486 return;
487 }
488
489 sb->removeDockWidget(dw);
490 dw->setFloating(false); // dock it
491}
492
494{
495 if (!dw || dw->isPersistentCentralDockWidget())
496 return;
497
498 const Core::SideBar *sb = sideBarForDockWidget(dw);
499 if (!sb) {
500 KDDW_ERROR("You need to add the dock widget to the sidebar before you can overlay it");
501 return;
502 }
503
504 if (d->m_overlayedDockWidget == dw) {
505 // Already overlayed
506 return;
507 }
508
509 // We only support one overlay at a time, remove any existing overlay
511
512 auto group = new Core::Group(nullptr, FrameOption_IsOverlayed);
513 group->setParentView(view());
514 d->m_overlayedDockWidget = dw;
515 group->addTab(dw);
516 d->updateOverlayGeometry(dw->d->lastPosition()->lastOverlayedGeometry(sb->location()).size());
517
518 group->setAllowedResizeSides(d->allowedResizeSides(sb->location()));
519 group->view()->show();
520
521 dw->d->isOverlayedChanged.emit(true);
522}
523
525{
526 const bool wasOverlayed = d->m_overlayedDockWidget == dw;
527 clearSideBarOverlay(); // Because only 1 dock widget can be overlayed each time
528 if (!wasOverlayed) {
530 }
531}
532
533void MainWindow::clearSideBarOverlay(bool deleteFrame)
534{
535 if (!d->m_overlayedDockWidget)
536 return;
537
538 auto overlayedDockWidget = d->m_overlayedDockWidget;
539 d->m_overlayedDockWidget = nullptr;
540
541 Core::Group *group = overlayedDockWidget->d->group();
542 if (!group) { // prophylactic check
543 return;
544 }
545
547 overlayedDockWidget->d->lastPosition()->setLastOverlayedGeometry(loc, group->geometry());
548
549 group->unoverlay();
550
551 if (deleteFrame) {
552 overlayedDockWidget->setParent(nullptr);
553
554 {
555 ScopedValueRollback guard(overlayedDockWidget->d->m_removingFromOverlay, true);
557 }
558
559 overlayedDockWidget->d->isOverlayedChanged.emit(false);
560 overlayedDockWidget = nullptr;
561 delete group;
562 } else {
563 // No cleanup, just unset. When we drag the overlay it becomes a normal floating window
564 // meaning we reuse Frame. Don't delete it.
565 overlayedDockWidget->d->isOverlayedChanged.emit(false);
566 overlayedDockWidget = nullptr;
567 }
568}
569
571{
574
575 if (Core::SideBar *sb = sideBar(loc)) {
576 if (sb->containsDockWidget(const_cast<Core::DockWidget *>(dw)))
577 return sb;
578 }
579 }
580
581 return nullptr;
582}
583
585{
586 return d->m_overlayedDockWidget;
587}
588
590{
591 if (Core::SideBar *sb = sideBar(loc)) {
592 return !sb->isEmpty(); // isVisible() is always true, but its height is 0 when empty.
593 }
594
595 return false;
596}
597
599{
602 if (sideBarIsVisible(loc))
603 return true;
604 }
605
606 return false;
607}
608
609bool MainWindow::isMDI() const
610{
611 return d->m_options & MainWindowOption_MDI;
612}
613
614bool MainWindow::closeDockWidgets(bool force)
615{
616 bool allClosed = true;
617
618 const auto dockWidgets = d->m_layout->dockWidgets();
619 for (Core::DockWidget *dw : dockWidgets) {
620 Core::Group *group = dw->d->group();
621
622 if (force) {
623 dw->forceClose();
624 } else {
625 const bool closed = dw->view()->close();
626 allClosed = allClosed && closed;
627 }
628
629 if (group->beingDeletedLater()) {
630 // The dock widget was closed and this group is empty, delete immediately instead of
631 // waiting. I'm not a big fan of deleting stuff later, as state becomes inconsistent
632
633 // Empty groups are historically deleted later since they are triggered by mouse click
634 // on the title bar, and the title bar is inside the group.
635 // When doing it programmatically we can delete immediately.
636
637 delete group;
638 }
639 }
640
641 return allClosed;
642}
643
644void MainWindow::setUniqueName(const QString &uniqueName)
645{
646 if (uniqueName.isEmpty())
647 return;
648
649 if (d->name.isEmpty()) {
650 d->name = uniqueName;
651 d->uniqueNameChanged.emit();
653 } else {
654 KDDW_ERROR("Already has a name. {} {}", this->uniqueName(), uniqueName);
655 }
656}
657
658bool MainWindow::deserialize(const LayoutSaver::MainWindow &mw)
659{
660 if (mw.options != options()) {
661 KDDW_ERROR("Refusing to restore MainWindow with different options ; expected={}, has={}", int(mw.options), int(options()));
662 return false;
663 }
664
665 if (d->affinities != mw.affinities) {
666 KDDW_ERROR("Affinity name changed from {} to {}", d->affinities, mw.affinities);
667
668 d->affinities = mw.affinities;
669 }
670
671 const bool success = layout()->deserialize(mw.multiSplitterLayout);
672
673 // Restore the SideBars
674 d->clearSideBars();
677 Core::SideBar *sb = sideBar(loc);
678 if (!sb)
679 continue;
680
681 const Vector<QString> dockWidgets = mw.dockWidgetsForSideBar(loc);
682 for (const QString &uniqueName : dockWidgets) {
683
686 if (!dw) {
687 KDDW_ERROR("Could not find dock widget {} . Won't restore it to sidebar", uniqueName);
688 continue;
689 }
690
691 sb->addDockWidget(dw);
692 }
693 }
694
695 // Commented-out for now, we don't want to restore the popup/overlay. popups are perishable
696 // if (!mw.overlayedDockWidget.isEmpty())
697 // overlayOnSideBar(DockRegistry::self()->dockByName(mw.overlayedDockWidget));
698
699 return success;
700}
701
702LayoutSaver::MainWindow MainWindow::serialize() const
703{
704 LayoutSaver::MainWindow m;
705
706 Window::Ptr window = view()->window();
707
708 m.options = options();
709 m.geometry = d->windowGeometry();
710 m.normalGeometry = view()->normalGeometry();
711 m.isVisible = isVisible();
712 m.uniqueName = uniqueName();
713 m.screenIndex = Platform::instance()->screenNumberFor(view());
714 m.screenSize = Platform::instance()->screenSizeFor(view());
715 m.multiSplitterLayout = layout()->serialize();
716 m.affinities = d->affinities;
717 m.windowState = window ? window->windowState() : WindowState::None;
718
721 if (Core::SideBar *sb = sideBar(loc)) {
722 const Vector<QString> dockwidgets = sb->serialize();
723 if (!dockwidgets.isEmpty())
724 m.dockWidgetsPerSideBar[loc] = dockwidgets;
725 }
726 }
727
728 return m;
729}
730
731void MainWindow::setPersistentCentralView(std::shared_ptr<View> widget)
732{
733 if (!d->supportsPersistentCentralWidget()) {
734 KDDW_ERROR("MainWindow::setPersistentCentralWidget() requires "
735 "MainWindowOption_HasCentralWidget");
736 return;
737 }
738
739 if (auto dw = d->m_persistentCentralDockWidget) {
740 dw->setGuestView(widget);
741 } else {
742 KDDW_ERROR("Unexpected null central dock widget");
743 }
744}
745
746std::shared_ptr<View> MainWindow::persistentCentralView() const
747{
748 if (auto dw = d->m_persistentCentralDockWidget)
749 return dw->guestView();
750
751 return {};
752}
753
754void MainWindow::setContentsMargins(int left, int top, int right, int bottom)
755{
756 auto v = dynamic_cast<Core::MainWindowViewInterface *>(view());
757 v->setContentsMargins(left, top, right, bottom);
758}
759
761{
762 auto v = dynamic_cast<Core::MainWindowViewInterface *>(view());
763 return v->centerWidgetMargins();
764}
765
767{
768 auto it = d->m_sideBars.find(loc);
769 return it == d->m_sideBars.cend() ? nullptr : it->second;
770}
771
773{
774 auto v = dynamic_cast<Core::MainWindowViewInterface *>(view());
775 return v->centralAreaGeometry();
776}
777
779{
780 return d->m_overlayMargin;
781}
782
783void MainWindow::setOverlayMargin(int margin)
784{
785 if (margin == d->m_overlayMargin)
786 return;
787
788 d->m_overlayMargin = margin;
789 d->overlayMarginChanged.emit(margin);
790}
void setParentView(View *parent)
View * view() const
Returns the view associated with this controller, if any.
std::shared_ptr< View > window() const
The DockWidget base-class. DockWidget and Core::DockWidget are only split in two so we can share some...
bool setFloating(bool floats)
setter to make the dock widget float or dock.
SideBarLocation sideBarLocation() const
Returns whether this dock widget is in a side bar, and which. SideBarLocation::None is returned if it...
Vector< QString > affinities() const
Returns the affinity name. Empty by default.
std::shared_ptr< View > guestView() const
Like widget() but returns a view.
void setGuestView(std::shared_ptr< View > guest)
sets the widget which this dock widget hosts.
bool isPersistentCentralDockWidget() const
Returns whether this dock widget is the main window persistent central widget This only applies when ...
DockWidgetOptions options() const
Returns the dock widget's options which control behaviour.
void forceClose()
Like QWidget::close() but the hosted widget won't be asked if we should close.
void layoutParentContainerEqually(DockWidget *)
void addDockWidget(DockWidget *dw, KDDockWidgets::Location location, DockWidget *relativeTo, InitialOption initialOption={})
void layoutEqually()
See docs for MainWindowBase::layoutEqually()
void addTab(DockWidget *, InitialOption={})
Adds a widget into the Group's Stack.
void unoverlay()
clears the FrameOption_IsOverlayed flag. For example, if you drag a side-bar overlay,...
void setAllowedResizeSides(CursorPositions sides)
Usually we do resize via the native window manager, but if a widget is docked like in MDI mode,...
bool beingDeletedLater() const
Returns whether a deleteLater has already been issued.
The widget (QWidget or QQuickItem) which holds a layout of dock widgets.
Definition Layout.h:57
virtual bool deserialize(const LayoutSaver::MultiSplitter &)
Definition Layout.cpp:288
LayoutSaver::MultiSplitter serialize() const
Definition Layout.cpp:323
The MDILayout class implements a layout suitable for MDI style docking. Where dock widgets are free t...
The interface that MainWindow views should implement.
virtual Margins centerWidgetMargins() const =0
virtual void setContentsMargins(int left, int top, int right, int bottom)=0
The MainWindow base-class. MainWindow and MainWindowBase are only split in two so we can share some c...
bool sideBarIsVisible(KDDockWidgets::SideBarLocation location) const
Returns whether the specified sidebar is visible.
void setAffinities(const Vector< QString > &names)
Sets the affinities names. Dock widgets can only dock into main windows of the same affinity.
void clearSideBarOverlay(bool deleteFrame=true)
closes any overlayed dock widget. The sidebar still displays them as button.
QString uniqueName() const
Returns the unique name that was passed via constructor. Used internally by the save/restore mechanis...
void setOverlayMargin(int margin)
Sets the margin used by overlay docks. Does not modify currently overlayed docks.
void addDockWidgetAsTab(KDDockWidgets::Core::DockWidget *dockwidget)
Docks a DockWidget into the central group, tabbed.
void overlayOnSideBar(KDDockWidgets::Core::DockWidget *dw)
Shows the dock widget overlayed on top of the main window, placed next to the sidebar.
friend class KDDockWidgets::QtWidgets::MainWindow
std::shared_ptr< View > persistentCentralView() const
KDDockWidgets::Core::SideBar * sideBarForDockWidget(const KDDockWidgets::Core::DockWidget *dw) const
Returns the sidebar this dockwidget is in. nullptr if not in any.
void toggleOverlayOnSideBar(KDDockWidgets::Core::DockWidget *dw)
Shows or hides an overlay. It's assumed the dock widget is already in a side-bar.
void layoutParentContainerEqually(KDDockWidgets::Core::DockWidget *dockWidget)
like layoutEqually() but starts with the container that has dockWidget. While layoutEqually() starts ...
Margins centerWidgetMargins() const
bool anySideBarIsVisible() const
Returns whether any side bar is visible.
void addDockWidget(KDDockWidgets::Core::DockWidget *dockWidget, KDDockWidgets::Location location, KDDockWidgets::Core::DockWidget *relativeTo=nullptr, KDDockWidgets::InitialOption initialOption={})
Docks a DockWidget into this main window.
int overlayMargin() const
Returns the margin used by overlay docks. Default: 1.
void setContentsMargins(int l, int t, int r, int b)
Sets the content's margins.
void setPersistentCentralView(std::shared_ptr< View > widget)
Sets a persistent central widget. It can't be detached.
MDILayout * mdiLayout() const
void layoutEqually()
layouts all the widgets so they have an equal size within their parent container
DropArea * multiSplitter() const
MainWindowOptions options() const
Returns the main window options that were passed via constructor.
Core::DockWidget * overlayedDockWidget() const
returns the dock widget which is currently overlayed. nullptr if none. This is only relevant when usi...
void moveToSideBar(KDDockWidgets::Core::DockWidget *dw)
Moves the dock widget into one of the MainWindow's sidebar. Means the dock widget is removed from the...
bool closeDockWidgets(bool force=false)
Closes all dock widgets which are docked into this main window This is convenience to calling DockWid...
void init(const QString &name)
bool isMDI() const
Returns whether this main window is using an MDI layout. In other words, returns true if MainWindowOp...
Vector< QString > affinities() const
Returns the list of affinity names. Empty by default.
void restoreFromSideBar(KDDockWidgets::Core::DockWidget *dw)
Removes the dock widget from the sidebar and docks it into the main window again.
Core::SideBar * sideBar(SideBarLocation location) const
Returns the side bar at the specified location.
void setUniqueName(const QString &uniqueName)
static Platform * instance()
Returns the platform singleton.
virtual Size screenSizeFor(View *) const =0
Returns the size of the screen where this view is in.
virtual int screenNumberFor(View *) const =0
Returns the screen index for the specified view or window. It's up to the platform to decide how scre...
Vector< QString > serialize() const
returns a serialization of this sidebar's state Currently it's just a list of dock widget ids
void clear()
clears the sidebar (removes all dock widgets from it)
void removeDockWidget(DockWidget *dw)
SideBarLocation location() const
returns the sidebar's location in the main window
bool containsDockWidget(DockWidget *) const
void addDockWidget(DockWidget *dw)
bool isEmpty() const
returns whether there's no dock widgets
virtual void show()=0
virtual Size minSize() const =0
virtual Rect normalGeometry() const =0
virtual std::shared_ptr< Core::Window > window() const =0
Returns the window this view is inside For the Qt frontend, this wraps a QWindow. Like QWidget::windo...
virtual bool close()=0
virtual Point mapTo(View *, Point) const =0
@ CreateIfNotFound
Creates the dock widget via the user's widget factory in case it doesn't exist.
Q_INVOKABLE KDDockWidgets::Core::DockWidget * dockByName(const QString &, KDDockWidgets::DockRegistry::DockByNameFlags={}) const
void registerMainWindow(Core::MainWindow *)
static DockRegistry * self()
void unregisterMainWindow(Core::MainWindow *)
A MultiSplitter with support for drop indicators when hovering over.
static Layout * createLayout(MainWindow *mainWindow, MainWindowOptions options)
static SideBarLocation opposedSideBarLocationForBorder(Core::LayoutBorderLocation loc)
static SideBarLocation sideBarLocationForBorder(Core::LayoutBorderLocations loc)
ViewType
Each View type also has a specific Controller associated with, except for ViewType::None.
Definition Controller.h:26
Class to abstract QAction, so code still works with QtQuick and Flutter.
@ MainWindowOption_MDI
‍Makes the MainWindow always have a central group, for tabbing documents
SideBarLocation
Each main window supports 4 sidebars.
@ DockWidgetOption_NotDockable
The DockWidget can't be docked, it's always floating.
bool isEmpty() const const
QTextStream & right(QTextStream &stream)
QMainWindow sub-class to enable KDDockWidgets support.
Struct describing the preferred dock widget size and visibility when adding it to a layout.

© 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 by doxygen 1.9.8