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