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"
34 #include "DropAreaWithCentralFrame_p.h"
36 #include <QCloseEvent>
39 #define MARGIN_THRESHOLD 100
55 Frame::Frame(
QWidgetOrQuick *parent, FrameOptions options,
int userType)
58 , m_tabWidget(
Config::self().frameworkWidgetFactory()->createTabWidget(this))
59 , m_titleBar(
Config::self().frameworkWidgetFactory()->createTitleBar(this))
61 , m_userType(userType)
64 DockRegistry::self()->registerFrame(
this);
66 connect(
this, &Frame::currentDockWidgetChanged,
this, &Frame::updateTitleAndIcon);
68 connect(m_tabWidget->asWidget(), SIGNAL(currentTabChanged(
int)),
69 this, SLOT(onCurrentTabChanged(
int)));
71 setLayoutWidget(qobject_cast<LayoutWidget *>(QWidgetAdapter::parentWidget()));
80 m_layoutItem->unref();
82 delete m_resizeHandler;
83 m_resizeHandler =
nullptr;
85 DockRegistry::self()->unregisterFrame(
this);
88 setLayoutWidget(
nullptr);
91 void Frame::updateTitleAndIcon()
94 m_titleBar->setTitle(dw->title());
95 m_titleBar->setIcon(dw->icon());
97 if (
auto fw = floatingWindow()) {
98 if (fw->hasSingleFrame()) {
99 fw->updateTitleAndIcon();
103 setObjectName(dw->uniqueName());
105 }
else if (currentTabIndex() != -1) {
106 qWarning() << Q_FUNC_INFO <<
"Invalid dock widget for frame." << currentTabIndex();
110 void Frame::onDockWidgetTitleChanged()
112 updateTitleAndIcon();
115 if (
auto dw = qobject_cast<DockWidgetBase *>(sender())) {
116 int index = indexOfDockWidget(dw);
117 renameTab(index, dw->title());
118 changeTabIcon(index, dw->icon(DockWidgetBase::IconPlace::TabBar));
125 insertWidget(dockWidget, dockWidgetCount(), addingOption);
128 void Frame::addWidget(Frame *frame,
InitialOption addingOption)
130 if (frame->isEmpty()) {
131 qWarning() <<
"Frame::addWidget: frame is empty." << frame;
135 const auto &docks = frame->dockWidgets();
137 addWidget(dockWidget, addingOption);
140 void Frame::addWidget(FloatingWindow *floatingWindow,
InitialOption addingOption)
142 Q_ASSERT(floatingWindow);
143 for (Frame *f : floatingWindow->frames())
144 addWidget(f, addingOption);
149 Q_ASSERT(dockWidget);
150 if (containsDockWidget(dockWidget)) {
152 qWarning() <<
"Frame::addWidget dockWidget already exists. this=" <<
this <<
"; dockWidget=" << dockWidget;
156 dockWidget->d->addPlaceholderItem(m_layoutItem);
158 insertDockWidget(dockWidget, index);
163 if (hasSingleDockWidget()) {
164 Q_EMIT currentDockWidgetChanged(dockWidget);
171 resize(dockWidget->size());
176 connect(dockWidget, &DockWidgetBase::titleChanged,
this, &Frame::onDockWidgetTitleChanged);
177 connect(dockWidget, &DockWidgetBase::iconChanged,
this, &Frame::onDockWidgetTitleChanged);
182 disconnect(dw, &DockWidgetBase::titleChanged,
this, &Frame::onDockWidgetTitleChanged);
183 disconnect(dw, &DockWidgetBase::iconChanged,
this, &Frame::onDockWidgetTitleChanged);
184 removeWidget_impl(dw);
189 if (m_inCtor || m_inDtor)
192 dockWidget->d->saveTabIndex();
194 QRect r = dockWidget->geometry();
195 removeWidget(dockWidget);
197 auto newFrame = Config::self().frameworkWidgetFactory()->createFrame();
199 newFrame->addWidget(dockWidget);
203 auto floatingWindow = Config::self().frameworkWidgetFactory()->createFloatingWindow(newFrame);
206 floatingWindow->show();
208 return floatingWindow;
213 if (m_inCtor || m_inDtor)
216 return indexOfDockWidget_impl(dw);
219 int Frame::currentIndex()
const
221 if (m_inCtor || m_inDtor)
224 return currentIndex_impl();
227 void Frame::setCurrentTabIndex(
int index)
229 if (m_inCtor || m_inDtor)
232 setCurrentTabIndex_impl(index);
237 if (m_inCtor || m_inDtor)
240 setCurrentDockWidget_impl(dw);
245 if (m_inCtor || m_inDtor)
248 insertDockWidget_impl(dw, index);
253 if (m_inCtor || m_inDtor)
256 return dockWidgetAt_impl(index);
261 if (m_inCtor || m_inDtor)
264 return currentDockWidget_impl();
267 int Frame::dockWidgetCount()
const
269 if (m_inCtor || m_inDtor)
272 return m_tabWidget->numDockWidgets();
275 void Frame::onDockWidgetCountChanged()
277 qCDebug(docking) <<
"Frame::onDockWidgetCountChanged:" <<
this <<
"; widgetCount=" << dockWidgetCount();
278 if (isEmpty() && !isCentralFrame()) {
279 scheduleDeleteLater();
281 updateTitleBarVisibility();
285 Q_EMIT hasTabsVisibleChanged();
289 dock->d->updateFloatAction();
292 Q_EMIT numDockWidgetsChanged();
295 void Frame::onCurrentTabChanged(
int index)
298 if (
auto dock = dockWidgetAt(index)) {
299 Q_EMIT currentDockWidgetChanged(dock);
301 qWarning() <<
"dockWidgetAt" << index <<
"returned nullptr" <<
this;
306 void Frame::isFocusedChangedCallback()
308 Q_EMIT isFocusedChanged();
311 void Frame::focusedWidgetChangedCallback()
313 Q_EMIT focusedWidgetChanged();
316 void Frame::updateTitleBarVisibility()
318 if (m_updatingTitleBar || m_beingDeleted) {
325 bool visible =
false;
326 if (isCentralFrame()) {
328 }
else if ((Config::self().flags() & Config::Flag_HideTitleBarWhenTabsVisible) && hasTabsVisible()) {
330 }
else if (FloatingWindow *fw = floatingWindow()) {
332 visible = !fw->hasSingleFrame();
337 const bool wasVisible = m_titleBar->isVisible();
338 m_titleBar->setVisible(visible);
340 if (wasVisible != visible) {
341 Q_EMIT actualTitleBarChanged();
342 for (
auto dw : dockWidgets())
346 if (
auto fw = floatingWindow()) {
349 fw->updateTitleBarVisibility();
353 void Frame::updateFloatingActions()
357 dw->d->updateFloatAction();
360 bool Frame::containsMouse(
QPoint globalPos)
const
362 return QWidgetAdapter::rect().contains(KDDockWidgets::QWidgetAdapter::mapFromGlobal(globalPos));
365 TitleBar *Frame::titleBar()
const
370 TitleBar *Frame::actualTitleBar()
const
372 if (FloatingWindow *fw = floatingWindow()) {
374 if (fw->hasSingleFrame())
375 return fw->titleBar();
383 return m_titleBar->title();
386 QIcon Frame::icon()
const
388 return m_titleBar->icon();
393 if (m_inCtor || m_inDtor)
397 const int count = dockWidgetCount();
399 for (
int i = 0; i < count; ++i)
400 dockWidgets << dockWidgetAt(i);
407 const int count = dockWidgetCount();
408 for (
int i = 0, e = count; i != e; ++i) {
409 if (dockWidget == dockWidgetAt(i))
415 FloatingWindow *Frame::floatingWindow()
const
421 auto p = QWidgetAdapter::parentWidget();
423 if (qobject_cast<KDDockWidgets::MainWindowBase *>(p))
426 if (
auto fw = qobject_cast<FloatingWindow *>(p))
434 p = p->parentWidget();
440 void Frame::restoreToPreviousPosition()
442 if (hasSingleDockWidget()) {
443 qWarning() << Q_FUNC_INFO <<
"Invalid usage, there's no tabs";
448 qCDebug(placeholder) << Q_FUNC_INFO <<
"There's no previous position known";
452 if (!m_layoutItem->isPlaceholder()) {
454 qCDebug(placeholder) << Q_FUNC_INFO <<
"Previous position isn't a placeholder";
458 m_layoutItem->restore(
this);
461 int Frame::currentTabIndex()
const
463 return currentIndex();
468 qCDebug(closing) <<
"Frame::closeEvent";
472 qApp->sendEvent(dock, e);
478 bool Frame::anyNonClosable()
const
480 for (
auto dw : dockWidgets()) {
481 if ((dw->
options() & DockWidgetBase::Option_NotClosable) && !DockRegistry::self()->isProcessingAppQuitEvent())
488 bool Frame::anyNonDockable()
const
490 for (
auto dw : dockWidgets()) {
491 if (dw->
options() & DockWidgetBase::Option_NotDockable)
500 if (hasSingleDockWidget() && containsDockWidget(w)) {
501 if (!QWidgetAdapter::isVisible()) {
502 qCDebug(hiding) <<
"Widget" << w <<
" was shown, we're="
504 << QWidgetAdapter::isVisible();
505 QWidgetAdapter::setVisible(
true);
512 if (!isCentralFrame() && hasSingleDockWidget() && containsDockWidget(w)) {
513 if (QWidgetAdapter::isVisible()) {
514 qCDebug(hiding) <<
"Widget" << w <<
" was hidden, we're="
515 <<
"; visible=" << QWidgetAdapter::isVisible()
516 <<
"; dockWidgets=" << dockWidgets();
517 QWidgetAdapter::setVisible(
false);
522 void Frame::setLayoutItem(Layouting::Item *item)
524 if (item == m_layoutItem)
528 m_layoutItem->unref();
536 dw->d->addPlaceholderItem(item);
539 dw->d->lastPositions().removePlaceholders();
543 Layouting::Item *Frame::layoutItem()
const
548 int Frame::dbg_numFrames()
553 bool Frame::beingDeletedLater()
const
555 return m_beingDeleted;
558 bool Frame::hasTabsVisible()
const
563 return alwaysShowsTabs() || dockWidgetCount() > 1;
571 return dockWidgetAt(0)->affinities();
575 void Frame::setLayoutWidget(LayoutWidget *dt)
577 if (dt == m_layoutWidget)
580 const bool wasInMainWindow = dt && isInMainWindow();
581 const bool wasMDI = isMDI();
583 disconnect(m_visibleWidgetCountChangedConnection);
586 delete m_resizeHandler;
587 m_resizeHandler =
nullptr;
589 if (m_layoutWidget) {
591 m_resizeHandler =
new WidgetResizeHandler(
false,
this);
594 m_visibleWidgetCountChangedConnection =
595 connect(m_layoutWidget, &LayoutWidget::visibleWidgetCountChanged,
this,
596 &Frame::updateTitleBarVisibility);
597 updateTitleBarVisibility();
598 if (wasInMainWindow != isInMainWindow())
599 Q_EMIT isInMainWindowChanged();
602 if (wasMDI != isMDI())
603 Q_EMIT isMDIChanged();
606 bool Frame::isTheOnlyFrame()
const
608 return m_layoutWidget && m_layoutWidget->visibleCount() == 1;
611 bool Frame::isOverlayed()
const
616 void Frame::unoverlay()
621 bool Frame::isFloating()
const
623 if (isInMainWindow())
626 return isTheOnlyFrame();
629 bool Frame::isInFloatingWindow()
const
631 return floatingWindow() !=
nullptr;
634 bool Frame::isInMainWindow()
const
636 return mainWindow() !=
nullptr;
639 bool Frame::event(
QEvent *e)
642 if (
auto layoutWidget = qobject_cast<LayoutWidget *>(QWidgetAdapter::parentWidget())) {
643 setLayoutWidget(layoutWidget);
645 setLayoutWidget(
nullptr);
649 return QWidgetAdapter::event(e);
652 Frame *Frame::deserialize(
const LayoutSaver::Frame &f)
657 const FrameOptions options = FrameOptions(f.options);
658 Frame *frame =
nullptr;
660 auto widgetFactory = Config::self().frameworkWidgetFactory();
662 if (isPersistentCentralFrame) {
666 if (f.mainWindowUniqueName.isEmpty()) {
668 qWarning() << Q_FUNC_INFO <<
"Frame is the persistent central frame but doesn't have"
669 <<
"an associated window name";
671 if (
MainWindowBase *mw = DockRegistry::self()->mainWindowByName(f.mainWindowUniqueName)) {
672 frame = mw->dropArea()->m_centralFrame;
675 qWarning() <<
"Main window" << f.mainWindowUniqueName <<
"doesn't have central frame";
679 qWarning() << Q_FUNC_INFO <<
"Couldn't find main window"
680 << f.mainWindowUniqueName;
686 frame = widgetFactory->createFrame(
nullptr, options);
688 frame->setObjectName(f.objectName);
690 for (
const auto &savedDock : qAsConst(f.dockWidgets)) {
691 if (
DockWidgetBase *dw = DockWidgetBase::deserialize(savedDock)) {
692 frame->addWidget(dw);
696 frame->setCurrentTabIndex(f.currentTabIndex);
697 frame->QWidgetAdapter::setGeometry(f.geometry);
702 LayoutSaver::Frame Frame::serialize()
const
704 LayoutSaver::Frame frame;
705 frame.isNull =
false;
709 frame.objectName = objectName();
710 frame.geometry = QWidgetAdapter::geometry();
711 frame.options = options();
712 frame.currentTabIndex = currentTabIndex();
716 frame.mainWindowUniqueName = mw->uniqueName();
719 frame.dockWidgets.push_back(dock->d->serialize());
724 void Frame::scheduleDeleteLater()
726 qCDebug(creation) << Q_FUNC_INFO <<
this;
727 m_beingDeleted =
true;
734 QSize Frame::dockWidgetsMinSize()
const
736 QSize size = Layouting::Item::hardcodedMinimumSize;
743 QSize Frame::biggestDockWidgetMaxSize()
const
745 QSize size = Layouting::Item::hardcodedMaximumSize;
747 const QSize dwMax = widgetMaxSize(dw);
748 if (size == Layouting::Item::hardcodedMaximumSize) {
753 const bool hasMaxSize = dwMax != Layouting::Item::hardcodedMaximumSize;
755 size = dw->maximumSize().expandedTo(size);
759 if (size.
width() == 0)
760 size.
setWidth(Layouting::Item::hardcodedMaximumSize.width());
762 size.
setHeight(Layouting::Item::hardcodedMaximumSize.height());
767 QRect Frame::dragRect()
const
770 if (m_titleBar->isVisible()) {
771 rect = m_titleBar->rect();
780 return m_layoutWidget ? m_layoutWidget->mainWindow() :
nullptr;
783 TabWidget *Frame::tabWidget()
const
793 return dw->options() & option;
802 return dw->options() & option;
810 return dw->layoutSaverOptions() & option;
818 return dw->layoutSaverOptions() & option;
822 void Frame::setAllowedResizeSides(CursorPositions sides)
825 delete m_resizeHandler;
826 m_resizeHandler =
new WidgetResizeHandler(
false,
this);
827 m_resizeHandler->setAllowedResizeSides(sides);
829 delete m_resizeHandler;
830 m_resizeHandler =
nullptr;
834 bool Frame::isMDI()
const
836 return mdiLayoutWidget() !=
nullptr;
839 MDILayoutWidget *Frame::mdiLayoutWidget()
const
841 return qobject_cast<MDILayoutWidget *>(m_layoutWidget);
844 int Frame::userType()
const
849 WidgetResizeHandler *Frame::resizeHandler()
const
851 return m_resizeHandler;