Don't create duplicate central frame with restoring
When using MainWindowOption_HasCentralFrame we have a persistent central frame which is never destroyed. When restoring a layout we shouldn't create it, as it exists already.
This commit is contained in:
@@ -652,7 +652,7 @@ QVariantMap LayoutSaver::Frame::toVariantMap() const
|
||||
map.insert(QStringLiteral("geometry"), Layouting::rectToMap(geometry));
|
||||
map.insert(QStringLiteral("options"), options);
|
||||
map.insert(QStringLiteral("currentTabIndex"), currentTabIndex);
|
||||
|
||||
map.insert(QStringLiteral("mainWindowUniqueName"), mainWindowUniqueName);
|
||||
map.insert(QStringLiteral("dockWidgets"), dockWidgetNames(dockWidgets));
|
||||
|
||||
return map;
|
||||
@@ -669,6 +669,7 @@ void LayoutSaver::Frame::fromVariantMap(const QVariantMap &map)
|
||||
id = map.value(QStringLiteral("id")).toString();
|
||||
isNull = map.value(QStringLiteral("isNull")).toBool();
|
||||
objectName = map.value(QStringLiteral("objectName")).toString();
|
||||
mainWindowUniqueName = map.value(QStringLiteral("mainWindowUniqueName")).toString();
|
||||
geometry = Layouting::mapToRect(map.value(QStringLiteral("geometry")).toMap());
|
||||
options = static_cast<QFlags<FrameOption>::Int>(map.value(QStringLiteral("options")).toUInt());
|
||||
currentTabIndex = map.value(QStringLiteral("currentTabIndex")).toInt();
|
||||
|
||||
@@ -28,6 +28,7 @@ public:
|
||||
|
||||
private:
|
||||
friend class MainWindowBase;
|
||||
friend class Frame;
|
||||
Frame *const m_centralFrame = nullptr;
|
||||
};
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "Utils_p.h"
|
||||
#include "WidgetResizeHandler_p.h"
|
||||
#include "MDILayoutWidget_p.h"
|
||||
#include "DropAreaWithCentralFrame_p.h"
|
||||
|
||||
#include <QCloseEvent>
|
||||
#include <QTimer>
|
||||
@@ -147,7 +148,8 @@ void Frame::insertWidget(DockWidgetBase *dockWidget, int index, InitialOption ad
|
||||
{
|
||||
Q_ASSERT(dockWidget);
|
||||
if (containsDockWidget(dockWidget)) {
|
||||
qWarning() << "Frame::addWidget dockWidget already exists. this=" << this << "; dockWidget=" << dockWidget;
|
||||
if (!dockWidget->isPersistentCentralDockWidget())
|
||||
qWarning() << "Frame::addWidget dockWidget already exists. this=" << this << "; dockWidget=" << dockWidget;
|
||||
return;
|
||||
}
|
||||
if (m_layoutItem)
|
||||
@@ -652,7 +654,37 @@ Frame *Frame::deserialize(const LayoutSaver::Frame &f)
|
||||
if (!f.isValid())
|
||||
return nullptr;
|
||||
|
||||
auto frame = Config::self().frameworkWidgetFactory()->createFrame(/*parent=*/nullptr, FrameOptions(f.options));
|
||||
const FrameOptions options = FrameOptions(f.options);
|
||||
Frame *frame = nullptr;
|
||||
const bool isPersistentCentralFrame = options & FrameOption::FrameOption_IsCentralFrame;
|
||||
auto widgetFactory = Config::self().frameworkWidgetFactory();
|
||||
|
||||
if (isPersistentCentralFrame) {
|
||||
// Don't create a new Frame if we're restoring the Persistent Central frame (the one created
|
||||
// by MainWindowOption_HasCentralFrame). It already exists.
|
||||
|
||||
if (f.mainWindowUniqueName.isEmpty()) {
|
||||
// Can happen with older serialization formats
|
||||
qWarning() << Q_FUNC_INFO << "Frame is the persistent central frame but doesn't have"
|
||||
<< "an associated window name";
|
||||
} else {
|
||||
if (MainWindowBase *mw = DockRegistry::self()->mainWindowByName(f.mainWindowUniqueName)) {
|
||||
frame = mw->dropArea()->m_centralFrame;
|
||||
if (!frame) {
|
||||
// Doesn't happen...
|
||||
qWarning() << "Main window" << f.mainWindowUniqueName << "doesn't have central frame";
|
||||
}
|
||||
} else {
|
||||
// Doesn't happen...
|
||||
qWarning() << Q_FUNC_INFO << "Couldn't find main window"
|
||||
<< f.mainWindowUniqueName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!frame)
|
||||
frame = widgetFactory->createFrame(/*parent=*/nullptr, options);
|
||||
|
||||
frame->setObjectName(f.objectName);
|
||||
|
||||
for (const auto &savedDock : qAsConst(f.dockWidgets)) {
|
||||
@@ -680,6 +712,9 @@ LayoutSaver::Frame Frame::serialize() const
|
||||
frame.currentTabIndex = currentTabIndex();
|
||||
frame.id = id(); // for coorelation purposes
|
||||
|
||||
if (MainWindowBase *mw = mainWindow())
|
||||
frame.mainWindowUniqueName = mw->uniqueName();
|
||||
|
||||
for (DockWidgetBase *dock : docks)
|
||||
frame.dockWidgets.push_back(dock->d->serialize());
|
||||
|
||||
|
||||
@@ -212,6 +212,10 @@ struct LayoutSaver::Frame
|
||||
int currentTabIndex;
|
||||
QString id; // for coorelation purposes
|
||||
|
||||
/// Might be empty if not in a main window. Used so we don't create a frame when restoring
|
||||
/// the persistent central frame, that's never deleted when restoring
|
||||
QString mainWindowUniqueName;
|
||||
|
||||
LayoutSaver::DockWidget::List dockWidgets;
|
||||
};
|
||||
|
||||
|
||||
@@ -3746,6 +3746,23 @@ void TestDocks::tst_restoreSideBySide()
|
||||
}
|
||||
}
|
||||
|
||||
void TestDocks::tst_restoreWithCentralFrameWithTabs()
|
||||
{
|
||||
auto m = createMainWindow(QSize(500, 500), MainWindowOption_HasCentralFrame, "tst_restoreTwice");
|
||||
auto dock1 = createDockWidget("1", new QPushButton("1"));
|
||||
auto dock2 = createDockWidget("2", new QPushButton("2"));
|
||||
m->addDockWidgetAsTab(dock1);
|
||||
m->addDockWidgetAsTab(dock2);
|
||||
|
||||
QCOMPARE(DockRegistry::self()->frames().size(), 1);
|
||||
|
||||
LayoutSaver saver;
|
||||
const QByteArray saved = saver.serializeLayout();
|
||||
QVERIFY(saver.restoreLayout(saved));
|
||||
|
||||
QCOMPARE(DockRegistry::self()->frames().size(), 1);
|
||||
}
|
||||
|
||||
void TestDocks::tst_restoreWithPlaceholder()
|
||||
{
|
||||
// Float dock1, save and restore, then unfloat and see if dock2 goes back to where it was
|
||||
|
||||
@@ -106,6 +106,7 @@ private Q_SLOTS:
|
||||
void tst_restoreNestedAndTabbed();
|
||||
void tst_restoreCrash();
|
||||
void tst_restoreSideBySide();
|
||||
void tst_restoreWithCentralFrameWithTabs();
|
||||
void tst_restoreWithPlaceholder();
|
||||
void tst_restoreWithAffinity();
|
||||
void tst_marginsAfterRestore();
|
||||
|
||||
Reference in New Issue
Block a user