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"
39 return new MDILayoutWidget(mainWindow);
41 return new DropAreaWithCentralFrame(mainWindow, options);
44 class MainWindowBase::Private
54 bool supportsCentralFrame()
const
60 void updateOverlayedDockWidgetGeometries()
62 if (m_overlayedDockWidget)
63 updateOverlayGeometry(m_overlayedDockWidget->d->frame()->QWidgetAdapter::size());
70 void updateOverlayGeometry(
QSize suggestedSize);
75 const MainWindowOptions m_options;
78 LayoutWidget *
const m_layoutWidget;
84 , d(new Private(this, options))
88 connect(d->m_layoutWidget, &LayoutWidget::visibleWidgetCountChanged,
this,
92 d->updateOverlayedDockWidgetGeometries();
98 DockRegistry::self()->unregisterMainWindow(
this);
105 qCDebug(addwidget) << Q_FUNC_INFO << widget;
107 if (!DockRegistry::self()->affinitiesMatch(d->affinities, widget->affinities())) {
108 qWarning() << Q_FUNC_INFO <<
"Refusing to dock widget with incompatible affinity."
114 qWarning() << Q_FUNC_INFO <<
"Refusing to dock non-dockable widget" << widget;
123 if (d->supportsCentralFrame()) {
124 dropArea()->m_centralFrame->addWidget(widget);
126 qWarning() << Q_FUNC_INFO <<
"Not supported without MainWindowOption_HasCentralFrame";
134 qWarning() << Q_FUNC_INFO <<
"Refusing to dock non-dockable widget" << dw;
143 dropArea()->addDockWidget(dw, location, relativeTo, option);
158 return qobject_cast<DropAreaWithCentralFrame *>(d->m_layoutWidget);
168 return d->m_layoutWidget;
184 if (!d->affinities.isEmpty()) {
185 qWarning() << Q_FUNC_INFO
186 <<
"Affinity is already set, refusing to change."
187 <<
"Submit a feature request with a good justification.";
196 return d->affinities;
206 dropArea()->layoutParentContainerEqually(dockWidget);
209 CursorPositions MainWindowBase::Private::allowedResizeSides(
SideBarLocation loc)
const
232 SideBar *sb = q->sideBar(location);
236 const QRect centralAreaGeo = q->centralAreaGeometry();
237 const QMargins centerWidgetMargins = q->centerWidgetMargins();
240 const int margin = 1;
247 const int leftSideBarWidth = (leftSideBar && leftSideBar->isVisible()) ? leftSideBar->width()
249 const int rightSideBarWidth = (rightSideBar && rightSideBar->isVisible()) ? rightSideBar->width()
251 rect.
setHeight(qMax(300, frame->minSize().height()));
252 rect.
setWidth(centralAreaGeo.
width() - margin * 2 - leftSideBarWidth - rightSideBarWidth);
253 rect.
moveLeft(margin + leftSideBarWidth);
257 rect.
moveTop(centralAreaGeo.
y() + sb->height() + centerWidgetMargins.
top());
265 const int topSideBarHeight = (topSideBar && topSideBar->isVisible()) ? topSideBar->height()
267 const int bottomSideBarHeight = (bottomSideBar && bottomSideBar->isVisible()) ? bottomSideBar->height()
269 rect.
setWidth(qMax(300, frame->minSize().width()));
270 rect.
setHeight(centralAreaGeo.
height() - topSideBarHeight - bottomSideBarHeight - centerWidgetMargins.
top() - centerWidgetMargins.
bottom());
271 rect.
moveTop(sb->mapTo(q,
QPoint(0, 0)).y() + topSideBarHeight - 1);
275 rect.
moveLeft(margin + centralAreaGeo.
x() + centerWidgetMargins.
left() + sb->width());
290 case Layouting::LayoutBorderLocation_North:
292 case Layouting::LayoutBorderLocation_East:
294 case Layouting::LayoutBorderLocation_West:
296 case Layouting::LayoutBorderLocation_South:
298 case Layouting::LayoutBorderLocation_All:
299 case Layouting::LayoutBorderLocation_Verticals:
300 case Layouting::LayoutBorderLocation_Horizontals:
301 case Layouting::LayoutBorderLocation_None:
305 qWarning() << Q_FUNC_INFO <<
"Unknown loc" << loc;
312 case Layouting::LayoutBorderLocation_North:
314 case Layouting::LayoutBorderLocation_East:
316 case Layouting::LayoutBorderLocation_West:
318 case Layouting::LayoutBorderLocation_South:
320 case Layouting::LayoutBorderLocation_All:
321 case Layouting::LayoutBorderLocation_Verticals:
322 case Layouting::LayoutBorderLocation_Horizontals:
323 case Layouting::LayoutBorderLocation_None:
334 Layouting::Item *item = q->layoutWidget()->itemForFrame(dw->d->frame());
336 qWarning() << Q_FUNC_INFO <<
"No item for dock widget";
340 const Layouting::LayoutBorderLocations borders = item->adjacentLayoutBorders();
341 const qreal aspectRatio = dw->width() / (dw->height() * 1.0);
344 if (borders == Layouting::LayoutBorderLocation_All) {
350 for (
auto borderLoc : { Layouting::LayoutBorderLocation_North, Layouting::LayoutBorderLocation_East,
351 Layouting::LayoutBorderLocation_West, Layouting::LayoutBorderLocation_South }) {
352 if (borders == (Layouting::LayoutBorderLocation_All & ~borderLoc))
357 if ((borders & Layouting::LayoutBorderLocation_Verticals) == Layouting::LayoutBorderLocation_Verticals) {
363 if ((borders & Layouting::LayoutBorderLocation_Horizontals) == Layouting::LayoutBorderLocation_Horizontals) {
369 if (borders == (Layouting::LayoutBorderLocation_West | Layouting::LayoutBorderLocation_South)) {
372 }
else if (borders == (Layouting::LayoutBorderLocation_East | Layouting::LayoutBorderLocation_South)) {
375 }
else if (borders == (Layouting::LayoutBorderLocation_West | Layouting::LayoutBorderLocation_North)) {
378 }
else if (borders == (Layouting::LayoutBorderLocation_East | Layouting::LayoutBorderLocation_North)) {
396 void MainWindowBase::Private::updateOverlayGeometry(
QSize suggestedSize)
398 if (!m_overlayedDockWidget)
401 SideBar *sb = q->sideBarForDockWidget(m_overlayedDockWidget);
403 qWarning() << Q_FUNC_INFO <<
"Expected a sidebar";
407 const QRect defaultGeometry = rectForOverlay(m_overlayedDockWidget->d->frame(), sb->location());
408 QRect newGeometry = defaultGeometry;
410 Frame *frame = m_overlayedDockWidget->d->frame();
414 switch (sb->location()) {
416 const int maxHeight = q->height() - frame->pos().y() - 10;
421 const int maxHeight = sb->pos().y() - m_layoutWidget->pos().y() - 10;
422 const int bottom = newGeometry.
bottom();
428 const int maxWidth = sb->pos().x() - m_layoutWidget->pos().x() - 10;
435 const int maxWidth = q->width() - frame->pos().x() - 10;
440 qWarning() << Q_FUNC_INFO <<
"Unexpected sidebar value";
445 m_overlayedDockWidget->d->frame()->QWidgetAdapter::setGeometry(newGeometry);
448 void MainWindowBase::Private::clearSideBars()
452 if (SideBar *sb = q->sideBar(loc))
464 if (SideBar *sb =
sideBar(location)) {
467 sb->addDockWidget(dw);
470 qWarning() << Q_FUNC_INFO <<
"Minimization supported, probably disabled in Config::self().flags()";
477 if (dw == d->m_overlayedDockWidget)
483 qWarning() << Q_FUNC_INFO <<
"Dock widget isn't in any sidebar";
487 sb->removeDockWidget(dw);
498 qWarning() << Q_FUNC_INFO <<
"You need to add the dock widget to the sidebar before you can overlay it";
502 if (d->m_overlayedDockWidget == dw) {
511 d->m_overlayedDockWidget = dw;
512 frame->addWidget(dw);
513 d->updateOverlayGeometry(dw->d->lastPositions().lastOverlayedGeometry(sb->location()).size());
515 frame->setAllowedResizeSides(d->allowedResizeSides(sb->location()));
516 frame->QWidgetAdapter::show();
523 const bool wasOverlayed = d->m_overlayedDockWidget == dw;
532 if (!d->m_overlayedDockWidget)
535 Frame *frame = d->m_overlayedDockWidget->d->frame();
537 d->m_overlayedDockWidget =
nullptr;
541 const SideBarLocation loc = d->m_overlayedDockWidget->sideBarLocation();
542 d->m_overlayedDockWidget->d->lastPositions().setLastOverlayedGeometry(
543 loc, frame->QWidgetAdapter::geometry());
548 d->m_overlayedDockWidget->setParent(
nullptr);
549 Q_EMIT d->m_overlayedDockWidget->isOverlayedChanged(
false);
550 d->m_overlayedDockWidget =
nullptr;
555 Q_EMIT d->m_overlayedDockWidget->isOverlayedChanged(
false);
556 d->m_overlayedDockWidget =
nullptr;
565 if (SideBar *sb =
sideBar(loc)) {
576 return d->m_overlayedDockWidget;
581 if (SideBar *sb =
sideBar(loc)) {
582 return !sb->isEmpty();
606 bool allClosed =
true;
608 const auto dockWidgets = d->m_layoutWidget->dockWidgets();
610 Frame *frame = dw->d->frame();
615 const bool closed = dw->close();
616 allClosed = allClosed && closed;
619 if (frame->beingDeletedLater()) {
639 if (d->name.isEmpty()) {
642 DockRegistry::self()->registerMainWindow(
this);
650 d->updateOverlayedDockWidgetGeometries();
653 bool MainWindowBase::deserialize(
const LayoutSaver::MainWindow &mw)
656 qWarning() << Q_FUNC_INFO <<
"Refusing to restore MainWindow with different options"
657 <<
"; expected=" << mw.options <<
"; has=" <<
options();
661 if (d->affinities != mw.affinities) {
662 qWarning() << Q_FUNC_INFO <<
"Affinty name changed from" << d->affinities
663 <<
"; to" << mw.affinities;
665 d->affinities = mw.affinities;
668 const bool success =
layoutWidget()->deserialize(mw.multiSplitterLayout);
682 qWarning() << Q_FUNC_INFO <<
"Could not find dock widget" <<
uniqueName
683 <<
". Won't restore it to sidebar";
687 sb->addDockWidget(dw);
698 LayoutSaver::MainWindow MainWindowBase::serialize()
const
700 LayoutSaver::MainWindow m;
706 m.screenIndex = screenNumberForWidget(
this);
707 m.screenSize = screenSizeForWidget(
this);
709 m.affinities = d->affinities;
714 if (SideBar *sb =
sideBar(loc)) {
717 m.dockWidgetsPerSideBar.
insert(loc, dockwidgets);