Session: Minimize direct use of reader when loading sessions

Instead of directly reading things like the project list from the
reader, add a map of "session values" in the session and read these from
the reader once, then use the session to access these values while
loading the details of the session. This is in preparation of separating
the session loading from projectexplorer.

This is similar to Session::(set)Value. We cannot use the same
(set)Value methods directly though, because of differences in the
handling of these values during implict and explicit default session
loading.

Change-Id: I9a4f38a9f958734d20d6e6eb7253f9e44ba1285e
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
Eike Ziller
2023-05-15 15:19:01 +02:00
parent c7bf77ae72
commit b512f414bd
6 changed files with 93 additions and 53 deletions

View File

@@ -2400,7 +2400,7 @@ ProjectExplorerPlugin::OpenProjectResult ProjectExplorerPlugin::openProjects(con
Utils::equal(&Project::projectFilePath, filePath)); Utils::equal(&Project::projectFilePath, filePath));
if (found) { if (found) {
alreadyOpen.append(found); alreadyOpen.append(found);
ProjectManager::reportProjectLoadingProgress(); SessionManager::sessionLoadingProgress();
continue; continue;
} }
@@ -2429,7 +2429,7 @@ ProjectExplorerPlugin::OpenProjectResult ProjectExplorerPlugin::openProjects(con
.arg(mt.name())); .arg(mt.name()));
} }
if (filePaths.size() > 1) if (filePaths.size() > 1)
ProjectManager::reportProjectLoadingProgress(); SessionManager::sessionLoadingProgress();
} }
dd->updateActions(); dd->updateActions();

View File

@@ -54,8 +54,8 @@ const char DEFAULT_SESSION[] = "default";
class ProjectManagerPrivate class ProjectManagerPrivate
{ {
public: public:
void restoreDependencies(const PersistentSettingsReader &reader); void restoreDependencies();
void restoreStartupProject(const PersistentSettingsReader &reader); void restoreStartupProject();
void restoreProjects(const FilePaths &fileList); void restoreProjects(const FilePaths &fileList);
void askUserAboutFailedProjects(); void askUserAboutFailedProjects();
@@ -619,9 +619,9 @@ void ProjectManager::removeProjects(const QList<Project *> &remove)
qDeleteAll(remove); qDeleteAll(remove);
} }
void ProjectManagerPrivate::restoreDependencies(const PersistentSettingsReader &reader) void ProjectManagerPrivate::restoreDependencies()
{ {
QMap<QString, QVariant> depMap = reader.restoreValue(QLatin1String("ProjectDependencies")).toMap(); QMap<QString, QVariant> depMap = SessionManager::sessionValue("ProjectDependencies").toMap();
auto i = depMap.constBegin(); auto i = depMap.constBegin();
while (i != depMap.constEnd()) { while (i != depMap.constEnd()) {
const QString &key = i.key(); const QString &key = i.key();
@@ -655,9 +655,10 @@ void ProjectManagerPrivate::askUserAboutFailedProjects()
} }
} }
void ProjectManagerPrivate::restoreStartupProject(const PersistentSettingsReader &reader) void ProjectManagerPrivate::restoreStartupProject()
{ {
const FilePath startupProject = FilePath::fromSettings(reader.restoreValue("StartupProject")); const FilePath startupProject = FilePath::fromSettings(
SessionManager::sessionValue("StartupProject"));
if (!startupProject.isEmpty()) { if (!startupProject.isEmpty()) {
for (Project *pro : std::as_const(m_projects)) { for (Project *pro : std::as_const(m_projects)) {
if (pro->projectFilePath() == startupProject) { if (pro->projectFilePath() == startupProject) {
@@ -732,7 +733,6 @@ bool ProjectManager::loadSession(const QString &session, bool initial)
if (!loadImplicitDefault && !SessionManager::sessions().contains(session)) if (!loadImplicitDefault && !SessionManager::sessions().contains(session))
return false; return false;
FilePaths fileList;
// Try loading the file // Try loading the file
FilePath fileName = SessionManager::sessionNameToFileName(loadImplicitDefault ? DEFAULT_SESSION : session); FilePath fileName = SessionManager::sessionNameToFileName(loadImplicitDefault ? DEFAULT_SESSION : session);
PersistentSettingsReader reader; PersistentSettingsReader reader;
@@ -749,8 +749,6 @@ bool ProjectManager::loadSession(const QString &session, bool initial)
emit SessionManager::instance()->sessionLoaded(DEFAULT_SESSION); emit SessionManager::instance()->sessionLoaded(DEFAULT_SESSION);
return true; return true;
} }
fileList = FileUtils::toFilePathList(reader.restoreValue("ProjectList").toStringList());
} else if (loadImplicitDefault) { } else if (loadImplicitDefault) {
return true; return true;
} }
@@ -771,20 +769,11 @@ bool ProjectManager::loadSession(const QString &session, bool initial)
return false; return false;
} }
// find a list of projects to close later
const QList<Project *> projectsToRemove = Utils::filtered(projects(), [&fileList](Project *p) {
return !fileList.contains(p->projectFilePath());
});
const QList<Project *> openProjects = projects();
const FilePaths projectPathsToLoad = Utils::filtered(fileList, [&openProjects](const FilePath &path) {
return !Utils::contains(openProjects, [&path](Project *p) {
return p->projectFilePath() == path;
});
});
d->m_failedProjects.clear(); d->m_failedProjects.clear();
d->m_depMap.clear(); d->m_depMap.clear();
if (!switchFromImplicitToExplicitDefault) if (!switchFromImplicitToExplicitDefault)
sb_d->m_values.clear(); sb_d->m_values.clear();
sb_d->m_sessionValues.clear();
d->m_casadeSetActive = false; d->m_casadeSetActive = false;
sb_d->m_sessionName = session; sb_d->m_sessionName = session;
@@ -798,38 +787,53 @@ bool ProjectManager::loadSession(const QString &session, bool initial)
ProgressManager::addTask(sb_d->m_future.future(), Tr::tr("Loading Session"), ProgressManager::addTask(sb_d->m_future.future(), Tr::tr("Loading Session"),
"ProjectExplorer.SessionFile.Load"); "ProjectExplorer.SessionFile.Load");
sb_d->m_future.setProgressRange(0, 1); sb_d->m_future.setProgressRange(0, 1 /*initialization*/ + 1 /*editors*/);
sb_d->m_future.setProgressValue(0); sb_d->m_future.setProgressValue(0);
if (!switchFromImplicitToExplicitDefault) if (!switchFromImplicitToExplicitDefault)
sb_d->restoreValues(reader); sb_d->restoreValues(reader);
emit SessionManager::instance()->aboutToLoadSession(session); sb_d->restoreSessionValues(reader);
// retrieve all values before the following code could change them again // retrieve all values before the following code could change them again
Id modeId = Id::fromSetting(SessionManager::value(QLatin1String("ActiveMode"))); Id modeId = Id::fromSetting(SessionManager::value(QLatin1String("ActiveMode")));
if (!modeId.isValid()) if (!modeId.isValid())
modeId = Id(Core::Constants::MODE_EDIT); modeId = Id(Core::Constants::MODE_EDIT);
QColor c = QColor(reader.restoreValue(QLatin1String("Color")).toString()); QColor c = QColor(SessionManager::sessionValue("Color").toString());
if (c.isValid()) if (c.isValid())
StyleHelper::setBaseColor(c); StyleHelper::setBaseColor(c);
sb_d->m_future.setProgressRange(0, projectPathsToLoad.count() + 1/*initialization above*/ + 1/*editors*/); SessionManager::sessionLoadingProgress();
sb_d->m_future.setProgressValue(1);
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); sb_d->restoreEditors();
// let other code restore the session
emit SessionManager::instance()->aboutToLoadSession(session);
// find a list of projects to close later
const FilePaths fileList = FileUtils::toFilePathList(
SessionManager::sessionValue("ProjectList").toStringList());
const QList<Project *> projectsToRemove
= Utils::filtered(projects(), [&fileList](Project *p) {
return !fileList.contains(p->projectFilePath());
});
const QList<Project *> openProjects = projects();
const FilePaths projectPathsToLoad
= Utils::filtered(fileList, [&openProjects](const FilePath &path) {
return !Utils::contains(openProjects, [&path](Project *p) {
return p->projectFilePath() == path;
});
});
SessionManager::addSessionLoadingSteps(projectPathsToLoad.count());
d->restoreProjects(projectPathsToLoad); d->restoreProjects(projectPathsToLoad);
sb_d->sessionLoadingProgress(); SessionManager::sessionLoadingProgress();
d->restoreDependencies(reader); d->restoreDependencies();
d->restoreStartupProject(reader); d->restoreStartupProject();
removeProjects(projectsToRemove); // only remove old projects now that the startup project is set! removeProjects(projectsToRemove); // only remove old projects now that the startup project is set!
sb_d->restoreEditors(reader);
sb_d->m_future.reportFinished();
sb_d->m_future = QFutureInterface<void>();
// Fall back to Project mode if the startup project is unconfigured and // Fall back to Project mode if the startup project is unconfigured and
// use the mode saved in the session otherwise // use the mode saved in the session otherwise
if (d->m_startupProject && d->m_startupProject->needsConfiguration()) if (d->m_startupProject && d->m_startupProject->needsConfiguration())
@@ -843,9 +847,12 @@ bool ProjectManager::loadSession(const QString &session, bool initial)
ModeManager::setFocusToCurrentMode(); ModeManager::setFocusToCurrentMode();
} }
d->m_casadeSetActive = reader.restoreValue(QLatin1String("CascadeSetActive"), false).toBool(); d->m_casadeSetActive = SessionManager::sessionValue("CascadeSetActive", false).toBool();
sb_d->m_lastActiveTimes.insert(session, QDateTime::currentDateTime()); sb_d->m_lastActiveTimes.insert(session, QDateTime::currentDateTime());
sb_d->m_future.reportFinished();
sb_d->m_future = QFutureInterface<void>();
emit SessionManager::instance()->sessionLoaded(session); emit SessionManager::instance()->sessionLoaded(session);
// Starts a event loop, better do that at the very end // Starts a event loop, better do that at the very end
@@ -854,11 +861,6 @@ bool ProjectManager::loadSession(const QString &session, bool initial)
return true; return true;
} }
void ProjectManager::reportProjectLoadingProgress()
{
sb_d->sessionLoadingProgress();
}
FilePaths ProjectManager::projectsForSessionName(const QString &session) FilePaths ProjectManager::projectsForSessionName(const QString &session)
{ {
const FilePath fileName = SessionManager::sessionNameToFileName(session); const FilePath fileName = SessionManager::sessionNameToFileName(session);

View File

@@ -82,8 +82,6 @@ public:
static Utils::FilePaths projectsForSessionName(const QString &session); static Utils::FilePaths projectsForSessionName(const QString &session);
static void reportProjectLoadingProgress();
static bool loadSession(const QString &session, bool initial = false); static bool loadSession(const QString &session, bool initial = false);
signals: signals:

View File

@@ -141,6 +141,17 @@ QVariant SessionManager::value(const QString &name)
return (it == sb_d->m_values.constEnd()) ? QVariant() : *it; return (it == sb_d->m_values.constEnd()) ? QVariant() : *it;
} }
void SessionManager::setSessionValue(const QString &name, const QVariant &value)
{
sb_d->m_sessionValues.insert(name, value);
}
QVariant SessionManager::sessionValue(const QString &name, const QVariant &defaultValue)
{
auto it = sb_d->m_sessionValues.constFind(name);
return (it == sb_d->m_sessionValues.constEnd()) ? defaultValue : *it;
}
QString SessionManager::activeSession() QString SessionManager::activeSession()
{ {
return sb_d->m_sessionName; return sb_d->m_sessionName;
@@ -382,12 +393,24 @@ void SessionManagerPrivate::restoreValues(const PersistentSettingsReader &reader
} }
} }
void SessionManagerPrivate::restoreEditors(const PersistentSettingsReader &reader) void SessionManagerPrivate::restoreSessionValues(const PersistentSettingsReader &reader)
{ {
const QVariant editorsettings = reader.restoreValue(QLatin1String("EditorSettings")); const QVariantMap values = reader.restoreValues();
// restore toplevel items that are not restored by restoreValues
const auto end = values.constEnd();
for (auto it = values.constBegin(); it != end; ++it) {
if (it.key() == "valueKeys" || it.key().startsWith("value-"))
continue;
m_sessionValues.insert(it.key(), it.value());
}
}
void SessionManagerPrivate::restoreEditors()
{
const QVariant editorsettings = m_sessionValues.value("EditorSettings");
if (editorsettings.isValid()) { if (editorsettings.isValid()) {
EditorManager::restoreState(QByteArray::fromBase64(editorsettings.toByteArray())); EditorManager::restoreState(QByteArray::fromBase64(editorsettings.toByteArray()));
sessionLoadingProgress(); SessionManager::sessionLoadingProgress();
} }
} }
@@ -412,10 +435,15 @@ void SessionManager::markSessionFileDirty()
sb_d->m_virginSession = false; sb_d->m_virginSession = false;
} }
void SessionManagerPrivate::sessionLoadingProgress() void SessionManager::sessionLoadingProgress()
{ {
m_future.setProgressValue(m_future.progressValue() + 1); sb_d->m_future.setProgressValue(sb_d->m_future.progressValue() + 1);
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
} }
void SessionManager::addSessionLoadingSteps(int steps)
{
sb_d->m_future.setProgressRange(0, sb_d->m_future.progressMaximum() + steps);
}
} // namespace ProjectExplorer } // namespace ProjectExplorer

View File

@@ -47,15 +47,26 @@ public:
static bool isDefaultSession(const QString &session); static bool isDefaultSession(const QString &session);
// Let other plugins store persistent values within the session file // Let other plugins store persistent values within the session file
// These are settings that are also saved and loaded at startup, and are taken over
// to the default session when switching from implicit to explicit default session
static void setValue(const QString &name, const QVariant &value); static void setValue(const QString &name, const QVariant &value);
static QVariant value(const QString &name); static QVariant value(const QString &name);
// These are settings that are specific to a session and are not loaded
// at startup and also not taken over to the default session when switching from implicit
static void setSessionValue(const QString &name, const QVariant &value);
static QVariant sessionValue(const QString &name, const QVariant &defaultValue = {});
static bool loadingSession(); static bool loadingSession();
static void markSessionFileDirty(); static void markSessionFileDirty();
static void sessionLoadingProgress();
static void addSessionLoadingSteps(int steps);
signals: signals:
void startupSessionRestored(); void startupSessionRestored();
void aboutToUnloadSession(QString sessionName); void aboutToUnloadSession(QString sessionName);
// Sent during session loading, after the values of the session are available via value() and
// sessionValue. Use to restore values from the new session
void aboutToLoadSession(QString sessionName); void aboutToLoadSession(QString sessionName);
void sessionLoaded(QString sessionName); void sessionLoaded(QString sessionName);
void aboutToSaveSession(); void aboutToSaveSession();

View File

@@ -15,8 +15,8 @@ public:
void restoreStartupSession(); void restoreStartupSession();
void restoreValues(const PersistentSettingsReader &reader); void restoreValues(const PersistentSettingsReader &reader);
void restoreEditors(const PersistentSettingsReader &reader); void restoreSessionValues(const PersistentSettingsReader &reader);
void sessionLoadingProgress(); void restoreEditors();
bool isStartupSessionRestored(); bool isStartupSessionRestored();
void saveSettings(); void saveSettings();
@@ -38,6 +38,7 @@ public:
QHash<QString, QDateTime> m_lastActiveTimes; QHash<QString, QDateTime> m_lastActiveTimes;
QMap<QString, QVariant> m_values; QMap<QString, QVariant> m_values;
QMap<QString, QVariant> m_sessionValues;
QFutureInterface<void> m_future; QFutureInterface<void> m_future;
PersistentSettingsWriter *m_writer = nullptr; PersistentSettingsWriter *m_writer = nullptr;
}; };