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:
Sergio Martins
2021-09-20 12:02:57 +01:00
parent f6f772edc5
commit 33c5647e57
6 changed files with 62 additions and 3 deletions

View File

@@ -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();

View File

@@ -28,6 +28,7 @@ public:
private:
friend class MainWindowBase;
friend class Frame;
Frame *const m_centralFrame = nullptr;
};

View File

@@ -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());

View File

@@ -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;
};

View File

@@ -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

View File

@@ -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();