15#include "kddockwidgets/Config.h"
21#include "FloatingWindow_p.h"
22#include "ScopedValueRollback_p.h"
33#include "core/TabBar_p.h"
36#include "DockWidget_p.h"
37#include "ObjectGuard_p.h"
39#include "core/Logging_p.h"
40#include "core/Utils_p.h"
41#include "core/View_p.h"
42#include "core/LayoutSaver_p.h"
43#include "core/Position_p.h"
44#include "core/WidgetResizeHandler_p.h"
45#include "core/DelayedCall_p.h"
46#include "core/layouting/Item_p.h"
52#define MARGIN_THRESHOLD 100
87 , m_tabBar(m_stack->tabBar())
88 , m_titleBar(new Core::
TitleBar(this))
93 m_tabBar->
dptr()->currentDockWidgetChanged.connect([
this] {
100 view()->
d->closeRequested.connect([
this](CloseEvent *ev) { onCloseEvent(ev); });
111 d->m_layoutItem->unref();
113 delete m_resizeHandler;
114 m_resizeHandler =
nullptr;
125void Group::onCloseEvent(CloseEvent *e)
130 dock->view()->d->requestClose(e);
131 if (!e->isAccepted())
144 delete m_resizeHandler;
145 m_resizeHandler =
nullptr;
149 m_resizeHandler =
new WidgetResizeHandler(WidgetResizeHandler::EventFilterMode::Global,
150 WidgetResizeHandler::WindowMode::MDI,
view());
153 d->m_visibleWidgetCountChangedConnection =
157 d->isInMainWindowChanged.emit();
160 d->isMDIChanged.emit();
195 if (fw->hasSingleFrame()) {
196 fw->updateTitleAndIcon();
200 setObjectName(dw->uniqueName());
203 KDDW_ERROR(
"Invalid dock widget for group. index={}",
currentTabIndex());
226 KDDW_ERROR(
"Group::addTab: group is empty. group={}", (
void * )group);
232 addTab(dockWidget, addingOption);
239 for (
Group *f : groups)
248 KDDW_ERROR(
"Group::addTab dockWidget already exists. this={} ; dockWidget={}", (
void * )
this, (
void * )dockWidget);
252 dockWidget->
d->addPlaceholderItem(d->m_layoutItem);
263 if (!d->m_layoutItem) {
273 dockWidget->
d->setIsOpen(
true);
282 d->titleChangedConnections[dockWidget] = std::move(titleChangedConnection);
283 d->iconChangedConnections[dockWidget] = std::move(iconChangedConnection);
288 auto it = d->titleChangedConnections.find(dw);
289 if (it != d->titleChangedConnections.end())
290 d->titleChangedConnections.erase(it);
292 it = d->iconChangedConnections.find(dw);
293 if (it != d->iconChangedConnections.end())
294 d->iconChangedConnections.erase(it);
297 gvi->removeDockWidget(dw);
305 dockWidget->
d->saveTabIndex();
310 auto newGroup =
new Group();
311 const Point globalPoint =
mapToGlobal(Point(0, 0));
312 newGroup->addTab(dockWidget);
318 r.moveTopLeft(globalPoint);
363 dw->
d->onParentChanged();
393 scheduleDeleteLater();
400 d->hasTabsVisibleChanged.emit();
405 dock->d->updateFloatAction();
409 fw->dptr()->numDockWidgetsChanged.emit();
413 d->numDockWidgetsChanged.emit();
418 d->isFocusedChanged.emit();
423 d->focusedWidgetChanged.emit();
428 if (m_updatingTitleBar || m_beingDeleted) {
433 ScopedValueRollback guard(m_updatingTitleBar,
true);
435 bool visible =
false;
443 visible = !fw->hasSingleFrame();
446 visible = !dropArea->hasSingleFrame();
454 if (wasVisible != visible) {
455 d->actualTitleBarChanged.emit();
457 for (
auto dw : docks)
458 dw->d->actualTitleBarChanged.emit();
465 fw->updateTitleBarVisibility();
473 dw->d->updateFloatAction();
478 return rect().contains(
view()->mapFromGlobal(globalPos));
490 if (fw->hasSingleFrame())
491 return fw->titleBar();
493 if (mdiDropArea->hasSingleFrame()) {
519 for (
int i = 0; i < count; ++i)
528 for (
int i = 0, e = count; i != e; ++i) {
546 if (
auto fw = p->asFloatingWindowController())
549 if (p->equals(
view()->rootView())) {
563 KDDW_ERROR(
"Invalid usage, there's no tabs");
567 if (!d->m_layoutItem) {
568 KDDW_DEBUG(
"Group::restoreToPreviousPosition: There's no previous position known");
572 if (!d->m_layoutItem->isPlaceholder()) {
575 KDDW_DEBUG(
"Group::restoreToPreviousPosition: Previous position isn't a placeholder");
579 d->m_layoutItem->restore(d);
590 for (
auto dw : docks) {
602 for (
auto dw : docks) {
610void Group::Private::setLayoutItem_impl(Item *item)
614 const auto docks = q->dockWidgets();
617 dw->d->addPlaceholderItem(item);
620 dw->d->lastPosition()->removePlaceholders();
624LayoutingHost *Group::Private::host()
const
626 return q->m_layout ? q->m_layout->asLayoutingHost() :
nullptr;
629void Group::Private::setHost(LayoutingHost *host)
633 parent = layout->view();
636 q->setParentView(parent);
641 return d->m_layoutItem;
651 return m_beingDeleted;
666 return m->affinities();
675 d->setLayoutItem(item);
690 d->m_options &= ~FrameOption_IsOverlayed;
716 const FrameOptions
options = FrameOptions(f.options);
717 Group *group =
nullptr;
720 if (isPersistentCentralFrame) {
724 if (f.mainWindowUniqueName.isEmpty()) {
726 KDDW_ERROR(
"Group is the persistent central group but doesn't have"
727 "an associated window name");
730 group = mw->dropArea()->centralGroup();
733 KDDW_ERROR(
"Main window {} doesn't have central group", f.mainWindowUniqueName);
737 KDDW_ERROR(
"Couldn't find main window {}", f.mainWindowUniqueName);
745 group->setObjectName(f.objectName);
747 for (
const auto &savedDock : std::as_const(f.dockWidgets)) {
761 LayoutSaver::Group group;
762 group.isNull =
false;
766 group.objectName = objectName();
770 group.id =
view()->
d->id();
773 group.mainWindowUniqueName = mw->uniqueName();
777 group.dockWidgets.push_back(dock->d->serialize());
779 if (group.currentTabIndex == -1 && !docks.
isEmpty()) {
780 KDDW_ERROR(
"Group::serialize: Current index shouldn't be -1. Setting to 0 instead.");
781 group.currentTabIndex = 0;
787void Group::scheduleDeleteLater()
789 KDDW_TRACE(
"Group::scheduleDeleteLater: {}", (
void * )
this);
790 m_beingDeleted =
true;
799 Size
size = Item::hardcodedMinimumSize;
803 size =
size.expandedTo(dw->view()->minSize());
812 Size
size = Item::hardcodedMaximumSize;
817 const Size dwMax = dw->view()->maxSizeHint();
818 if (
size == Item::hardcodedMaximumSize) {
823 const bool hasMaxSize = dwMax != Item::hardcodedMaximumSize;
829 if (
size.width() == 0)
830 size.setWidth(Item::hardcodedMaximumSize.width());
831 if (
size.height() == 0)
832 size.setHeight(Item::hardcodedMaximumSize.height());
849 return gvi->dragRect();
856 return m_layout ? m_layout->
mainWindow() :
nullptr;
863 return std::all_of(docks.cbegin(), docks.cend(),
864 [option](
DockWidget *dw) { return dw->options() & option; });
871 return std::any_of(docks.cbegin(), docks.cend(),
872 [option](
DockWidget *dw) { return dw->options() & option; });
878 return std::all_of(docks.cbegin(), docks.cend(),
879 [option](
DockWidget *dw) { return dw->layoutSaverOptions() & option; });
885 return std::any_of(docks.cbegin(), docks.cend(),
886 [option](
DockWidget *dw) { return dw->layoutSaverOptions() & option; });
892 delete m_resizeHandler;
893 m_resizeHandler =
new WidgetResizeHandler(WidgetResizeHandler::EventFilterMode::Global,
894 WidgetResizeHandler::WindowMode::MDI,
view());
895 m_resizeHandler->setAllowedResizeSides(sides);
897 delete m_resizeHandler;
898 m_resizeHandler =
nullptr;
915 return dwWrapper->d->group();
932 auto dropArea = p ? p->asDropAreaController() :
nullptr;
933 if (dropArea && dropArea->isMDIWrapper())
940 return m_layout ? m_layout->
asMDILayout() :
nullptr;
949 KDDW_ERROR(
"Expected a single dock widget wrapper as group child");
958 return d->m_userType;
963 return m_resizeHandler;
975 if (!dockwidgets.isEmpty())
976 return dockwidgets.first()->floatingWindowFlags();
1008Group::Private::Private(
Group *qq,
int userType, FrameOptions options)
1010 , m_userType(userType)
1011 , m_options(options)
1013 m_parentViewChangedConnection = q->Controller::dptr()->parentViewChanged.connect([
this] {
1014 hostChanged.emit(host());
1017 q->view()->d->layoutInvalidated.connect([
this] { layoutInvalidated.emit(); });
1020Group::Private::~Private()
1022 m_visibleWidgetCountChangedConnection->disconnect();
1024 beingDestroyed.emit();
1032 if (
auto guest = item->guest()) {
1033 if (
auto group =
dynamic_cast<Core::Group::Private *
>(guest))
A widget that supports an arbitrary number of splitters (called Separators) in any combination of ver...
A ScopedConnection is a RAII-style way to make sure a Connection is disconnected.
The MainWindow base-class. MainWindow and MainWindowBase are only split in two so we can share some c...
A MultiSplitter with support for drop indicators when hovering over.
static int s_dbg_numFrames
The MainWindow base-class that's shared between QtWidgets and QtQuick stack.