ProjectExplorer: Use LRU for sorting sessions in menu

Right now, upon start-up of Qt Creator, entries in the Sessions menu are
sorted in reverse order of the time the corresponding files were last
modified on disk, which often (but not always) corresponds to a "least
recently used" order. This order is unchanged during the lifetime of the
current instance of Qt Creator, and potentially changes again after the
next start.
As this can be confusing to users, we now ensure LRU sorting at all
times.

Task-number: QTCREATORBUG-28202
Change-Id: I758371ac1cb968dd3f2e4278fc5066d1e74397c6
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
Christian Kandeler
2022-10-20 17:53:09 +02:00
parent 07d30b8632
commit d77a7167db
3 changed files with 29 additions and 1 deletions

View File

@@ -145,7 +145,9 @@
#include <QTimer> #include <QTimer>
#include <QVBoxLayout> #include <QVBoxLayout>
#include <algorithm>
#include <functional> #include <functional>
#include <iterator>
#include <memory> #include <memory>
#include <vector> #include <vector>
@@ -4174,7 +4176,10 @@ void ProjectExplorerPluginPrivate::updateSessionMenu()
connect(ag, &QActionGroup::triggered, this, &ProjectExplorerPluginPrivate::setSession); connect(ag, &QActionGroup::triggered, this, &ProjectExplorerPluginPrivate::setSession);
const QString activeSession = SessionManager::activeSession(); const QString activeSession = SessionManager::activeSession();
const QStringList sessions = SessionManager::sessions(); QStringList sessions = SessionManager::sessions();
std::sort(std::next(sessions.begin()), sessions.end(), [](const QString &s1, const QString &s2) {
return SessionManager::lastActiveTime(s1) > SessionManager::lastActiveTime(s2);
});
for (int i = 0; i < sessions.size(); ++i) { for (int i = 0; i < sessions.size(); ++i) {
const QString &session = sessions[i]; const QString &session = sessions[i];

View File

@@ -48,6 +48,7 @@ using namespace ProjectExplorer::Internal;
namespace ProjectExplorer { namespace ProjectExplorer {
const char DEFAULT_SESSION[] = "default"; const char DEFAULT_SESSION[] = "default";
const char LAST_ACTIVE_TIMES_KEY[] = "LastActiveTimes";
/*! /*!
\class ProjectExplorer::SessionManager \class ProjectExplorer::SessionManager
@@ -88,6 +89,7 @@ public:
mutable QStringList m_sessions; mutable QStringList m_sessions;
mutable QHash<QString, QDateTime> m_sessionDateTimes; mutable QHash<QString, QDateTime> m_sessionDateTimes;
QHash<QString, QDateTime> m_lastActiveTimes;
Project *m_startupProject = nullptr; Project *m_startupProject = nullptr;
QList<Project *> m_projects; QList<Project *> m_projects;
@@ -119,6 +121,13 @@ SessionManager::SessionManager(QObject *parent) : QObject(parent)
connect(ModeManager::instance(), &ModeManager::currentModeChanged, connect(ModeManager::instance(), &ModeManager::currentModeChanged,
this, &SessionManager::saveActiveMode); this, &SessionManager::saveActiveMode);
connect(ICore::instance(), &ICore::saveSettingsRequested, this, [] {
QVariantMap times;
for (auto it = d->m_lastActiveTimes.cbegin(); it != d->m_lastActiveTimes.cend(); ++it)
times.insert(it.key(), it.value());
ICore::settings()->setValue(LAST_ACTIVE_TIMES_KEY, times);
});
connect(EditorManager::instance(), &EditorManager::editorCreated, connect(EditorManager::instance(), &EditorManager::editorCreated,
this, &SessionManager::configureEditor); this, &SessionManager::configureEditor);
connect(this, &SessionManager::projectAdded, connect(this, &SessionManager::projectAdded,
@@ -776,9 +785,14 @@ QStringList SessionManager::sessions()
// We are not initialized yet, so do that now // We are not initialized yet, so do that now
const FilePaths sessionFiles = const FilePaths sessionFiles =
ICore::userResourcePath().dirEntries({{"*qws"}}, QDir::Time | QDir::Reversed); ICore::userResourcePath().dirEntries({{"*qws"}}, QDir::Time | QDir::Reversed);
const QVariantMap lastActiveTimes = ICore::settings()->value(LAST_ACTIVE_TIMES_KEY).toMap();
for (const FilePath &file : sessionFiles) { for (const FilePath &file : sessionFiles) {
const QString &name = file.completeBaseName(); const QString &name = file.completeBaseName();
d->m_sessionDateTimes.insert(name, file.lastModified()); d->m_sessionDateTimes.insert(name, file.lastModified());
const auto lastActiveTime = lastActiveTimes.find(name);
d->m_lastActiveTimes.insert(name, lastActiveTime != lastActiveTimes.end()
? lastActiveTime->toDateTime()
: file.lastModified());
if (name != QLatin1String(DEFAULT_SESSION)) if (name != QLatin1String(DEFAULT_SESSION))
d->m_sessions << name; d->m_sessions << name;
} }
@@ -792,6 +806,11 @@ QDateTime SessionManager::sessionDateTime(const QString &session)
return d->m_sessionDateTimes.value(session); return d->m_sessionDateTimes.value(session);
} }
QDateTime SessionManager::lastActiveTime(const QString &session)
{
return d->m_lastActiveTimes.value(session);
}
FilePath SessionManager::sessionNameToFileName(const QString &session) FilePath SessionManager::sessionNameToFileName(const QString &session)
{ {
return ICore::userResourcePath(session + ".qws"); return ICore::userResourcePath(session + ".qws");
@@ -807,6 +826,7 @@ bool SessionManager::createSession(const QString &session)
return false; return false;
Q_ASSERT(d->m_sessions.size() > 0); Q_ASSERT(d->m_sessions.size() > 0);
d->m_sessions.insert(1, session); d->m_sessions.insert(1, session);
d->m_lastActiveTimes.insert(session, QDateTime::currentDateTime());
return true; return true;
} }
@@ -844,6 +864,7 @@ bool SessionManager::deleteSession(const QString &session)
if (!d->m_sessions.contains(session)) if (!d->m_sessions.contains(session))
return false; return false;
d->m_sessions.removeOne(session); d->m_sessions.removeOne(session);
d->m_lastActiveTimes.remove(session);
emit instance()->sessionRemoved(session); emit instance()->sessionRemoved(session);
QFile fi(sessionNameToFileName(session).toString()); QFile fi(sessionNameToFileName(session).toString());
if (fi.exists()) if (fi.exists())
@@ -1115,6 +1136,7 @@ bool SessionManager::loadSession(const QString &session, bool initial)
} }
d->m_casadeSetActive = reader.restoreValue(QLatin1String("CascadeSetActive"), false).toBool(); d->m_casadeSetActive = reader.restoreValue(QLatin1String("CascadeSetActive"), false).toBool();
d->m_lastActiveTimes.insert(session, QDateTime::currentDateTime());
emit m_instance->sessionLoaded(session); emit m_instance->sessionLoaded(session);

View File

@@ -41,6 +41,7 @@ public:
static QString startupSession(); static QString startupSession();
static QStringList sessions(); static QStringList sessions();
static QDateTime sessionDateTime(const QString &session); static QDateTime sessionDateTime(const QString &session);
static QDateTime lastActiveTime(const QString &session);
static bool createSession(const QString &session); static bool createSession(const QString &session);