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"
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"
34#include "DropAreaWithCentralFrame_p.h"
35#include "multisplitter/Item_p.h"
40#define MARGIN_THRESHOLD 100
66Frame::Frame(
QWidgetOrQuick *parent, FrameOptions options,
int userType)
70 , m_titleBar(
Config::self().frameworkWidgetFactory()->createTitleBar(this))
72 , m_userType(userType)
75 DockRegistry::self()->registerFrame(
this);
77 connect(
this, &Frame::currentDockWidgetChanged,
this, &Frame::updateTitleAndIcon);
79 connect(m_tabWidget->asWidget(), SIGNAL(currentTabChanged(
int)),
80 this, SLOT(onCurrentTabChanged(
int)));
82 setLayoutWidget(qobject_cast<LayoutWidget *>(QWidgetAdapter::parentWidget()));
91 m_layoutItem->unref();
93 delete m_resizeHandler;
94 m_resizeHandler =
nullptr;
96 DockRegistry::self()->unregisterFrame(
this);
99 setLayoutWidget(
nullptr);
102void Frame::updateTitleAndIcon()
105 m_titleBar->setTitle(dw->title());
106 m_titleBar->setIcon(dw->icon());
108 if (
auto fw = floatingWindow()) {
109 if (fw->hasSingleFrame()) {
110 fw->updateTitleAndIcon();
114 setObjectName(dw->uniqueName());
116 }
else if (currentTabIndex() != -1) {
117 qWarning() << Q_FUNC_INFO <<
"Invalid dock widget for frame." << currentTabIndex();
121void Frame::onDockWidgetTitleChanged()
123 updateTitleAndIcon();
126 if (
auto dw = qobject_cast<DockWidgetBase *>(sender())) {
127 int index = indexOfDockWidget(dw);
128 renameTab(index, dw->title());
129 changeTabIcon(index, dw->icon(DockWidgetBase::IconPlace::TabBar));
136 insertWidget(dockWidget, dockWidgetCount(), addingOption);
139void Frame::addWidget(Frame *frame,
InitialOption addingOption)
141 if (frame->isEmpty()) {
142 qWarning() <<
"Frame::addWidget: frame is empty." << frame;
146 const auto &docks = frame->dockWidgets();
148 addWidget(dockWidget, addingOption);
151void Frame::addWidget(FloatingWindow *floatingWindow,
InitialOption addingOption)
153 Q_ASSERT(floatingWindow);
154 for (Frame *f : floatingWindow->frames())
155 addWidget(f, addingOption);
160 Q_ASSERT(dockWidget);
161 if (containsDockWidget(dockWidget)) {
163 qWarning() <<
"Frame::addWidget dockWidget already exists. this=" <<
this <<
"; dockWidget=" << dockWidget;
167 dockWidget->d->addPlaceholderItem(m_layoutItem);
169 const int originalCurrentIndex = currentIndex();
171 insertDockWidget(dockWidget, index);
176 if (hasSingleDockWidget()) {
177 Q_EMIT currentDockWidgetChanged(dockWidget);
184 resize(dockWidget->size());
187 setCurrentTabIndex(originalCurrentIndex);
199 removeWidget_impl(dw);
204 if (m_inCtor || m_inDtor)
207 dockWidget->d->saveTabIndex();
209 QRect r = dockWidget->geometry();
210 removeWidget(dockWidget);
214 newFrame->addWidget(dockWidget);
221 floatingWindow->show();
223 return floatingWindow;
228 if (m_inCtor || m_inDtor)
231 return indexOfDockWidget_impl(dw);
234int Frame::currentIndex()
const
236 if (m_inCtor || m_inDtor)
239 return currentIndex_impl();
242void Frame::setCurrentTabIndex(
int index)
244 if (m_inCtor || m_inDtor)
247 setCurrentTabIndex_impl(index);
252 if (m_inCtor || m_inDtor)
255 setCurrentDockWidget_impl(dw);
260 if (m_inCtor || m_inDtor)
263 insertDockWidget_impl(dw, index);
268 if (m_inCtor || m_inDtor)
271 return dockWidgetAt_impl(index);
276 if (m_inCtor || m_inDtor)
279 return currentDockWidget_impl();
282int Frame::dockWidgetCount()
const
284 if (m_inCtor || m_inDtor)
287 return m_tabWidget->numDockWidgets();
290void Frame::onDockWidgetCountChanged()
292 qCDebug(docking) <<
"Frame::onDockWidgetCountChanged:" <<
this <<
"; widgetCount=" << dockWidgetCount();
293 if (isEmpty() && !isCentralFrame()) {
294 scheduleDeleteLater();
296 updateTitleBarVisibility();
300 Q_EMIT hasTabsVisibleChanged();
304 dock->d->updateFloatAction();
307 Q_EMIT numDockWidgetsChanged();
310void Frame::onCurrentTabChanged(
int index)
313 if (
auto dock = dockWidgetAt(index)) {
314 Q_EMIT currentDockWidgetChanged(dock);
316 qWarning() <<
"dockWidgetAt" << index <<
"returned nullptr" <<
this;
321void Frame::isFocusedChangedCallback()
323 Q_EMIT isFocusedChanged();
326void Frame::focusedWidgetChangedCallback()
328 Q_EMIT focusedWidgetChanged();
331void Frame::updateTitleBarVisibility()
333 if (m_updatingTitleBar || m_beingDeleted) {
340 bool visible =
false;
341 if (isCentralFrame()) {
345 }
else if (FloatingWindow *fw = floatingWindow()) {
347 visible = !fw->hasSingleFrame();
348 }
else if (isMDIWrapper()) {
349 auto dropArea = this->mdiDropAreaWrapper();
350 visible = !dropArea->hasSingleFrame();
355 const bool wasVisible = m_titleBar->isVisible();
356 m_titleBar->setVisible(visible);
358 if (wasVisible != visible) {
359 Q_EMIT actualTitleBarChanged();
360 for (
auto dw : dockWidgets())
361 Q_EMIT dw->actualTitleBarChanged();
364 if (
auto fw = floatingWindow()) {
367 fw->updateTitleBarVisibility();
371void Frame::updateFloatingActions()
375 dw->d->updateFloatAction();
378bool Frame::containsMouse(
QPoint globalPos)
const
380 return QWidgetAdapter::rect().contains(KDDockWidgets::QWidgetAdapter::mapFromGlobal(globalPos));
383TitleBar *Frame::titleBar()
const
388TitleBar *Frame::actualTitleBar()
const
390 if (FloatingWindow *fw = floatingWindow()) {
392 if (fw->hasSingleFrame())
394 }
else if (
auto mdiDropArea = mdiDropAreaWrapper()) {
395 if (mdiDropArea->hasSingleFrame()) {
396 return mdiFrame()->titleBar();
405 return m_titleBar->title();
408QIcon Frame::icon()
const
410 return m_titleBar->icon();
415 if (m_inCtor || m_inDtor)
419 const int count = dockWidgetCount();
421 for (
int i = 0; i < count; ++i)
422 dockWidgets << dockWidgetAt(i);
429 const int count = dockWidgetCount();
430 for (
int i = 0, e = count; i != e; ++i) {
431 if (dockWidget == dockWidgetAt(i))
437FloatingWindow *Frame::floatingWindow()
const
443 auto p = QWidgetAdapter::parentWidget();
445 if (qobject_cast<KDDockWidgets::MainWindowBase *>(p))
448 if (
auto fw = qobject_cast<FloatingWindow *>(p))
456 p = p->parentWidget();
462void Frame::restoreToPreviousPosition()
464 if (hasSingleDockWidget()) {
465 qWarning() << Q_FUNC_INFO <<
"Invalid usage, there's no tabs";
470 qCDebug(placeholder) << Q_FUNC_INFO <<
"There's no previous position known";
474 if (!m_layoutItem->isPlaceholder()) {
476 qCDebug(placeholder) << Q_FUNC_INFO <<
"Previous position isn't a placeholder";
480 m_layoutItem->restore(
this);
483int Frame::currentTabIndex()
const
485 return currentIndex();
490 qCDebug(closing) <<
"Frame::closeEvent";
494 qApp->sendEvent(dock, e);
500bool Frame::anyNonClosable()
const
502 for (
auto dw : dockWidgets()) {
510bool Frame::anyNonDockable()
const
512 for (
auto dw : dockWidgets()) {
522 if (hasSingleDockWidget() && containsDockWidget(w)) {
523 if (!QWidgetAdapter::isVisible()) {
524 qCDebug(hiding) <<
"Widget" << w <<
" was shown, we're="
526 << QWidgetAdapter::isVisible();
527 QWidgetAdapter::setVisible(
true);
534 if (!isCentralFrame() && hasSingleDockWidget() && containsDockWidget(w)) {
535 if (QWidgetAdapter::isVisible()) {
536 qCDebug(hiding) <<
"Widget" << w <<
" was hidden, we're="
537 <<
"; visible=" << QWidgetAdapter::isVisible()
538 <<
"; dockWidgets=" << dockWidgets();
539 QWidgetAdapter::setVisible(
false);
544void Frame::setLayoutItem(Layouting::Item *item)
546 if (item == m_layoutItem)
550 m_layoutItem->unref();
558 dw->d->addPlaceholderItem(item);
561 dw->d->lastPosition()->removePlaceholders();
565Layouting::Item *Frame::layoutItem()
const
570int Frame::dbg_numFrames()
575bool Frame::beingDeletedLater()
const
577 return m_beingDeleted;
580bool Frame::hasTabsVisible()
const
585 return alwaysShowsTabs() || dockWidgetCount() > 1;
591 if (
auto m = mainWindow())
592 return m->affinities();
595 return dockWidgetAt(0)->affinities();
599void Frame::setLayoutWidget(LayoutWidget *dt)
601 if (dt == m_layoutWidget)
604 const bool wasInMainWindow = dt && isInMainWindow();
605 const bool wasMDI = isMDI();
607 disconnect(m_visibleWidgetCountChangedConnection);
610 delete m_resizeHandler;
611 m_resizeHandler =
nullptr;
613 if (m_layoutWidget) {
615 m_resizeHandler =
new WidgetResizeHandler(WidgetResizeHandler::EventFilterMode::Global, WidgetResizeHandler::WindowMode::MDI,
this);
618 m_visibleWidgetCountChangedConnection =
619 connect(m_layoutWidget, &LayoutWidget::visibleWidgetCountChanged,
this,
620 &Frame::updateTitleBarVisibility);
621 updateTitleBarVisibility();
622 if (wasInMainWindow != isInMainWindow())
623 Q_EMIT isInMainWindowChanged();
626 if (wasMDI != isMDI())
627 Q_EMIT isMDIChanged();
630bool Frame::isTheOnlyFrame()
const
632 return m_layoutWidget && m_layoutWidget->visibleCount() == 1;
635bool Frame::isOverlayed()
const
640void Frame::unoverlay()
642 m_options &= ~FrameOption_IsOverlayed;
645bool Frame::isFloating()
const
647 if (isInMainWindow() || isMDI())
650 return isTheOnlyFrame();
653bool Frame::isInFloatingWindow()
const
655 return floatingWindow() !=
nullptr;
658bool Frame::isInMainWindow()
const
660 return mainWindow() !=
nullptr;
663bool Frame::event(
QEvent *e)
666 if (
auto layoutWidget = qobject_cast<LayoutWidget *>(QWidgetAdapter::parentWidget())) {
667 setLayoutWidget(layoutWidget);
669 setLayoutWidget(
nullptr);
673 return QWidgetAdapter::event(e);
676Frame *Frame::deserialize(
const LayoutSaver::Frame &f)
681 const FrameOptions options = FrameOptions(f.options);
682 Frame *frame =
nullptr;
683 const bool isPersistentCentralFrame = options & FrameOption::FrameOption_IsCentralFrame;
686 if (isPersistentCentralFrame) {
690 if (f.mainWindowUniqueName.isEmpty()) {
692 qWarning() << Q_FUNC_INFO <<
"Frame is the persistent central frame but doesn't have"
693 <<
"an associated window name";
695 if (
MainWindowBase *mw = DockRegistry::self()->mainWindowByName(f.mainWindowUniqueName)) {
696 frame = mw->dropArea()->m_centralFrame;
699 qWarning() <<
"Main window" << f.mainWindowUniqueName <<
"doesn't have central frame";
703 qWarning() << Q_FUNC_INFO <<
"Couldn't find main window"
704 << f.mainWindowUniqueName;
710 frame = widgetFactory->
createFrame(
nullptr, options);
712 frame->setObjectName(f.objectName);
714 for (
const auto &savedDock : qAsConst(f.dockWidgets)) {
715 if (
DockWidgetBase *dw = DockWidgetBase::deserialize(savedDock)) {
716 frame->addWidget(dw);
720 frame->setCurrentTabIndex(f.currentTabIndex);
721 frame->QWidgetAdapter::setGeometry(f.geometry);
726LayoutSaver::Frame Frame::serialize()
const
728 LayoutSaver::Frame frame;
729 frame.isNull =
false;
733 frame.objectName = objectName();
734 frame.geometry = QWidgetAdapter::geometry();
735 frame.options = options();
736 frame.currentTabIndex = currentTabIndex();
740 frame.mainWindowUniqueName = mw->uniqueName();
743 frame.dockWidgets.push_back(dock->d->serialize());
748void Frame::scheduleDeleteLater()
750 qCDebug(creation) << Q_FUNC_INFO <<
this;
751 m_beingDeleted =
true;
758QSize Frame::dockWidgetsMinSize()
const
760 QSize size = Layouting::Item::hardcodedMinimumSize;
767QSize Frame::biggestDockWidgetMaxSize()
const
769 QSize size = Layouting::Item::hardcodedMaximumSize;
771 const QSize dwMax = widgetMaxSize(dw);
772 if (size == Layouting::Item::hardcodedMaximumSize) {
777 const bool hasMaxSize = dwMax != Layouting::Item::hardcodedMaximumSize;
779 size = dw->maximumSize().expandedTo(size);
783 if (size.
width() == 0)
784 size.
setWidth(Layouting::Item::hardcodedMaximumSize.width());
786 size.
setHeight(Layouting::Item::hardcodedMaximumSize.height());
791QRect Frame::dragRect()
const
794 if (m_titleBar->isVisible()) {
795 rect = m_titleBar->rect();
804 return m_layoutWidget ? m_layoutWidget->mainWindow() :
nullptr;
807TabWidget *Frame::tabWidget()
const
817 return dw->options() & option;
826 return dw->options() & option;
834 return dw->layoutSaverOptions() & option;
842 return dw->layoutSaverOptions() & option;
846void Frame::setAllowedResizeSides(CursorPositions sides)
849 delete m_resizeHandler;
850 m_resizeHandler =
new WidgetResizeHandler(WidgetResizeHandler::EventFilterMode::Global, WidgetResizeHandler::WindowMode::MDI,
this);
851 m_resizeHandler->setAllowedResizeSides(sides);
853 delete m_resizeHandler;
854 m_resizeHandler =
nullptr;
858bool Frame::isMDI()
const
860 return mdiLayoutWidget() !=
nullptr;
863bool Frame::isMDIWrapper()
const
865 return mdiDropAreaWrapper() !=
nullptr;
868Frame *Frame::mdiFrame()
const
870 if (
auto dwWrapper = mdiDockWidgetWrapper()) {
871 return dwWrapper->d->frame();
879 if (
auto dropArea = mdiDropAreaWrapper()) {
880 return qobject_cast<DockWidgetBase *>(dropArea->QWidgetAdapter::parent());
886DropArea *Frame::mdiDropAreaWrapper()
const
888 auto dropArea = qobject_cast<DropArea *>(QWidgetAdapter::parent());
889 if (dropArea && dropArea->isMDIWrapper())
894MDILayoutWidget *Frame::mdiLayoutWidget()
const
896 return qobject_cast<MDILayoutWidget *>(m_layoutWidget);
899bool Frame::hasNestedMDIDockWidgets()
const
901 if (!isMDI() || dockWidgetCount() == 0)
904 if (dockWidgetCount() != 1) {
905 qWarning() << Q_FUNC_INFO <<
"Expected a single dock widget wrapper as frame child";
909 return dockWidgetAt(0)->d->isMDIWrapper();
912int Frame::userType()
const
917WidgetResizeHandler *Frame::resizeHandler()
const
919 return m_resizeHandler;
922FloatingWindowFlags Frame::requestedFloatingWindowFlags()
const
924 const auto dockwidgets = this->dockWidgets();
925 if (!dockwidgets.isEmpty())
926 return dockwidgets.first()->floatingWindowFlags();
928 return FloatingWindowFlag::FromGlobalConfig;
Application-wide config to tune certain behaviours of the framework.
static int s_dbg_numFrames
The MainWindow base-class. MainWindow and MainWindowBase are only split in two so we can share some c...
bool isAccepted() const const
QEvent::Type type() const const
void moveTopLeft(const QPoint &position)
void setHeight(int height)
QVector::const_iterator cbegin() const const
QVector::const_iterator cend() const const