LayoutSaver: Support the user's factory func doing remapping
While restoring a layout, we expect all widgets to exist already, but we allow the user to create them delayed, by providing us a factory function. What we're supporting in this commit is the ability of the user's factory function returning a dock widget with an ID different than the one that was requested. We then save that mapping so the rest of the layout restore works with the new ID.
This commit is contained in:
@@ -776,11 +776,18 @@ void DockWidgetBase::onCloseEvent(QCloseEvent *e)
|
|||||||
|
|
||||||
DockWidgetBase *DockWidgetBase::deserialize(const LayoutSaver::DockWidget::Ptr &saved)
|
DockWidgetBase *DockWidgetBase::deserialize(const LayoutSaver::DockWidget::Ptr &saved)
|
||||||
{
|
{
|
||||||
DockWidgetBase *dw = DockRegistry::self()->dockByName(saved->uniqueName);
|
auto dr = DockRegistry::self();
|
||||||
|
DockWidgetBase *dw = dr->dockByName(saved->uniqueName);
|
||||||
if (!dw) {
|
if (!dw) {
|
||||||
|
// DockWidget doesn't exist, ask to create it
|
||||||
if (auto factoryFunc = Config::self().dockWidgetFactoryFunc()) {
|
if (auto factoryFunc = Config::self().dockWidgetFactoryFunc()) {
|
||||||
// DockWidget doesn't exist, ask to create it
|
|
||||||
dw = factoryFunc(saved->uniqueName);
|
dw = factoryFunc(saved->uniqueName);
|
||||||
|
if (dw && dw->uniqueName() != saved->uniqueName) {
|
||||||
|
// Very special case
|
||||||
|
// The user's factory function returned a dock widget with a different ID.
|
||||||
|
// We support it. Save the mapping though.
|
||||||
|
dr->dockWidgetIdRemapping().insert(saved->uniqueName, dw->uniqueName());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -313,7 +313,8 @@ bool LayoutSaver::restoreLayout(const QByteArray &data)
|
|||||||
if (!d->matchesAffinity(dw->affinities))
|
if (!d->matchesAffinity(dw->affinities))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (DockWidgetBase *dockWidget = d->m_dockRegistry->dockByName(dw->uniqueName)) {
|
if (DockWidgetBase *dockWidget =
|
||||||
|
d->m_dockRegistry->dockByName(dw->uniqueName, /*consultRemapping=*/true)) {
|
||||||
dockWidget->d->lastPositions().deserialize(dw->lastPosition);
|
dockWidget->d->lastPositions().deserialize(dw->lastPosition);
|
||||||
} else {
|
} else {
|
||||||
qWarning() << Q_FUNC_INFO << "Couldn't find dock widget" << dw->uniqueName;
|
qWarning() << Q_FUNC_INFO << "Couldn't find dock widget" << dw->uniqueName;
|
||||||
|
|||||||
@@ -256,6 +256,11 @@ Frame *DockRegistry::frameInMDIResize() const
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QHash<QString, QString> &DockRegistry::dockWidgetIdRemapping()
|
||||||
|
{
|
||||||
|
return m_dockWidgetIdRemapping;
|
||||||
|
}
|
||||||
|
|
||||||
MainWindowBase::List DockRegistry::mainWindowsWithAffinity(const QStringList &affinities) const
|
MainWindowBase::List DockRegistry::mainWindowsWithAffinity(const QStringList &affinities) const
|
||||||
{
|
{
|
||||||
MainWindowBase::List result;
|
MainWindowBase::List result;
|
||||||
@@ -383,13 +388,20 @@ bool DockRegistry::containsMainWindow(const QString &uniqueName) const
|
|||||||
return mainWindowByName(uniqueName) != nullptr;
|
return mainWindowByName(uniqueName) != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
DockWidgetBase *DockRegistry::dockByName(const QString &name) const
|
DockWidgetBase *DockRegistry::dockByName(const QString &name, bool consultRemapping) const
|
||||||
{
|
{
|
||||||
for (auto dock : qAsConst(m_dockWidgets)) {
|
for (auto dock : qAsConst(m_dockWidgets)) {
|
||||||
if (dock->uniqueName() == name)
|
if (dock->uniqueName() == name)
|
||||||
return dock;
|
return dock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (consultRemapping) {
|
||||||
|
// Name doesn't exist, let's check if it was remapped during a layout restore.
|
||||||
|
const QString newName = m_dockWidgetIdRemapping.value(name);
|
||||||
|
if (!newName.isEmpty())
|
||||||
|
return dockByName(newName);
|
||||||
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,7 +64,8 @@ public:
|
|||||||
Q_INVOKABLE bool containsDockWidget(const QString &uniqueName) const;
|
Q_INVOKABLE bool containsDockWidget(const QString &uniqueName) const;
|
||||||
Q_INVOKABLE bool containsMainWindow(const QString &uniqueName) const;
|
Q_INVOKABLE bool containsMainWindow(const QString &uniqueName) const;
|
||||||
|
|
||||||
Q_INVOKABLE KDDockWidgets::DockWidgetBase *dockByName(const QString &) const;
|
Q_INVOKABLE KDDockWidgets::DockWidgetBase *dockByName(const QString &,
|
||||||
|
bool consultRemapping = false) const;
|
||||||
Q_INVOKABLE KDDockWidgets::MainWindowBase *mainWindowByName(const QString &) const;
|
Q_INVOKABLE KDDockWidgets::MainWindowBase *mainWindowByName(const QString &) const;
|
||||||
Q_INVOKABLE KDDockWidgets::MainWindowMDI *mdiMainWindowByName(const QString &) const;
|
Q_INVOKABLE KDDockWidgets::MainWindowMDI *mdiMainWindowByName(const QString &) const;
|
||||||
|
|
||||||
@@ -219,6 +220,14 @@ public:
|
|||||||
///@brief Returns the Frame which is being resized in a MDI layout. nullptr if none
|
///@brief Returns the Frame which is being resized in a MDI layout. nullptr if none
|
||||||
Frame *frameInMDIResize() const;
|
Frame *frameInMDIResize() const;
|
||||||
|
|
||||||
|
///@brief Returns the dock widget id remapping, used by LayoutSaver
|
||||||
|
///
|
||||||
|
/// When LayoutSaver is trying to restore dock widget "foo", but it doesn't exist, it will
|
||||||
|
/// attempt to call a user provided factory function. That function can however return a dock
|
||||||
|
/// widget with another ID, such as "bar". When that happens this QHash gets a "foo" : "bar"
|
||||||
|
/// entry
|
||||||
|
QHash<QString, QString> &dockWidgetIdRemapping();
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
/// @brief emitted when a main window or a floating window change screen
|
/// @brief emitted when a main window or a floating window change screen
|
||||||
void windowChangedScreen(QWindow *);
|
void windowChangedScreen(QWindow *);
|
||||||
@@ -243,6 +252,7 @@ private:
|
|||||||
QVector<FloatingWindow*> m_floatingWindows;
|
QVector<FloatingWindow*> m_floatingWindows;
|
||||||
QVector<LayoutWidget *> m_layouts;
|
QVector<LayoutWidget *> m_layouts;
|
||||||
QPointer<DockWidgetBase> m_focusedDockWidget;
|
QPointer<DockWidgetBase> m_focusedDockWidget;
|
||||||
|
QHash<QString, QString> m_dockWidgetIdRemapping;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -134,6 +134,7 @@ private Q_SLOTS:
|
|||||||
void tst_marginsAfterRestore();
|
void tst_marginsAfterRestore();
|
||||||
void tst_restoreWithNewDockWidgets();
|
void tst_restoreWithNewDockWidgets();
|
||||||
void tst_restoreWithDockFactory();
|
void tst_restoreWithDockFactory();
|
||||||
|
void tst_restoreWithDockFactory2();
|
||||||
void tst_lastFloatingPositionIsRestored();
|
void tst_lastFloatingPositionIsRestored();
|
||||||
void tst_restoreSimple();
|
void tst_restoreSimple();
|
||||||
void tst_restoreSimplest();
|
void tst_restoreSimplest();
|
||||||
@@ -4055,6 +4056,31 @@ void TestDocks::tst_restoreWithDockFactory()
|
|||||||
layout->checkSanity();
|
layout->checkSanity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestDocks::tst_restoreWithDockFactory2()
|
||||||
|
{
|
||||||
|
// Teste that the factory function can do id remapping.
|
||||||
|
// For example, if id "foo" is missing, the factory can return a
|
||||||
|
// dock widget with id "bar" if it feels like it
|
||||||
|
|
||||||
|
auto m = createMainWindow(QSize(501, 500), MainWindowOption_None);
|
||||||
|
|
||||||
|
auto dock1 = createDockWidget("dw1", new QPushButton("1"));
|
||||||
|
m->addDockWidget(dock1, Location_OnLeft);
|
||||||
|
dock1->setFloating(true);
|
||||||
|
|
||||||
|
LayoutSaver saver;
|
||||||
|
const QByteArray saved = saver.serializeLayout();
|
||||||
|
delete dock1;
|
||||||
|
|
||||||
|
DockWidgetFactoryFunc func = [] (const QString &) {
|
||||||
|
// A factory func which does id remapping
|
||||||
|
return createDockWidget("dw2", new QPushButton("w"), {}, {}, /*show=*/ false);
|
||||||
|
};
|
||||||
|
|
||||||
|
KDDockWidgets::Config::self().setDockWidgetFactoryFunc(func);
|
||||||
|
saver.restoreLayout(saved);
|
||||||
|
}
|
||||||
|
|
||||||
void TestDocks::tst_addDockWidgetToMainWindow()
|
void TestDocks::tst_addDockWidgetToMainWindow()
|
||||||
{
|
{
|
||||||
EnsureTopLevelsDeleted e;
|
EnsureTopLevelsDeleted e;
|
||||||
|
|||||||
Reference in New Issue
Block a user