21 #include "private/DockRegistry_p.h"
22 #include "private/MDILayoutWidget_p.h"
23 #include "private/DropArea_p.h"
24 #include "private/Frame_p.h"
25 #include "private/Utils_p.h"
26 #include "private/SideBar_p.h"
27 #include "private/Logging_p.h"
28 #include "private/WidgetResizeHandler_p.h"
30 #include "private/DropAreaWithCentralFrame_p.h"
31 #include "private/LayoutSaver_p.h"
32 #include "private/DockWidgetBase_p.h"
35 #ifdef KDDOCKWIDGETS_QTQUICK
46 return new MDILayoutWidget(mainWindow);
48 return new DropAreaWithCentralFrame(mainWindow, options);
51 class MainWindowBase::Private
58 , m_persistentCentralDockWidget(createPersistentCentralDockWidget(
uniqueName))
62 bool supportsCentralFrame()
const
67 bool supportsPersistentCentralWidget()
const
79 if (!supportsPersistentCentralWidget())
83 dw->dptr()->m_isPersistentCentralDockWidget =
true;
84 Frame *frame =
dropArea()->m_centralFrame;
86 qWarning() << Q_FUNC_INFO <<
"Expected central frame";
94 DropAreaWithCentralFrame *
dropArea()
const
96 return qobject_cast<DropAreaWithCentralFrame *>(m_layoutWidget);
103 void updateOverlayGeometry(
QSize suggestedSize);
104 void clearSideBars();
108 const MainWindowOptions m_options;
111 LayoutWidget *
const m_layoutWidget;
118 , d(new Private(this, uniqueName, options))
122 connect(d->m_layoutWidget, &LayoutWidget::visibleWidgetCountChanged,
this,
128 DockRegistry::self()->unregisterMainWindow(
this);
135 qCDebug(addwidget) << Q_FUNC_INFO << widget;
137 if (!DockRegistry::self()->affinitiesMatch(d->affinities, widget->affinities())) {
138 qWarning() << Q_FUNC_INFO <<
"Refusing to dock widget with incompatible affinity."
144 qWarning() << Q_FUNC_INFO <<
"Refusing to dock non-dockable widget" << widget;
153 if (d->supportsPersistentCentralWidget()) {
154 qWarning() << Q_FUNC_INFO <<
"Not supported with MainWindowOption_HasCentralWidget."
155 <<
"MainWindowOption_HasCentralWidget can only have 1 widget in the center."
156 <<
"Use MainWindowOption_HasCentralFrame instead, which is similar but supports tabbing";
157 }
else if (d->supportsCentralFrame()) {
158 dropArea()->m_centralFrame->addWidget(widget);
160 qWarning() << Q_FUNC_INFO <<
"Not supported without MainWindowOption_HasCentralFrame";
168 qWarning() << Q_FUNC_INFO <<
"Refusing to dock non-dockable widget" << dw;
177 dropArea()->addDockWidget(dw, location, relativeTo, option);
192 return qobject_cast<DropAreaWithCentralFrame *>(d->m_layoutWidget);
202 return d->m_layoutWidget;
218 if (!d->affinities.isEmpty()) {
219 qWarning() << Q_FUNC_INFO
220 <<
"Affinity is already set, refusing to change."
221 <<
"Submit a feature request with a good justification.";
230 return d->affinities;
240 dropArea()->layoutParentContainerEqually(dockWidget);
243 CursorPositions MainWindowBase::Private::allowedResizeSides(
SideBarLocation loc)
const
266 SideBar *sb = q->sideBar(location);
270 const QRect centralAreaGeo = q->centralAreaGeometry();
271 const QMargins centerWidgetMargins = q->centerWidgetMargins();
274 const int margin = 1;
281 const int leftSideBarWidth = (leftSideBar && leftSideBar->isVisible()) ? leftSideBar->width()
283 const int rightSideBarWidth = (rightSideBar && rightSideBar->isVisible()) ? rightSideBar->width()
285 rect.
setHeight(qMax(300, frame->minSize().height()));
286 rect.
setWidth(centralAreaGeo.
width() - margin * 2 - leftSideBarWidth - rightSideBarWidth);
287 rect.
moveLeft(margin + leftSideBarWidth);
291 rect.
moveTop(centralAreaGeo.
y() + sb->height() + centerWidgetMargins.
top());
299 const int topSideBarHeight = (topSideBar && topSideBar->isVisible()) ? topSideBar->height()
301 const int bottomSideBarHeight = (bottomSideBar && bottomSideBar->isVisible()) ? bottomSideBar->height()
303 rect.
setWidth(qMax(300, frame->minSize().width()));
304 rect.
setHeight(centralAreaGeo.
height() - topSideBarHeight - bottomSideBarHeight - centerWidgetMargins.
top() - centerWidgetMargins.
bottom());
305 rect.
moveTop(sb->mapTo(q,
QPoint(0, 0)).y() + topSideBarHeight - 1);
309 rect.
moveLeft(margin + centralAreaGeo.
x() + centerWidgetMargins.
left() + sb->width());
324 case Layouting::LayoutBorderLocation_North:
326 case Layouting::LayoutBorderLocation_East:
328 case Layouting::LayoutBorderLocation_West:
330 case Layouting::LayoutBorderLocation_South:
332 case Layouting::LayoutBorderLocation_All:
333 case Layouting::LayoutBorderLocation_Verticals:
334 case Layouting::LayoutBorderLocation_Horizontals:
335 case Layouting::LayoutBorderLocation_None:
339 qWarning() << Q_FUNC_INFO <<
"Unknown loc" << loc;
346 case Layouting::LayoutBorderLocation_North:
348 case Layouting::LayoutBorderLocation_East:
350 case Layouting::LayoutBorderLocation_West:
352 case Layouting::LayoutBorderLocation_South:
354 case Layouting::LayoutBorderLocation_All:
355 case Layouting::LayoutBorderLocation_Verticals:
356 case Layouting::LayoutBorderLocation_Horizontals:
357 case Layouting::LayoutBorderLocation_None:
368 Layouting::Item *item = q->layoutWidget()->itemForFrame(dw->d->frame());
370 qWarning() << Q_FUNC_INFO <<
"No item for dock widget";
374 const Layouting::LayoutBorderLocations borders = item->adjacentLayoutBorders();
375 const qreal aspectRatio = dw->width() / (std::max(1, dw->height()) * 1.0);
378 if (borders == Layouting::LayoutBorderLocation_All) {
384 for (
auto borderLoc : { Layouting::LayoutBorderLocation_North, Layouting::LayoutBorderLocation_East,
385 Layouting::LayoutBorderLocation_West, Layouting::LayoutBorderLocation_South }) {
386 if (borders == (Layouting::LayoutBorderLocation_All & ~borderLoc))
391 if ((borders & Layouting::LayoutBorderLocation_Verticals) == Layouting::LayoutBorderLocation_Verticals) {
397 if ((borders & Layouting::LayoutBorderLocation_Horizontals) == Layouting::LayoutBorderLocation_Horizontals) {
403 if (borders == (Layouting::LayoutBorderLocation_West | Layouting::LayoutBorderLocation_South)) {
406 }
else if (borders == (Layouting::LayoutBorderLocation_East | Layouting::LayoutBorderLocation_South)) {
409 }
else if (borders == (Layouting::LayoutBorderLocation_West | Layouting::LayoutBorderLocation_North)) {
412 }
else if (borders == (Layouting::LayoutBorderLocation_East | Layouting::LayoutBorderLocation_North)) {
430 void MainWindowBase::Private::updateOverlayGeometry(
QSize suggestedSize)
432 if (!m_overlayedDockWidget)
435 SideBar *sb = q->sideBarForDockWidget(m_overlayedDockWidget);
437 qWarning() << Q_FUNC_INFO <<
"Expected a sidebar";
441 const QRect defaultGeometry = rectForOverlay(m_overlayedDockWidget->d->frame(), sb->location());
442 QRect newGeometry = defaultGeometry;
444 Frame *frame = m_overlayedDockWidget->d->frame();
448 switch (sb->location()) {
450 const int maxHeight = q->height() - frame->pos().y() - 10;
455 const int maxHeight = sb->pos().y() - m_layoutWidget->pos().y() - 10;
456 const int bottom = newGeometry.
bottom();
462 const int maxWidth = sb->pos().x() - m_layoutWidget->pos().x() - 10;
469 const int maxWidth = q->width() - frame->pos().x() - 10;
474 qWarning() << Q_FUNC_INFO <<
"Unexpected sidebar value";
479 m_overlayedDockWidget->d->frame()->QWidgetAdapter::setGeometry(newGeometry);
482 void MainWindowBase::Private::clearSideBars()
486 if (SideBar *sb = q->sideBar(loc))
501 if (SideBar *sb =
sideBar(location)) {
504 sb->addDockWidget(dw);
507 qWarning() << Q_FUNC_INFO <<
"Minimization supported, probably disabled in Config::self().flags()";
514 if (dw == d->m_overlayedDockWidget)
520 qWarning() << Q_FUNC_INFO <<
"Dock widget isn't in any sidebar";
524 sb->removeDockWidget(dw);
535 qWarning() << Q_FUNC_INFO <<
"You need to add the dock widget to the sidebar before you can overlay it";
539 if (d->m_overlayedDockWidget == dw) {
548 d->m_overlayedDockWidget = dw;
549 frame->addWidget(dw);
550 d->updateOverlayGeometry(dw->d->lastPositions().lastOverlayedGeometry(sb->location()).size());
552 frame->setAllowedResizeSides(d->allowedResizeSides(sb->location()));
553 frame->QWidgetAdapter::show();
560 const bool wasOverlayed = d->m_overlayedDockWidget == dw;
569 if (!d->m_overlayedDockWidget)
572 Frame *frame = d->m_overlayedDockWidget->d->frame();
574 d->m_overlayedDockWidget =
nullptr;
578 const SideBarLocation loc = d->m_overlayedDockWidget->sideBarLocation();
579 d->m_overlayedDockWidget->d->lastPositions().setLastOverlayedGeometry(
580 loc, frame->QWidgetAdapter::geometry());
585 d->m_overlayedDockWidget->setParent(
nullptr);
586 Q_EMIT d->m_overlayedDockWidget->isOverlayedChanged(
false);
587 d->m_overlayedDockWidget =
nullptr;
592 Q_EMIT d->m_overlayedDockWidget->isOverlayedChanged(
false);
593 d->m_overlayedDockWidget =
nullptr;
602 if (SideBar *sb =
sideBar(loc)) {
613 return d->m_overlayedDockWidget;
618 if (SideBar *sb =
sideBar(loc)) {
619 return !sb->isEmpty();
643 bool allClosed =
true;
645 const auto dockWidgets = d->m_layoutWidget->dockWidgets();
647 Frame *frame = dw->d->frame();
652 const bool closed = dw->close();
653 allClosed = allClosed && closed;
656 if (frame->beingDeletedLater()) {
676 if (d->name.isEmpty()) {
679 DockRegistry::self()->registerMainWindow(
this);
687 if (d->m_overlayedDockWidget)
688 d->updateOverlayGeometry(d->m_overlayedDockWidget->d->frame()->QWidgetAdapter::size());
691 bool MainWindowBase::deserialize(
const LayoutSaver::MainWindow &mw)
694 qWarning() << Q_FUNC_INFO <<
"Refusing to restore MainWindow with different options"
695 <<
"; expected=" << mw.options <<
"; has=" <<
options();
699 if (d->affinities != mw.affinities) {
700 qWarning() << Q_FUNC_INFO <<
"Affinty name changed from" << d->affinities
701 <<
"; to" << mw.affinities;
703 d->affinities = mw.affinities;
706 const bool success =
layoutWidget()->deserialize(mw.multiSplitterLayout);
720 qWarning() << Q_FUNC_INFO <<
"Could not find dock widget" <<
uniqueName
721 <<
". Won't restore it to sidebar";
725 sb->addDockWidget(dw);
736 LayoutSaver::MainWindow MainWindowBase::serialize()
const
738 LayoutSaver::MainWindow m;
744 m.screenIndex = screenNumberForWidget(
this);
745 m.screenSize = screenSizeForWidget(
this);
747 m.affinities = d->affinities;
752 if (SideBar *sb =
sideBar(loc)) {
755 m.dockWidgetsPerSideBar.
insert(loc, dockwidgets);
772 if (!d->supportsPersistentCentralWidget()) {
773 qWarning() <<
"MainWindow::setPersistentCentralWidget() requires MainWindowOption_HasCentralWidget";
777 auto dw = d->m_persistentCentralDockWidget;
781 qWarning() << Q_FUNC_INFO <<
"Unexpected null central dock widget";
787 if (
auto dw = d->m_persistentCentralDockWidget)