21 #include "DockRegistry_p.h"
22 #include "DockWidgetBase_p.h"
23 #include "FloatingWindow_p.h"
25 #include "LayoutSaver_p.h"
26 #include "LayoutWidget_p.h"
27 #include "Logging_p.h"
28 #include "Position_p.h"
29 #include "TabWidget_p.h"
30 #include "TitleBar_p.h"
32 #include "WidgetResizeHandler_p.h"
33 #include "MDILayoutWidget_p.h"
35 #include <QCloseEvent>
38 #define MARGIN_THRESHOLD 100
54 Frame::Frame(
QWidgetOrQuick *parent, FrameOptions options,
int userType)
57 , m_tabWidget(
Config::self().frameworkWidgetFactory()->createTabWidget(this))
58 , m_titleBar(
Config::self().frameworkWidgetFactory()->createTitleBar(this))
60 , m_userType(userType)
63 DockRegistry::self()->registerFrame(
this);
65 connect(
this, &Frame::currentDockWidgetChanged,
this, &Frame::updateTitleAndIcon);
67 connect(m_tabWidget->asWidget(), SIGNAL(currentTabChanged(
int)),
68 this, SLOT(onCurrentTabChanged(
int)));
70 setLayoutWidget(qobject_cast<LayoutWidget *>(QWidgetAdapter::parentWidget()));
79 m_layoutItem->unref();
81 delete m_resizeHandler;
82 m_resizeHandler =
nullptr;
84 DockRegistry::self()->unregisterFrame(
this);
87 setLayoutWidget(
nullptr);
90 void Frame::updateTitleAndIcon()
93 m_titleBar->setTitle(dw->title());
94 m_titleBar->setIcon(dw->icon());
96 if (
auto fw = floatingWindow()) {
97 if (fw->hasSingleFrame()) {
98 fw->updateTitleAndIcon();
102 setObjectName(dw->uniqueName());
104 }
else if (currentTabIndex() != -1) {
105 qWarning() << Q_FUNC_INFO <<
"Invalid dock widget for frame." << currentTabIndex();
109 void Frame::onDockWidgetTitleChanged()
111 updateTitleAndIcon();
114 if (
auto dw = qobject_cast<DockWidgetBase *>(sender())) {
115 int index = indexOfDockWidget(dw);
116 renameTab(index, dw->title());
117 changeTabIcon(index, dw->icon(DockWidgetBase::IconPlace::TabBar));
124 insertWidget(dockWidget, dockWidgetCount(), addingOption);
127 void Frame::addWidget(Frame *frame,
InitialOption addingOption)
129 if (frame->isEmpty()) {
130 qWarning() <<
"Frame::addWidget: frame is empty." << frame;
134 const auto &docks = frame->dockWidgets();
136 addWidget(dockWidget, addingOption);
139 void Frame::addWidget(FloatingWindow *floatingWindow,
InitialOption addingOption)
141 Q_ASSERT(floatingWindow);
142 for (Frame *f : floatingWindow->frames())
143 addWidget(f, addingOption);
148 Q_ASSERT(dockWidget);
149 if (containsDockWidget(dockWidget)) {
150 qWarning() <<
"Frame::addWidget dockWidget already exists. this=" <<
this <<
"; dockWidget=" << dockWidget;
154 dockWidget->d->addPlaceholderItem(m_layoutItem);
156 insertDockWidget(dockWidget, index);
161 if (hasSingleDockWidget()) {
162 Q_EMIT currentDockWidgetChanged(dockWidget);
169 resize(dockWidget->size());
174 connect(dockWidget, &DockWidgetBase::titleChanged,
this, &Frame::onDockWidgetTitleChanged);
175 connect(dockWidget, &DockWidgetBase::iconChanged,
this, &Frame::onDockWidgetTitleChanged);
180 disconnect(dw, &DockWidgetBase::titleChanged,
this, &Frame::onDockWidgetTitleChanged);
181 disconnect(dw, &DockWidgetBase::iconChanged,
this, &Frame::onDockWidgetTitleChanged);
182 removeWidget_impl(dw);
187 if (m_inCtor || m_inDtor)
190 dockWidget->d->saveTabIndex();
192 QRect r = dockWidget->geometry();
193 removeWidget(dockWidget);
195 auto newFrame = Config::self().frameworkWidgetFactory()->createFrame();
197 newFrame->addWidget(dockWidget);
201 auto floatingWindow = Config::self().frameworkWidgetFactory()->createFloatingWindow(newFrame);
204 floatingWindow->show();
206 return floatingWindow;
211 if (m_inCtor || m_inDtor)
214 return indexOfDockWidget_impl(dw);
217 int Frame::currentIndex()
const
219 if (m_inCtor || m_inDtor)
222 return currentIndex_impl();
225 void Frame::setCurrentTabIndex(
int index)
227 if (m_inCtor || m_inDtor)
230 setCurrentTabIndex_impl(index);
235 if (m_inCtor || m_inDtor)
238 setCurrentDockWidget_impl(dw);
243 if (m_inCtor || m_inDtor)
246 insertDockWidget_impl(dw, index);
251 if (m_inCtor || m_inDtor)
254 return dockWidgetAt_impl(index);
259 if (m_inCtor || m_inDtor)
262 return currentDockWidget_impl();
265 int Frame::dockWidgetCount()
const
267 if (m_inCtor || m_inDtor)
270 return m_tabWidget->numDockWidgets();
273 void Frame::onDockWidgetCountChanged()
275 qCDebug(docking) <<
"Frame::onDockWidgetCountChanged:" <<
this <<
"; widgetCount=" << dockWidgetCount();
276 if (isEmpty() && !isCentralFrame()) {
277 scheduleDeleteLater();
279 updateTitleBarVisibility();
283 Q_EMIT hasTabsVisibleChanged();
287 dock->d->updateFloatAction();
290 Q_EMIT numDockWidgetsChanged();
293 void Frame::onCurrentTabChanged(
int index)
296 if (
auto dock = dockWidgetAt(index)) {
297 Q_EMIT currentDockWidgetChanged(dock);
299 qWarning() <<
"dockWidgetAt" << index <<
"returned nullptr" <<
this;
304 void Frame::isFocusedChangedCallback()
306 Q_EMIT isFocusedChanged();
309 void Frame::focusedWidgetChangedCallback()
311 Q_EMIT focusedWidgetChanged();
314 void Frame::updateTitleBarVisibility()
316 if (m_updatingTitleBar || m_beingDeleted) {
323 bool visible =
false;
324 if (isCentralFrame()) {
326 }
else if ((Config::self().flags() & Config::Flag_HideTitleBarWhenTabsVisible) && hasTabsVisible()) {
328 }
else if (FloatingWindow *fw = floatingWindow()) {
330 visible = !fw->hasSingleFrame();
335 const bool wasVisible = m_titleBar->isVisible();
336 m_titleBar->setVisible(visible);
338 if (wasVisible != visible) {
339 Q_EMIT actualTitleBarChanged();
340 for (
auto dw : dockWidgets())
344 if (
auto fw = floatingWindow()) {
347 fw->updateTitleBarVisibility();
351 void Frame::updateFloatingActions()
355 dw->d->updateFloatAction();
358 bool Frame::containsMouse(
QPoint globalPos)
const
360 return QWidgetAdapter::rect().contains(KDDockWidgets::QWidgetAdapter::mapFromGlobal(globalPos));
363 TitleBar *Frame::titleBar()
const
368 TitleBar *Frame::actualTitleBar()
const
370 if (FloatingWindow *fw = floatingWindow()) {
372 if (fw->hasSingleFrame())
373 return fw->titleBar();
381 return m_titleBar->title();
384 QIcon Frame::icon()
const
386 return m_titleBar->icon();
391 if (m_inCtor || m_inDtor)
395 const int count = dockWidgetCount();
397 for (
int i = 0; i < count; ++i)
398 dockWidgets << dockWidgetAt(i);
405 const int count = dockWidgetCount();
406 for (
int i = 0, e = count; i != e; ++i) {
407 if (dockWidget == dockWidgetAt(i))
413 FloatingWindow *Frame::floatingWindow()
const
419 auto p = QWidgetAdapter::parentWidget();
421 if (qobject_cast<KDDockWidgets::MainWindowBase *>(p))
424 if (
auto fw = qobject_cast<FloatingWindow *>(p))
432 p = p->parentWidget();
438 void Frame::restoreToPreviousPosition()
440 if (hasSingleDockWidget()) {
441 qWarning() << Q_FUNC_INFO <<
"Invalid usage, there's no tabs";
446 qCDebug(placeholder) << Q_FUNC_INFO <<
"There's no previous position known";
450 if (!m_layoutItem->isPlaceholder()) {
452 qCDebug(placeholder) << Q_FUNC_INFO <<
"Previous position isn't a placeholder";
456 m_layoutItem->restore(
this);
459 int Frame::currentTabIndex()
const
461 return currentIndex();
466 qCDebug(closing) <<
"Frame::closeEvent";
470 qApp->sendEvent(dock, e);
476 bool Frame::anyNonClosable()
const
478 for (
auto dw : dockWidgets()) {
479 if ((dw->
options() & DockWidgetBase::Option_NotClosable) && !DockRegistry::self()->isProcessingAppQuitEvent())
486 bool Frame::anyNonDockable()
const
488 for (
auto dw : dockWidgets()) {
489 if (dw->
options() & DockWidgetBase::Option_NotDockable)
498 if (hasSingleDockWidget() && containsDockWidget(w)) {
499 if (!QWidgetAdapter::isVisible()) {
500 qCDebug(hiding) <<
"Widget" << w <<
" was shown, we're="
502 << QWidgetAdapter::isVisible();
503 QWidgetAdapter::setVisible(
true);
510 if (!isCentralFrame() && hasSingleDockWidget() && containsDockWidget(w)) {
511 if (QWidgetAdapter::isVisible()) {
512 qCDebug(hiding) <<
"Widget" << w <<
" was hidden, we're="
513 <<
"; visible=" << QWidgetAdapter::isVisible()
514 <<
"; dockWidgets=" << dockWidgets();
515 QWidgetAdapter::setVisible(
false);
520 void Frame::setLayoutItem(Layouting::Item *item)
522 if (item == m_layoutItem)
526 m_layoutItem->unref();
534 dw->d->addPlaceholderItem(item);
537 dw->d->lastPositions().removePlaceholders();
541 Layouting::Item *Frame::layoutItem()
const
546 int Frame::dbg_numFrames()
551 bool Frame::beingDeletedLater()
const
553 return m_beingDeleted;
556 bool Frame::hasTabsVisible()
const
561 return alwaysShowsTabs() || dockWidgetCount() > 1;
569 return dockWidgetAt(0)->affinities();
573 void Frame::setLayoutWidget(LayoutWidget *dt)
575 if (dt == m_layoutWidget)
578 const bool wasInMainWindow = dt && isInMainWindow();
579 const bool wasMDI = isMDI();
581 disconnect(m_visibleWidgetCountChangedConnection);
584 delete m_resizeHandler;
585 m_resizeHandler =
nullptr;
587 if (m_layoutWidget) {
589 m_resizeHandler =
new WidgetResizeHandler(
false,
this);
592 m_visibleWidgetCountChangedConnection =
593 connect(m_layoutWidget, &LayoutWidget::visibleWidgetCountChanged,
this,
594 &Frame::updateTitleBarVisibility);
595 updateTitleBarVisibility();
596 if (wasInMainWindow != isInMainWindow())
597 Q_EMIT isInMainWindowChanged();
600 if (wasMDI != isMDI())
601 Q_EMIT isMDIChanged();
604 bool Frame::isTheOnlyFrame()
const
606 return m_layoutWidget && m_layoutWidget->visibleCount() == 1;
609 bool Frame::isOverlayed()
const
614 void Frame::unoverlay()
619 bool Frame::isFloating()
const
621 if (isInMainWindow())
624 return isTheOnlyFrame();
627 bool Frame::isInFloatingWindow()
const
629 return floatingWindow() !=
nullptr;
632 bool Frame::isInMainWindow()
const
634 return mainWindow() !=
nullptr;
637 bool Frame::event(
QEvent *e)
640 if (
auto layoutWidget = qobject_cast<LayoutWidget *>(QWidgetAdapter::parentWidget())) {
641 setLayoutWidget(layoutWidget);
643 setLayoutWidget(
nullptr);
647 return QWidgetAdapter::event(e);
650 Frame *Frame::deserialize(
const LayoutSaver::Frame &f)
655 auto frame = Config::self().frameworkWidgetFactory()->createFrame(
nullptr, FrameOptions(f.options));
656 frame->setObjectName(f.objectName);
658 for (
const auto &savedDock : qAsConst(f.dockWidgets)) {
659 if (
DockWidgetBase *dw = DockWidgetBase::deserialize(savedDock)) {
660 frame->addWidget(dw);
664 frame->setCurrentTabIndex(f.currentTabIndex);
665 frame->QWidgetAdapter::setGeometry(f.geometry);
670 LayoutSaver::Frame Frame::serialize()
const
672 LayoutSaver::Frame frame;
673 frame.isNull =
false;
677 frame.objectName = objectName();
678 frame.geometry = QWidgetAdapter::geometry();
679 frame.options = options();
680 frame.currentTabIndex = currentTabIndex();
684 frame.dockWidgets.push_back(dock->d->serialize());
689 void Frame::scheduleDeleteLater()
691 qCDebug(creation) << Q_FUNC_INFO <<
this;
692 m_beingDeleted =
true;
699 QSize Frame::dockWidgetsMinSize()
const
701 QSize size = Layouting::Item::hardcodedMinimumSize;
708 QSize Frame::biggestDockWidgetMaxSize()
const
710 QSize size = Layouting::Item::hardcodedMaximumSize;
712 const QSize dwMax = widgetMaxSize(dw);
713 if (size == Layouting::Item::hardcodedMaximumSize) {
718 const bool hasMaxSize = dwMax != Layouting::Item::hardcodedMaximumSize;
720 size = dw->maximumSize().expandedTo(size);
724 if (size.
width() == 0)
725 size.
setWidth(Layouting::Item::hardcodedMaximumSize.width());
727 size.
setHeight(Layouting::Item::hardcodedMaximumSize.height());
732 QRect Frame::dragRect()
const
735 if (m_titleBar->isVisible()) {
736 rect = m_titleBar->rect();
745 return m_layoutWidget ? m_layoutWidget->mainWindow() :
nullptr;
748 TabWidget *Frame::tabWidget()
const
758 return dw->options() & option;
767 return dw->options() & option;
775 return dw->layoutSaverOptions() & option;
783 return dw->layoutSaverOptions() & option;
787 void Frame::setAllowedResizeSides(CursorPositions sides)
790 delete m_resizeHandler;
791 m_resizeHandler =
new WidgetResizeHandler(
false,
this);
792 m_resizeHandler->setAllowedResizeSides(sides);
794 delete m_resizeHandler;
795 m_resizeHandler =
nullptr;
799 bool Frame::isMDI()
const
801 return mdiLayoutWidget() !=
nullptr;
804 MDILayoutWidget *Frame::mdiLayoutWidget()
const
806 return qobject_cast<MDILayoutWidget *>(m_layoutWidget);
809 int Frame::userType()
const
814 WidgetResizeHandler *Frame::resizeHandler()
const
816 return m_resizeHandler;