nested mdi: Get rid of unneeded drop area mdi wrapper when floating
When floating, the FloatingWindow has its own DropArea for nesting. We delete the redundant level of wrappers when floating.
This commit is contained in:
@@ -551,10 +551,17 @@ MDILayoutWidget *DockWidgetBase::Private::mdiLayout() const
|
||||
|
||||
bool DockWidgetBase::Private::isMDIWrapper() const
|
||||
{
|
||||
if (auto dropAreaGuest = qobject_cast<DropArea *>(q->widget()))
|
||||
return dropAreaGuest->isMDIWrapper();
|
||||
return mdiDropAreaWrapper() != nullptr;
|
||||
}
|
||||
|
||||
return false;
|
||||
DropArea *DockWidgetBase::Private::mdiDropAreaWrapper() const
|
||||
{
|
||||
if (auto dropAreaGuest = qobject_cast<DropArea *>(q->widget())) {
|
||||
if (dropAreaGuest->isMDIWrapper())
|
||||
return dropAreaGuest;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DockWidgetBase::Private *DockWidgetBase::dptr() const
|
||||
|
||||
@@ -140,6 +140,9 @@ public:
|
||||
/// This is only used by the DockWidget::Option_MDINestable feature
|
||||
bool isMDIWrapper() const;
|
||||
|
||||
/// @brief If this dock widget is an MDI wrapper (isMDIWrapper()), then returns the wrapper drop area
|
||||
DropArea *mdiDropAreaWrapper() const;
|
||||
|
||||
const QString name;
|
||||
QStringList affinities;
|
||||
QString title;
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "FrameworkWidgetFactory.h"
|
||||
#include "DragController_p.h"
|
||||
#include "LayoutSaver_p.h"
|
||||
#include "DockWidgetBase_p.h"
|
||||
|
||||
#include <QCloseEvent>
|
||||
#include <QScopedValueRollback>
|
||||
@@ -146,10 +147,26 @@ FloatingWindow::FloatingWindow(Frame *frame, QRect suggestedGeometry, MainWindow
|
||||
{
|
||||
QScopedValueRollback<bool> guard(m_disableSetVisible, true);
|
||||
|
||||
// Adding a widget will trigger onFrameCountChanged, which triggers a setVisible(true).
|
||||
// The problem with setVisible(true) will forget about or requested geometry and place the window at 0,0
|
||||
// So disable the setVisible(true) call while in the ctor.
|
||||
m_dropArea->addWidget(frame, KDDockWidgets::Location_OnTop, {});
|
||||
if (frame->hasNestedMDIDockWidgets()) {
|
||||
// When using DockWidget::MDINestable, the docked MDI widget is wrapped by a drop area so we can drop things into it.
|
||||
// When floating it, we can delete that helper drop area, as FloatingWindow already has one
|
||||
|
||||
if (frame->dockWidgetCount() == 0) {
|
||||
// doesn't happen
|
||||
qWarning() << Q_FUNC_INFO << "Unexpected empty frame";
|
||||
return;
|
||||
}
|
||||
|
||||
auto dwMDIWrapper = frame->dockWidgetAt(0);
|
||||
auto dropAreaMDIWrapper = dwMDIWrapper->d->mdiDropAreaWrapper();
|
||||
m_dropArea->addMultiSplitter(dropAreaMDIWrapper, Location_OnTop);
|
||||
delete dwMDIWrapper;
|
||||
} else {
|
||||
// Adding a widget will trigger onFrameCountChanged, which triggers a setVisible(true).
|
||||
// The problem with setVisible(true) will forget about or requested geometry and place the window at 0,0
|
||||
// So disable the setVisible(true) call while in the ctor.
|
||||
m_dropArea->addWidget(frame, KDDockWidgets::Location_OnTop, {});
|
||||
}
|
||||
}
|
||||
|
||||
FloatingWindow::~FloatingWindow()
|
||||
|
||||
@@ -889,6 +889,19 @@ MDILayoutWidget *Frame::mdiLayoutWidget() const
|
||||
return qobject_cast<MDILayoutWidget *>(m_layoutWidget);
|
||||
}
|
||||
|
||||
bool Frame::hasNestedMDIDockWidgets() const
|
||||
{
|
||||
if (!isMDI() || dockWidgetCount() == 0)
|
||||
return false;
|
||||
|
||||
if (dockWidgetCount() != 1) {
|
||||
qWarning() << Q_FUNC_INFO << "Expected a single dock widget wrapper as frame child";
|
||||
return false;
|
||||
}
|
||||
|
||||
return dockWidgetAt(0)->d->isMDIWrapper();
|
||||
}
|
||||
|
||||
int Frame::userType() const
|
||||
{
|
||||
return m_userType;
|
||||
|
||||
@@ -302,6 +302,10 @@ public:
|
||||
/// @brief Returns the MDI layout. Or nullptr if this frame isn't in a MDI layout
|
||||
MDILayoutWidget *mdiLayoutWidget() const;
|
||||
|
||||
/// @brief If this frame is a MDI frame (isMDI() == true), returns whether it contains nested dock widgets (DockWidget::Option_MDINestable)
|
||||
/// @sa isMDI()
|
||||
bool hasNestedMDIDockWidgets() const;
|
||||
|
||||
/// @brief See DockWidgetBase::userType()
|
||||
int userType() const;
|
||||
|
||||
|
||||
@@ -5153,7 +5153,32 @@ void TestDocks::tst_mdi_mixed_with_docking2()
|
||||
QVERIFY(!mdiWidget3->isOpen());
|
||||
QVERIFY(dropArea1.isNull());
|
||||
|
||||
// QTest::qWait(10000);
|
||||
// Reopen everything again:
|
||||
|
||||
mdiArea->addDockWidget(mdiWidget1, QPoint(10, 10));
|
||||
mdiArea->addDockWidget(mdiWidget2, QPoint(50, 50));
|
||||
frame1 = mdiWidget1->d->frame();
|
||||
mdiFrame1 = frame1->mdiFrame();
|
||||
dropArea1 = frame1->mdiDropAreaWrapper();
|
||||
dropArea1->addDockWidget(mdiWidget3, Location_OnLeft, nullptr);
|
||||
|
||||
// Test floating:
|
||||
frame2 = mdiWidget2->d->frame();
|
||||
QPointer<DockWidgetBase> dwWrapper2 = frame2->mdiDockWidgetWrapper();
|
||||
dropArea2 = frame2->mdiDropAreaWrapper();
|
||||
QVERIFY(mdiWidget2->isVisible());
|
||||
QVERIFY(frame2->isMDIWrapper());
|
||||
QVERIFY(dwWrapper2->d->isMDIWrapper());
|
||||
mdiWidget2->setFloating(true);
|
||||
QVERIFY(mdiWidget2->isFloating());
|
||||
|
||||
QVERIFY(!mdiWidget2->d->frame()->isMDI());
|
||||
QVERIFY(!mdiWidget2->d->frame()->isMDIWrapper());
|
||||
QTest::qWait(500); // remove
|
||||
QVERIFY(dropArea2.isNull());
|
||||
QVERIFY(dwWrapper2.isNull());
|
||||
|
||||
// QTest::qWait(100000);
|
||||
}
|
||||
|
||||
// No need to port to QtQuick
|
||||
|
||||
Reference in New Issue
Block a user