KDDockWidgets API Documentation 1.7
Loading...
Searching...
No Matches
Frame.cpp
Go to the documentation of this file.
1/*
2 This file is part of KDDockWidgets.
3
4 SPDX-FileCopyrightText: 2019-2023 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
5 Author: SĂ©rgio Martins <sergio.martins@kdab.com>
6
7 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
8
9 Contact KDAB at <info@kdab.com> for commercial licensing options.
10*/
11
19#include "Frame_p.h"
20#include "Config.h"
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"
31#include "Utils_p.h"
32#include "WidgetResizeHandler_p.h"
33#include "MDILayoutWidget_p.h"
34#include "DropAreaWithCentralFrame_p.h"
35#include "multisplitter/Item_p.h"
36
37#include <QCloseEvent>
38#include <QTimer>
39
40#define MARGIN_THRESHOLD 100
41
42static int s_dbg_numFrames = 0;
43
44using namespace KDDockWidgets;
45
46namespace KDDockWidgets {
47static FrameOptions actualOptions(FrameOptions options)
48{
51
52 return options;
53}
54
55static TabWidgetOptions tabWidgetOptions(FrameOptions options)
56{
57 if (options & FrameOption_NonDockable) {
60 }
61
63}
64}
65
66Frame::Frame(QWidgetOrQuick *parent, FrameOptions options, int userType)
67 : LayoutGuestWidget(parent)
68 , FocusScope(this)
69 , m_tabWidget(Config::self().frameworkWidgetFactory()->createTabWidget(this, tabWidgetOptions(options)))
70 , m_titleBar(Config::self().frameworkWidgetFactory()->createTitleBar(this))
71 , m_options(actualOptions(options))
72 , m_userType(userType)
73{
75 DockRegistry::self()->registerFrame(this);
76
77 connect(this, &Frame::currentDockWidgetChanged, this, &Frame::updateTitleAndIcon);
78
79 connect(m_tabWidget->asWidget(), SIGNAL(currentTabChanged(int)), // clazy:exclude=old-style-connect
80 this, SLOT(onCurrentTabChanged(int)));
81
82 setLayoutWidget(qobject_cast<LayoutWidget *>(QWidgetAdapter::parentWidget()));
83 m_inCtor = false;
84}
85
86Frame::~Frame()
87{
88 m_inDtor = true;
90 if (m_layoutItem)
91 m_layoutItem->unref();
92
93 delete m_resizeHandler;
94 m_resizeHandler = nullptr;
95
96 DockRegistry::self()->unregisterFrame(this);
97
98 // Run some disconnects() too, so we don't receive signals during destruction:
99 setLayoutWidget(nullptr);
100}
101
102void Frame::updateTitleAndIcon()
103{
104 if (DockWidgetBase *dw = currentDockWidget()) {
105 m_titleBar->setTitle(dw->title());
106 m_titleBar->setIcon(dw->icon());
107
108 if (auto fw = floatingWindow()) {
109 if (fw->hasSingleFrame()) {
110 fw->updateTitleAndIcon();
111 }
112 }
113
114 setObjectName(dw->uniqueName());
115
116 } else if (currentTabIndex() != -1) {
117 qWarning() << Q_FUNC_INFO << "Invalid dock widget for frame." << currentTabIndex();
118 }
119}
120
121void Frame::onDockWidgetTitleChanged()
122{
123 updateTitleAndIcon();
124
125 if (!m_inCtor) { // don't call pure virtual in ctor
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));
130 }
131 }
132}
133
134void Frame::addWidget(DockWidgetBase *dockWidget, InitialOption addingOption)
135{
136 insertWidget(dockWidget, dockWidgetCount(), addingOption); // append
137}
138
139void Frame::addWidget(Frame *frame, InitialOption addingOption)
140{
141 if (frame->isEmpty()) {
142 qWarning() << "Frame::addWidget: frame is empty." << frame;
143 return;
144 }
145
146 const auto &docks = frame->dockWidgets();
147 for (DockWidgetBase *dockWidget : docks)
148 addWidget(dockWidget, addingOption);
149}
150
151void Frame::addWidget(FloatingWindow *floatingWindow, InitialOption addingOption)
152{
153 Q_ASSERT(floatingWindow);
154 for (Frame *f : floatingWindow->frames())
155 addWidget(f, addingOption);
156}
157
158void Frame::insertWidget(DockWidgetBase *dockWidget, int index, InitialOption addingOption)
159{
160 Q_ASSERT(dockWidget);
161 if (containsDockWidget(dockWidget)) {
162 if (!dockWidget->isPersistentCentralDockWidget())
163 qWarning() << "Frame::addWidget dockWidget already exists. this=" << this << "; dockWidget=" << dockWidget;
164 return;
165 }
166 if (m_layoutItem)
167 dockWidget->d->addPlaceholderItem(m_layoutItem);
168
169 const int originalCurrentIndex = currentIndex();
170
171 insertDockWidget(dockWidget, index);
172
173 if (addingOption.startsHidden()) {
174 dockWidget->close(); // Ensure closed
175 } else {
176 if (hasSingleDockWidget()) {
177 Q_EMIT currentDockWidgetChanged(dockWidget);
178 setObjectName(dockWidget->uniqueName());
179
180 if (!m_layoutItem) {
181 // When adding the 1st dock widget of a fresh frame, let's give the frame the size
182 // of the dock widget, so that when adding it to the main window, the main window can
183 // use that size as the initial suggested size.
184 resize(dockWidget->size());
185 }
186 } else if (addingOption.preservesCurrentTab() && originalCurrentIndex != -1) {
187 setCurrentTabIndex(originalCurrentIndex);
188 }
189 }
190
191 connect(dockWidget, &DockWidgetBase::titleChanged, this, &Frame::onDockWidgetTitleChanged);
192 connect(dockWidget, &DockWidgetBase::iconChanged, this, &Frame::onDockWidgetTitleChanged);
193}
194
195void Frame::removeWidget(DockWidgetBase *dw)
196{
197 disconnect(dw, &DockWidgetBase::titleChanged, this, &Frame::onDockWidgetTitleChanged);
198 disconnect(dw, &DockWidgetBase::iconChanged, this, &Frame::onDockWidgetTitleChanged);
199 removeWidget_impl(dw);
200}
201
202FloatingWindow *Frame::detachTab(DockWidgetBase *dockWidget)
203{
204 if (m_inCtor || m_inDtor)
205 return nullptr;
206
207 dockWidget->d->saveTabIndex();
208
209 QRect r = dockWidget->geometry();
210 removeWidget(dockWidget);
211
212 auto newFrame = Config::self().frameworkWidgetFactory()->createFrame();
213 const QPoint globalPoint = mapToGlobal(QPoint(0, 0));
214 newFrame->addWidget(dockWidget);
215
216 // We're potentially already dead at this point, as frames with 0 tabs auto-destruct. Don't access members from this point.
217
218 auto floatingWindow = Config::self().frameworkWidgetFactory()->createFloatingWindow(newFrame);
219 r.moveTopLeft(globalPoint);
220 floatingWindow->setSuggestedGeometry(r, SuggestedGeometryHint_GeometryIsFromDocked);
221 floatingWindow->show();
222
223 return floatingWindow;
224}
225
226int Frame::indexOfDockWidget(const DockWidgetBase *dw)
227{
228 if (m_inCtor || m_inDtor)
229 return -1;
230
231 return indexOfDockWidget_impl(dw);
232}
233
234int Frame::currentIndex() const
235{
236 if (m_inCtor || m_inDtor)
237 return -1;
238
239 return currentIndex_impl();
240}
241
242void Frame::setCurrentTabIndex(int index)
243{
244 if (m_inCtor || m_inDtor)
245 return;
246
247 setCurrentTabIndex_impl(index);
248}
249
250void Frame::setCurrentDockWidget(DockWidgetBase *dw)
251{
252 if (m_inCtor || m_inDtor)
253 return;
254
255 setCurrentDockWidget_impl(dw);
256}
257
258void Frame::insertDockWidget(DockWidgetBase *dw, int index)
259{
260 if (m_inCtor || m_inDtor)
261 return;
262
263 insertDockWidget_impl(dw, index);
264}
265
266DockWidgetBase *Frame::dockWidgetAt(int index) const
267{
268 if (m_inCtor || m_inDtor)
269 return nullptr;
270
271 return dockWidgetAt_impl(index);
272}
273
274DockWidgetBase *Frame::currentDockWidget() const
275{
276 if (m_inCtor || m_inDtor)
277 return nullptr;
278
279 return currentDockWidget_impl();
280}
281
282int Frame::dockWidgetCount() const
283{
284 if (m_inCtor || m_inDtor)
285 return 0;
286
287 return m_tabWidget->numDockWidgets();
288}
289
290void Frame::onDockWidgetCountChanged()
291{
292 qCDebug(docking) << "Frame::onDockWidgetCountChanged:" << this << "; widgetCount=" << dockWidgetCount();
293 if (isEmpty() && !isCentralFrame()) {
294 scheduleDeleteLater();
295 } else {
296 updateTitleBarVisibility();
297
298 // We don't really keep track of the state, so emit even if the visibility didn't change. No biggie.
299 if (!(m_options & FrameOption_AlwaysShowsTabs))
300 Q_EMIT hasTabsVisibleChanged();
301
302 const DockWidgetBase::List docks = dockWidgets();
303 for (DockWidgetBase *dock : docks)
304 dock->d->updateFloatAction();
305 }
306
307 Q_EMIT numDockWidgetsChanged();
308}
309
310void Frame::onCurrentTabChanged(int index)
311{
312 if (index != -1) {
313 if (auto dock = dockWidgetAt(index)) {
314 Q_EMIT currentDockWidgetChanged(dock);
315 } else {
316 qWarning() << "dockWidgetAt" << index << "returned nullptr" << this;
317 }
318 }
319}
320
321void Frame::isFocusedChangedCallback()
322{
323 Q_EMIT isFocusedChanged();
324}
325
326void Frame::focusedWidgetChangedCallback()
327{
328 Q_EMIT focusedWidgetChanged();
329}
330
331void Frame::updateTitleBarVisibility()
332{
333 if (m_updatingTitleBar || m_beingDeleted) {
334 // To break a cyclic dependency
335 return;
336 }
337
338 QScopedValueRollback<bool> guard(m_updatingTitleBar, true);
339
340 bool visible = false;
341 if (isCentralFrame()) {
342 visible = false;
343 } else if ((Config::self().flags() & Config::Flag_HideTitleBarWhenTabsVisible) && hasTabsVisible()) {
344 visible = false;
345 } else if (FloatingWindow *fw = floatingWindow()) {
346 // If there's nested frames then show each Frame's title bar
347 visible = !fw->hasSingleFrame();
348 } else if (isMDIWrapper()) {
349 auto dropArea = this->mdiDropAreaWrapper();
350 visible = !dropArea->hasSingleFrame();
351 } else {
352 visible = true;
353 }
354
355 const bool wasVisible = m_titleBar->isVisible();
356 m_titleBar->setVisible(visible);
357
358 if (wasVisible != visible) {
359 Q_EMIT actualTitleBarChanged();
360 for (auto dw : dockWidgets())
361 Q_EMIT dw->actualTitleBarChanged();
362 }
363
364 if (auto fw = floatingWindow()) {
365 // Update the floating window which might be using Flag_HideTitleBarWhenTabsVisible
366 // In that case it might not show title bar depending on the number of tabs that the frame has
367 fw->updateTitleBarVisibility();
368 }
369}
370
371void Frame::updateFloatingActions()
372{
373 const QVector<DockWidgetBase *> widgets = dockWidgets();
374 for (DockWidgetBase *dw : widgets)
375 dw->d->updateFloatAction();
376}
377
378bool Frame::containsMouse(QPoint globalPos) const
379{
380 return QWidgetAdapter::rect().contains(KDDockWidgets::QWidgetAdapter::mapFromGlobal(globalPos));
381}
382
383TitleBar *Frame::titleBar() const
384{
385 return m_titleBar;
386}
387
388TitleBar *Frame::actualTitleBar() const
389{
390 if (FloatingWindow *fw = floatingWindow()) {
391 // If there's nested frames then show each Frame's title bar
392 if (fw->hasSingleFrame())
393 return fw->titleBar();
394 } else if (auto mdiDropArea = mdiDropAreaWrapper()) {
395 if (mdiDropArea->hasSingleFrame()) {
396 return mdiFrame()->titleBar();
397 }
398 }
399
400 return titleBar();
401}
402
403QString Frame::title() const
404{
405 return m_titleBar->title();
406}
407
408QIcon Frame::icon() const
409{
410 return m_titleBar->icon();
411}
412
413const DockWidgetBase::List Frame::dockWidgets() const
414{
415 if (m_inCtor || m_inDtor)
416 return {};
417
418 DockWidgetBase::List dockWidgets;
419 const int count = dockWidgetCount();
420 dockWidgets.reserve(count);
421 for (int i = 0; i < count; ++i)
422 dockWidgets << dockWidgetAt(i);
423
424 return dockWidgets;
425}
426
427bool Frame::containsDockWidget(DockWidgetBase *dockWidget) const
428{
429 const int count = dockWidgetCount();
430 for (int i = 0, e = count; i != e; ++i) {
431 if (dockWidget == dockWidgetAt(i))
432 return true;
433 }
434 return false;
435}
436
437FloatingWindow *Frame::floatingWindow() const
438{
439 // Returns the first FloatingWindow* parent in the hierarchy.
440 // However, if there's a MainWindow in the hierarchy it stops, which can
441 // happen with nested main windows.
442
443 auto p = QWidgetAdapter::parentWidget();
444 while (p) {
445 if (qobject_cast<KDDockWidgets::MainWindowBase *>(p))
446 return nullptr;
447
448 if (auto fw = qobject_cast<FloatingWindow *>(p))
449 return fw;
450
451 if (p == window()) {
452 // We stop at the window. (top-levels can have parent, but we're not interested)
453 return nullptr;
454 }
455
456 p = p->parentWidget();
457 }
458
459 return nullptr;
460}
461
462void Frame::restoreToPreviousPosition()
463{
464 if (hasSingleDockWidget()) {
465 qWarning() << Q_FUNC_INFO << "Invalid usage, there's no tabs";
466 return;
467 }
468
469 if (!m_layoutItem) {
470 qCDebug(placeholder) << Q_FUNC_INFO << "There's no previous position known";
471 return;
472 }
473
474 if (!m_layoutItem->isPlaceholder()) {
475 // Maybe in this case just fold the frame into the placeholder, which probably has other dockwidgets which were added meanwhile. TODO
476 qCDebug(placeholder) << Q_FUNC_INFO << "Previous position isn't a placeholder";
477 return;
478 }
479
480 m_layoutItem->restore(this);
481}
482
483int Frame::currentTabIndex() const
484{
485 return currentIndex();
486}
487
488void Frame::onCloseEvent(QCloseEvent *e)
489{
490 qCDebug(closing) << "Frame::closeEvent";
491 e->accept(); // Accepted by default (will close unless ignored)
492 const DockWidgetBase::List docks = dockWidgets();
493 for (DockWidgetBase *dock : docks) {
494 qApp->sendEvent(dock, e);
495 if (!e->isAccepted())
496 break; // Stop when the first dockwidget prevents closing
497 }
498}
499
500bool Frame::anyNonClosable() const
501{
502 for (auto dw : dockWidgets()) {
503 if ((dw->options() & DockWidgetBase::Option_NotClosable) && !DockRegistry::self()->isProcessingAppQuitEvent())
504 return true;
505 }
506
507 return false;
508}
509
510bool Frame::anyNonDockable() const
511{
512 for (auto dw : dockWidgets()) {
514 return true;
515 }
516
517 return false;
518}
519
520void Frame::onDockWidgetShown(DockWidgetBase *w)
521{
522 if (hasSingleDockWidget() && containsDockWidget(w)) { // We have to call contains because it might be being in process of being reparented
523 if (!QWidgetAdapter::isVisible()) {
524 qCDebug(hiding) << "Widget" << w << " was shown, we're="
525 << "; visible="
526 << QWidgetAdapter::isVisible();
527 QWidgetAdapter::setVisible(true);
528 }
529 }
530}
531
532void Frame::onDockWidgetHidden(DockWidgetBase *w)
533{
534 if (!isCentralFrame() && hasSingleDockWidget() && containsDockWidget(w)) { // We have to call contains because it might be being in process of being reparented
535 if (QWidgetAdapter::isVisible()) {
536 qCDebug(hiding) << "Widget" << w << " was hidden, we're="
537 << "; visible=" << QWidgetAdapter::isVisible()
538 << "; dockWidgets=" << dockWidgets();
539 QWidgetAdapter::setVisible(false);
540 }
541 }
542}
543
544void Frame::setLayoutItem(Layouting::Item *item)
545{
546 if (item == m_layoutItem)
547 return;
548
549 if (m_layoutItem)
550 m_layoutItem->unref();
551
552 if (item)
553 item->ref();
554
555 m_layoutItem = item;
556 if (item) {
557 for (DockWidgetBase *dw : dockWidgets())
558 dw->d->addPlaceholderItem(item);
559 } else {
560 for (DockWidgetBase *dw : dockWidgets())
561 dw->d->lastPosition()->removePlaceholders();
562 }
563}
564
565Layouting::Item *Frame::layoutItem() const
566{
567 return m_layoutItem;
568}
569
570int Frame::dbg_numFrames()
571{
572 return s_dbg_numFrames;
573}
574
575bool Frame::beingDeletedLater() const
576{
577 return m_beingDeleted;
578}
579
580bool Frame::hasTabsVisible() const
581{
582 if (m_beingDeleted)
583 return false;
584
585 return alwaysShowsTabs() || dockWidgetCount() > 1;
586}
587
588QStringList Frame::affinities() const
589{
590 if (isEmpty()) {
591 if (auto m = mainWindow())
592 return m->affinities();
593 return {};
594 } else {
595 return dockWidgetAt(0)->affinities();
596 }
597}
598
599void Frame::setLayoutWidget(LayoutWidget *dt)
600{
601 if (dt == m_layoutWidget)
602 return;
603
604 const bool wasInMainWindow = dt && isInMainWindow();
605 const bool wasMDI = isMDI();
606 if (m_layoutWidget)
607 disconnect(m_visibleWidgetCountChangedConnection);
608
609 m_layoutWidget = dt;
610 delete m_resizeHandler;
611 m_resizeHandler = nullptr;
612
613 if (m_layoutWidget) {
614 if (isMDI())
615 m_resizeHandler = new WidgetResizeHandler(WidgetResizeHandler::EventFilterMode::Global, WidgetResizeHandler::WindowMode::MDI, this);
616
617 // We keep the connect result so we don't dereference m_layoutWidget at shutdown
618 m_visibleWidgetCountChangedConnection =
619 connect(m_layoutWidget, &LayoutWidget::visibleWidgetCountChanged, this,
620 &Frame::updateTitleBarVisibility);
621 updateTitleBarVisibility();
622 if (wasInMainWindow != isInMainWindow())
623 Q_EMIT isInMainWindowChanged();
624 }
625
626 if (wasMDI != isMDI())
627 Q_EMIT isMDIChanged();
628}
629
630bool Frame::isTheOnlyFrame() const
631{
632 return m_layoutWidget && m_layoutWidget->visibleCount() == 1;
633}
634
635bool Frame::isOverlayed() const
636{
637 return m_options & FrameOption_IsOverlayed;
638}
639
640void Frame::unoverlay()
641{
642 m_options &= ~FrameOption_IsOverlayed;
643}
644
645bool Frame::isFloating() const
646{
647 if (isInMainWindow() || isMDI())
648 return false;
649
650 return isTheOnlyFrame();
651}
652
653bool Frame::isInFloatingWindow() const
654{
655 return floatingWindow() != nullptr;
656}
657
658bool Frame::isInMainWindow() const
659{
660 return mainWindow() != nullptr;
661}
662
663bool Frame::event(QEvent *e)
664{
665 if (e->type() == QEvent::ParentChange) {
666 if (auto layoutWidget = qobject_cast<LayoutWidget *>(QWidgetAdapter::parentWidget())) {
667 setLayoutWidget(layoutWidget);
668 } else {
669 setLayoutWidget(nullptr);
670 }
671 }
672
673 return QWidgetAdapter::event(e);
674}
675
676Frame *Frame::deserialize(const LayoutSaver::Frame &f)
677{
678 if (!f.isValid())
679 return nullptr;
680
681 const FrameOptions options = FrameOptions(f.options);
682 Frame *frame = nullptr;
683 const bool isPersistentCentralFrame = options & FrameOption::FrameOption_IsCentralFrame;
684 auto widgetFactory = Config::self().frameworkWidgetFactory();
685
686 if (isPersistentCentralFrame) {
687 // Don't create a new Frame if we're restoring the Persistent Central frame (the one created
688 // by MainWindowOption_HasCentralFrame). It already exists.
689
690 if (f.mainWindowUniqueName.isEmpty()) {
691 // Can happen with older serialization formats
692 qWarning() << Q_FUNC_INFO << "Frame is the persistent central frame but doesn't have"
693 << "an associated window name";
694 } else {
695 if (MainWindowBase *mw = DockRegistry::self()->mainWindowByName(f.mainWindowUniqueName)) {
696 frame = mw->dropArea()->m_centralFrame;
697 if (!frame) {
698 // Doesn't happen...
699 qWarning() << "Main window" << f.mainWindowUniqueName << "doesn't have central frame";
700 }
701 } else {
702 // Doesn't happen...
703 qWarning() << Q_FUNC_INFO << "Couldn't find main window"
704 << f.mainWindowUniqueName;
705 }
706 }
707 }
708
709 if (!frame)
710 frame = widgetFactory->createFrame(/*parent=*/nullptr, options);
711
712 frame->setObjectName(f.objectName);
713
714 for (const auto &savedDock : qAsConst(f.dockWidgets)) {
715 if (DockWidgetBase *dw = DockWidgetBase::deserialize(savedDock)) {
716 frame->addWidget(dw);
717 }
718 }
719
720 frame->setCurrentTabIndex(f.currentTabIndex);
721 frame->QWidgetAdapter::setGeometry(f.geometry);
722
723 return frame;
724}
725
726LayoutSaver::Frame Frame::serialize() const
727{
728 LayoutSaver::Frame frame;
729 frame.isNull = false;
730
731 const DockWidgetBase::List docks = dockWidgets();
732
733 frame.objectName = objectName();
734 frame.geometry = QWidgetAdapter::geometry();
735 frame.options = options();
736 frame.currentTabIndex = currentTabIndex();
737 frame.id = id(); // for coorelation purposes
738
739 if (MainWindowBase *mw = mainWindow())
740 frame.mainWindowUniqueName = mw->uniqueName();
741
742 for (DockWidgetBase *dock : docks)
743 frame.dockWidgets.push_back(dock->d->serialize());
744
745 return frame;
746}
747
748void Frame::scheduleDeleteLater()
749{
750 qCDebug(creation) << Q_FUNC_INFO << this;
751 m_beingDeleted = true;
752 QTimer::singleShot(0, this, [this] {
753 // Can't use deleteLater() here due to QTBUG-83030 (deleteLater() never delivered if triggered by a sendEvent() before event loop starts)
754 delete this;
755 });
756}
757
758QSize Frame::dockWidgetsMinSize() const
759{
760 QSize size = Layouting::Item::hardcodedMinimumSize;
761 for (DockWidgetBase *dw : dockWidgets())
762 size = size.expandedTo(Layouting::Widget::widgetMinSize(dw));
763
764 return size;
765}
766
767QSize Frame::biggestDockWidgetMaxSize() const
768{
769 QSize size = Layouting::Item::hardcodedMaximumSize;
770 for (DockWidgetBase *dw : dockWidgets()) {
771 const QSize dwMax = widgetMaxSize(dw);
772 if (size == Layouting::Item::hardcodedMaximumSize) {
773 size = dwMax;
774 continue;
775 }
776
777 const bool hasMaxSize = dwMax != Layouting::Item::hardcodedMaximumSize;
778 if (hasMaxSize)
779 size = dw->maximumSize().expandedTo(size);
780 }
781
782 // Interpret 0 max-size as not having one too.
783 if (size.width() == 0)
784 size.setWidth(Layouting::Item::hardcodedMaximumSize.width());
785 if (size.height() == 0)
786 size.setHeight(Layouting::Item::hardcodedMaximumSize.height());
787
788 return size;
789}
790
791QRect Frame::dragRect() const
792{
793 QRect rect;
794 if (m_titleBar->isVisible()) {
795 rect = m_titleBar->rect();
796 rect.moveTopLeft(m_titleBar->mapToGlobal(QPoint(0, 0)));
797 }
798
799 return rect;
800}
801
802MainWindowBase *Frame::mainWindow() const
803{
804 return m_layoutWidget ? m_layoutWidget->mainWindow() : nullptr;
805}
806
807TabWidget *Frame::tabWidget() const
808{
809 return m_tabWidget;
810}
811
813bool Frame::allDockWidgetsHave(DockWidgetBase::Option option) const
814{
815 const DockWidgetBase::List docks = dockWidgets();
816 return std::all_of(docks.cbegin(), docks.cend(), [option](DockWidgetBase *dw) {
817 return dw->options() & option;
818 });
819}
820
822bool Frame::anyDockWidgetsHas(DockWidgetBase::Option option) const
823{
824 const DockWidgetBase::List docks = dockWidgets();
825 return std::any_of(docks.cbegin(), docks.cend(), [option](DockWidgetBase *dw) {
826 return dw->options() & option;
827 });
828}
829
830bool Frame::allDockWidgetsHave(DockWidgetBase::LayoutSaverOption option) const
831{
832 const DockWidgetBase::List docks = dockWidgets();
833 return std::all_of(docks.cbegin(), docks.cend(), [option](DockWidgetBase *dw) {
834 return dw->layoutSaverOptions() & option;
835 });
836}
837
838bool Frame::anyDockWidgetsHas(DockWidgetBase::LayoutSaverOption option) const
839{
840 const DockWidgetBase::List docks = dockWidgets();
841 return std::any_of(docks.cbegin(), docks.cend(), [option](DockWidgetBase *dw) {
842 return dw->layoutSaverOptions() & option;
843 });
844}
845
846void Frame::setAllowedResizeSides(CursorPositions sides)
847{
848 if (sides) {
849 delete m_resizeHandler;
850 m_resizeHandler = new WidgetResizeHandler(WidgetResizeHandler::EventFilterMode::Global, WidgetResizeHandler::WindowMode::MDI, this);
851 m_resizeHandler->setAllowedResizeSides(sides);
852 } else {
853 delete m_resizeHandler;
854 m_resizeHandler = nullptr;
855 }
856}
857
858bool Frame::isMDI() const
859{
860 return mdiLayoutWidget() != nullptr;
861}
862
863bool Frame::isMDIWrapper() const
864{
865 return mdiDropAreaWrapper() != nullptr;
866}
867
868Frame *Frame::mdiFrame() const
869{
870 if (auto dwWrapper = mdiDockWidgetWrapper()) {
871 return dwWrapper->d->frame();
872 }
873
874 return nullptr;
875}
876
877DockWidgetBase *Frame::mdiDockWidgetWrapper() const
878{
879 if (auto dropArea = mdiDropAreaWrapper()) {
880 return qobject_cast<DockWidgetBase *>(dropArea->QWidgetAdapter::parent());
881 }
882
883 return nullptr;
884}
885
886DropArea *Frame::mdiDropAreaWrapper() const
887{
888 auto dropArea = qobject_cast<DropArea *>(QWidgetAdapter::parent());
889 if (dropArea && dropArea->isMDIWrapper())
890 return dropArea;
891 return nullptr;
892}
893
894MDILayoutWidget *Frame::mdiLayoutWidget() const
895{
896 return qobject_cast<MDILayoutWidget *>(m_layoutWidget);
897}
898
899bool Frame::hasNestedMDIDockWidgets() const
900{
901 if (!isMDI() || dockWidgetCount() == 0)
902 return false;
903
904 if (dockWidgetCount() != 1) {
905 qWarning() << Q_FUNC_INFO << "Expected a single dock widget wrapper as frame child";
906 return false;
907 }
908
909 return dockWidgetAt(0)->d->isMDIWrapper();
910}
911
912int Frame::userType() const
913{
914 return m_userType;
915}
916
917WidgetResizeHandler *Frame::resizeHandler() const
918{
919 return m_resizeHandler;
920}
921
922FloatingWindowFlags Frame::requestedFloatingWindowFlags() const
923{
924 const auto dockwidgets = this->dockWidgets();
925 if (!dockwidgets.isEmpty())
926 return dockwidgets.first()->floatingWindowFlags();
927
928 return FloatingWindowFlag::FromGlobalConfig;
929}
Application-wide config to tune certain behaviours of the framework.
static int s_dbg_numFrames
Definition Frame.cpp:42
A factory class for allowing the user to customize some internal widgets.
Singleton to allow to choose certain behaviours of the framework.
Definition Config.h:75
FrameworkWidgetFactory * frameworkWidgetFactory() const
getter for the framework widget factory
Definition Config.cpp:145
static Config & self()
returns the singleton Config instance
Definition Config.cpp:84
@ Flag_HideTitleBarWhenTabsVisible
Hides the title bar if there's tabs visible. The empty space in the tab bar becomes draggable.
Definition Config.h:92
@ Flag_AlwaysShowTabs
Always show tabs, even if there's only one,.
Definition Config.h:93
The DockWidget base-class. DockWidget and DockWidgetBase are only split in two so we can share some c...
KDDockWidgets::DockWidgetBase::Options options
TitleBar * titleBar() const
Returns this dock widget's title bar.
LayoutSaverOption
Options which will affect LayoutSaver save/restore.
bool isPersistentCentralDockWidget() const
Returns whether this dock widget is the main window persistent central widget This only applies when ...
Option
DockWidget options to pass at construction time.
@ Option_NotDockable
The DockWidget can't be docked, it's always floating.
@ Option_NotClosable
The DockWidget can't be closed on the [x], only programmatically.
void titleChanged(const QString &title)
signal emitted when the title changed
void iconChanged()
signal emitted when the icon changed
Allows to implement a similar functionality to QtQuick's FocusScope item, in QtWidgets.
Definition FocusScope.h:28
virtual FloatingWindow * createFloatingWindow(MainWindowBase *parent=nullptr, FloatingWindowFlags=FloatingWindowFlag::FromGlobalConfig) const =0
Called internally by the framework to create a FloatingWindow Override to provide your own FloatingWi...
virtual Frame * createFrame(QWidgetOrQuick *parent=nullptr, FrameOptions options=FrameOption_None) const =0
Called internally by the framework to create a Frame class Override to provide your own Frame sub-cla...
LayoutGuestWidget is the type that Item will host.
The MainWindow base-class. MainWindow and MainWindowBase are only split in two so we can share some c...
@ SuggestedGeometryHint_GeometryIsFromDocked
static FrameOptions actualOptions(FrameOptions options)
Definition Frame.cpp:47
static TabWidgetOptions tabWidgetOptions(FrameOptions options)
Definition Frame.cpp:55
void accept()
bool isAccepted() const const
QEvent::Type type() const const
void moveTopLeft(const QPoint &position)
int height() const const
void setHeight(int height)
void setWidth(int width)
int width() const const
QVector::const_iterator cbegin() const const
QVector::const_iterator cend() const const
void reserve(int size)
Struct describing the preferred dock widget size and visibility when adding it to a layout.

© 2019-2023 Klarälvdalens Datakonsult AB (KDAB)
"The Qt, C++ and OpenGL Experts"
https://www.kdab.com/
KDDockWidgets
Advanced Dock Widget Framework for Qt
https://www.kdab.com/development-resources/qt-tools/kddockwidgets/
Generated on Wed Nov 1 2023 00:02:31 for KDDockWidgets API Documentation by doxygen 1.9.8