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"
33#include "private/multisplitter/Item_p.h"
36#ifdef KDDOCKWIDGETS_QTQUICK
49 return new MDILayoutWidget(mainWindow);
51 return new DropAreaWithCentralFrame(mainWindow, options);
54class MainWindowBase::Private
61 , m_persistentCentralDockWidget(createPersistentCentralDockWidget(
uniqueName))
65 bool supportsCentralFrame()
const
70 bool supportsPersistentCentralWidget()
const
82 if (!supportsPersistentCentralWidget())
86 dw->dptr()->m_isPersistentCentralDockWidget =
true;
87 Frame *frame = dropArea()->m_centralFrame;
107 void clearSideBars();
114 LayoutWidget *
const m_layoutWidget;
116 int m_overlayMargin = 1;
122 , d(new Private(this, uniqueName, options))
126 connect(d->m_layoutWidget, &LayoutWidget::visibleWidgetCountChanged,
this,
132 DockRegistry::self()->unregisterMainWindow(
this);
157 if (d->supportsPersistentCentralWidget()) {
159 <<
"MainWindowOption_HasCentralWidget can only have 1 widget in the center."
160 <<
"Use MainWindowOption_HasCentralFrame instead, which is similar but supports tabbing";
161 }
else if (d->supportsCentralFrame()) {
162 dropArea()->m_centralFrame->addWidget(widget);
207 return d->m_layoutWidget;
223 if (!d->affinities.isEmpty()) {
225 <<
"Affinity is already set, refusing to change."
226 <<
"Submit a feature request with a good justification.";
235 return d->affinities;
248CursorPositions MainWindowBase::Private::allowedResizeSides(
SideBarLocation loc)
const
271 SideBar *sb = q->sideBar(location);
275 const QRect centralAreaGeo = q->centralAreaGeometry();
276 const QMargins centerWidgetMargins = q->centerWidgetMargins();
279 const int margin = m_overlayMargin;
286 const int leftSideBarWidth = (leftSideBar && leftSideBar->isVisible()) ? leftSideBar->
width()
288 const int rightSideBarWidth = (rightSideBar && rightSideBar->isVisible()) ? rightSideBar->width()
290 rect.
setHeight(qMax(300, frame->minSize().height()));
291 rect.
setWidth(centralAreaGeo.
width() - margin * 2 - leftSideBarWidth - rightSideBarWidth);
292 rect.
moveLeft(margin + leftSideBarWidth);
296 rect.
moveTop(centralAreaGeo.
y() + sb->height() + centerWidgetMargins.
top());
304 const int topSideBarHeight = (topSideBar && topSideBar->isVisible()) ? topSideBar->height()
306 const int bottomSideBarHeight = (bottomSideBar && bottomSideBar->isVisible()) ? bottomSideBar->height()
308 rect.
setWidth(qMax(300, frame->minSize().width()));
309 rect.
setHeight(centralAreaGeo.
height() - topSideBarHeight - bottomSideBarHeight - centerWidgetMargins.
top() - centerWidgetMargins.
bottom());
310 rect.
moveTop(sb->mapTo(q,
QPoint(0, 0)).y() + topSideBarHeight - 1);
312 rect.
moveLeft(centralAreaGeo.
x() + centralAreaGeo.
width() - rect.
width() - sb->width() - centerWidgetMargins.
right() - margin);
314 rect.
moveLeft(margin + centralAreaGeo.
x() + centerWidgetMargins.
left() + sb->width());
329 case Layouting::LayoutBorderLocation_North:
331 case Layouting::LayoutBorderLocation_East:
333 case Layouting::LayoutBorderLocation_West:
335 case Layouting::LayoutBorderLocation_South:
337 case Layouting::LayoutBorderLocation_All:
338 case Layouting::LayoutBorderLocation_Verticals:
339 case Layouting::LayoutBorderLocation_Horizontals:
340 case Layouting::LayoutBorderLocation_None:
344 qWarning() << Q_FUNC_INFO <<
"Unknown loc" << loc;
351 case Layouting::LayoutBorderLocation_North:
353 case Layouting::LayoutBorderLocation_East:
355 case Layouting::LayoutBorderLocation_West:
357 case Layouting::LayoutBorderLocation_South:
359 case Layouting::LayoutBorderLocation_All:
360 case Layouting::LayoutBorderLocation_Verticals:
361 case Layouting::LayoutBorderLocation_Horizontals:
362 case Layouting::LayoutBorderLocation_None:
373 Layouting::Item *item = q->layoutWidget()->itemForFrame(dw->d->frame());
375 qWarning() << Q_FUNC_INFO <<
"No item for dock widget";
379 const Layouting::LayoutBorderLocations borders = item->adjacentLayoutBorders();
380 const qreal aspectRatio = dw->width() / (std::max(1, dw->height()) * 1.0);
383 if (borders == Layouting::LayoutBorderLocation_All) {
389 for (
auto borderLoc : { Layouting::LayoutBorderLocation_North, Layouting::LayoutBorderLocation_East,
390 Layouting::LayoutBorderLocation_West, Layouting::LayoutBorderLocation_South }) {
391 if (borders == (Layouting::LayoutBorderLocation_All & ~borderLoc))
396 if ((borders & Layouting::LayoutBorderLocation_Verticals) == Layouting::LayoutBorderLocation_Verticals) {
402 if ((borders & Layouting::LayoutBorderLocation_Horizontals) == Layouting::LayoutBorderLocation_Horizontals) {
408 if (borders == (Layouting::LayoutBorderLocation_West | Layouting::LayoutBorderLocation_South)) {
411 }
else if (borders == (Layouting::LayoutBorderLocation_East | Layouting::LayoutBorderLocation_South)) {
414 }
else if (borders == (Layouting::LayoutBorderLocation_West | Layouting::LayoutBorderLocation_North)) {
417 }
else if (borders == (Layouting::LayoutBorderLocation_East | Layouting::LayoutBorderLocation_North)) {
435void MainWindowBase::Private::updateOverlayGeometry(
QSize suggestedSize)
437 if (!m_overlayedDockWidget)
440 SideBar *sb = q->sideBarForDockWidget(m_overlayedDockWidget);
442 qWarning() << Q_FUNC_INFO <<
"Expected a sidebar";
446 const QRect defaultGeometry = rectForOverlay(m_overlayedDockWidget->d->frame(), sb->location());
447 QRect newGeometry = defaultGeometry;
449 Frame *frame = m_overlayedDockWidget->d->frame();
453 switch (sb->location()) {
455 const int maxHeight = q->
height() - frame->pos().y() - 10;
460 const int maxHeight = sb->pos().y() - m_layoutWidget->pos().y() - 10;
461 const int bottom = newGeometry.
bottom();
467 const int maxWidth = sb->pos().x() - m_layoutWidget->pos().x() - 10;
474 const int maxWidth = q->width() - frame->pos().x() - 10;
479 qWarning() << Q_FUNC_INFO <<
"Unexpected sidebar value";
484 m_overlayedDockWidget->d->frame()->QWidgetAdapter::setGeometry(newGeometry);
487void MainWindowBase::Private::clearSideBars()
491 if (SideBar *sb = q->sideBar(loc))
503 if (
dw->isPersistentCentralDockWidget())
509 sb->addDockWidget(
dw);
512 qWarning() <<
Q_FUNC_INFO <<
"Minimization supported, probably disabled in Config::self().flags()";
519 if (
dw == d->m_overlayedDockWidget)
529 sb->removeDockWidget(
dw);
530 dw->setFloating(
false);
535 if (!
dw ||
dw->isPersistentCentralDockWidget())
540 qWarning() <<
Q_FUNC_INFO <<
"You need to add the dock widget to the sidebar before you can overlay it";
544 if (d->m_overlayedDockWidget ==
dw) {
553 d->m_overlayedDockWidget =
dw;
554 frame->addWidget(
dw);
555 d->updateOverlayGeometry(
dw->d->lastPosition()->lastOverlayedGeometry(
sb->location()).size());
556 connect(frame, &QWidgetAdapter::widgetGeometryChanged,
this, [
dw,
sb, frame] {
560 frame->setAllowedResizeSides(d->allowedResizeSides(
sb->location()));
561 frame->QWidgetAdapter::show();
563 Q_EMIT dw->isOverlayedChanged(
true);
577 if (!d->m_overlayedDockWidget)
580 Frame *frame = d->m_overlayedDockWidget->d->frame();
582 d->m_overlayedDockWidget =
nullptr;
586 frame->disconnect(
this);
590 d->m_overlayedDockWidget->setParent(
nullptr);
591 Q_EMIT d->m_overlayedDockWidget->isOverlayedChanged(
false);
592 d->m_overlayedDockWidget =
nullptr;
597 Q_EMIT d->m_overlayedDockWidget->isOverlayedChanged(
false);
598 d->m_overlayedDockWidget =
nullptr;
618 return d->m_overlayedDockWidget;
624 return !
sb->isEmpty();
650 const auto dockWidgets = d->m_layoutWidget->dockWidgets();
652 Frame *frame =
dw->d->frame();
661 if (frame->beingDeletedLater()) {
681 if (d->name.isEmpty()) {
684 DockRegistry::self()->registerMainWindow(
this);
692 if (d->m_overlayedDockWidget)
693 d->updateOverlayGeometry(d->m_overlayedDockWidget->d->frame()->QWidgetAdapter::size());
696bool MainWindowBase::deserialize(
const LayoutSaver::MainWindow &mw)
700 <<
"; expected=" <<
mw.options <<
"; has=" <<
options();
704 if (d->affinities !=
mw.affinities) {
706 <<
"; to" <<
mw.affinities;
708 d->affinities =
mw.affinities;
726 <<
". Won't restore it to sidebar";
730 sb->addDockWidget(
dw);
741LayoutSaver::MainWindow MainWindowBase::serialize()
const
743 LayoutSaver::MainWindow
m;
753 m.affinities = d->affinities;
778 return d->m_overlayMargin;
783 if (margin == d->m_overlayMargin) {
787 d->m_overlayMargin = margin;
793 if (!d->supportsPersistentCentralWidget()) {
794 qWarning() <<
"MainWindow::setPersistentCentralWidget() requires MainWindowOption_HasCentralWidget";
798 auto dw = d->m_persistentCentralDockWidget;
800 dw->setWidget(widget);
808 if (
auto dw = d->m_persistentCentralDockWidget)
816 d->m_layoutWidget->onCloseEvent(
e);
static LayoutWidget * createLayoutWidget(MainWindowBase *mainWindow, MainWindowOptions options)
static SideBarLocation sideBarLocationForBorder(Layouting::LayoutBorderLocations loc)
static SideBarLocation opposedSideBarLocationForBorder(Layouting::LayoutBorderLocation loc)
The MainWindow base-class that's shared between QtWidgets and QtQuick stack.
The MainWindow base-class. MainWindow and MainWindowBase are only split in two so we can share some c...
Q_INVOKABLE void toggleOverlayOnSideBar(KDDockWidgets::DockWidgetBase *)
Shows or hides an overlay. It's assumed the dock widget is already in a side-bar.
Q_INVOKABLE void moveToSideBar(KDDockWidgets::DockWidgetBase *)
Moves the dock widget into one of the MainWindow's sidebar. Means the dock widget is removed from the...
MainWindowBase(const QString &uniqueName, MainWindowOptions options=MainWindowOption_HasCentralFrame, WidgetType *parent=nullptr, Qt::WindowFlags flags=Qt::WindowFlags())
virtual SideBar * sideBar(SideBarLocation) const =0
void overlayMarginChanged(int)
Q_INVOKABLE void overlayOnSideBar(KDDockWidgets::DockWidgetBase *)
Shows the dock widget overlayed on top of the main window, placed next to the sidebar.
DockWidgetBase * overlayedDockWidget() const
returns the dock widget which is currently overlayed. nullptr if none. This is only relevant when usi...
void onResized(QResizeEvent *)
MDILayoutWidget * mdiLayoutWidget() const
Q_INVOKABLE void setPersistentCentralWidget(KDDockWidgets::QWidgetOrQuick *widget)
Sets a persistent central widget. It can't be detached.
Q_INVOKABLE void restoreFromSideBar(KDDockWidgets::DockWidgetBase *)
Removes the dock widget from the sidebar and docks it into the main window again.
void setAffinities(const QStringList &names)
Sets the affinities names. Dock widgets can only dock into main windows of the same affinity.
QRect windowGeometry() const
Returns the window geometry This is usually the same as MainWindowBase::geometry() But fixes the foll...
void setUniqueName(const QString &uniqueName)
Q_INVOKABLE void layoutParentContainerEqually(KDDockWidgets::DockWidgetBase *dockWidget)
like layoutEqually() but starts with the container that has dockWidget. While layoutEqually() starts ...
LayoutWidget * layoutWidget() const
Q_INVOKABLE KDDockWidgets::SideBar * sideBarForDockWidget(const KDDockWidgets::DockWidgetBase *) const
Returns the sidebar this dockwidget is in. nullptr if not in any.
DropAreaWithCentralFrame * dropArea() const
Q_INVOKABLE void clearSideBarOverlay(bool deleteFrame=true)
closes any overlayed dock widget. The sidebar still displays them as button.
void frameCountChanged(int)
emitted when the number of docked frames changes Note that we're using the "Frame" nomenculature inst...
~MainWindowBase() override
void setOverlayMargin(int margin)
Sets the margin used by overlay docks. Does not modify currently overlayed docks.
Q_INVOKABLE bool sideBarIsVisible(KDDockWidgets::SideBarLocation) const
Returns whether the specified sidebar is visible.
Q_INVOKABLE void addDockWidgetAsTab(KDDockWidgets::DockWidgetBase *dockwidget)
Docks a DockWidget into the central frame, tabbed.
Q_INVOKABLE void layoutEqually()
layouts all the widgets so they have an equal size within their parent container
Q_INVOKABLE void addDockWidget(KDDockWidgets::DockWidgetBase *dockWidget, KDDockWidgets::Location location, KDDockWidgets::DockWidgetBase *relativeTo=nullptr, KDDockWidgets::InitialOption initialOption={})
Docks a DockWidget into this main window.
bool anySideBarIsVisible() const
Returns whether any side bar is visible.
QWidgetOrQuick * persistentCentralWidget() const
KDDockWidgets::MainWindowOptions options
void onCloseEvent(QCloseEvent *)
Q_INVOKABLE bool closeDockWidgets(bool force=false)
Closes all dock widgets which are docked into this main window This is convenience to calling DockWid...
MultiSplitter * multiSplitter() const
void insert(int i, const T &value)
int removeAll(const T &value)
T value(int i) const const
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
T qobject_cast(QObject *object)
void setHeight(int height)
bool isEmpty() const const
bool isValid() const const
bool isEmpty() const const
QTextStream & right(QTextStream &stream)
Qt::WindowState windowState() const const