Welcome: Show open files in summary if there are no projects

In expanded items in the session list in Welcome mode.

Adapt the project display too: We showed the base name of the project
file as the project "title", which is "CMakeLists.txt" for all CMake
projects, and also for other projects doesn't really add interesting
information over the file name that we show.

If there are projects in the session, show a title "Projects" and the
list of open project paths.
If there are no projects, but open files, show a title "Files" and the
list of open file paths.
Limit the list of paths to 5 in both cases (adding "..." if there are
more).

Fixes: QTCREATORBUG-7660
Change-Id: I2e250c54f88932aaa95b926f60e0005da9c7a89e
Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
This commit is contained in:
Eike Ziller
2024-07-30 12:45:04 +02:00
parent 55615f63f7
commit c0fd0ab7b3
5 changed files with 112 additions and 67 deletions

View File

@@ -3639,10 +3639,14 @@ public:
bool pinned = false;
};
/*
Calls the "handler"s with the extracted data.
If the fileHandler returns false, the parsing is aborted.
*/
static void restore(
const QByteArray &state,
const std::function<void(QMap<QString, QVariant>)> &editorStatesHandler,
const std::function<void(FileStateEntry)> &fileHandler,
const std::function<bool(FileStateEntry)> &fileHandler,
const std::function<void(QByteArray)> &splitterStateHandler,
const std::function<void(QVector<QVariantHash>)> &windowStateHandler)
{
@@ -3668,8 +3672,8 @@ static void restore(
if (isVersion5)
stream >> file.pinned;
if (fileHandler)
fileHandler(file);
if (fileHandler && !fileHandler(file))
return;
}
QByteArray splitterstates;
@@ -3711,7 +3715,7 @@ void EditorManager::restoreState(const QByteArray &state)
if (!file.filePath.isEmpty() && !file.displayName.isEmpty()) {
const FilePath filePath = FilePath::fromUserInput(file.filePath);
if (!filePath.exists())
return;
return true;
const FilePath rfp = autoSaveName(filePath);
if (rfp.exists() && filePath.lastModified() < rfp.lastModified()) {
if (IEditor *editor = openEditor(filePath, file.id, DoNotMakeVisible))
@@ -3723,6 +3727,7 @@ void EditorManager::restoreState(const QByteArray &state)
DocumentModelPrivate::setPinned(entry, file.pinned);
}
}
return true;
};
const auto restoreSplitterState = [](const QByteArray &state) {
d->m_editorAreas.first()->restoreState(state);
@@ -3749,6 +3754,21 @@ void EditorManager::restoreState(const QByteArray &state)
QApplication::restoreOverrideCursor();
}
FilePaths EditorManagerPrivate::openFilesForState(const QByteArray &state, int max)
{
FilePaths result;
restore(
state,
{},
[&result, max](const FileStateEntry &entry) {
result << FilePath::fromUserInput(entry.filePath);
return max < 0 || result.size() <= max;
},
{},
{});
return result;
}
/*!
\internal
*/

View File

@@ -99,6 +99,7 @@ public:
static Qt::CaseSensitivity readFileSystemSensitivity(Utils::QtcSettings *settings);
static void writeFileSystemSensitivity(Utils::QtcSettings *settings,
Qt::CaseSensitivity sensitivity);
static Utils::FilePaths openFilesForState(const QByteArray &state, int max);
static EditorWindow *createEditorWindow();
static void addEditorArea(EditorArea *area);

View File

@@ -10,6 +10,7 @@
#include "coreconstants.h"
#include "coreplugin.h"
#include "editormanager/editormanager.h"
#include "editormanager/editormanager_p.h"
#include "icore.h"
#include "modemanager.h"
#include "progressmanager/progressmanager.h"
@@ -556,6 +557,18 @@ void SessionManagerPrivate::restoreEditors()
}
}
FilePaths SessionManager::openFilesForSessionName(const QString &session, int max)
{
const FilePath fileName = sessionNameToFileName(session);
PersistentSettingsReader reader;
if (fileName.exists()) {
if (!reader.load(fileName))
return {};
}
return Internal::EditorManagerPrivate::openFilesForState(
QByteArray::fromBase64(reader.restoreValue("EditorSettings").toByteArray()), max);
}
/*!
Returns the last session that was opened by the user.
*/

View File

@@ -12,6 +12,7 @@
namespace Utils {
class FilePath;
using FilePaths = QList<FilePath>;
class Key;
} // Utils
@@ -71,6 +72,8 @@ public:
static bool loadSession(const QString &session, bool initial = false);
static bool saveSession();
static Utils::FilePaths openFilesForSessionName(const QString &session, int max = -1);
signals:
void startupSessionRestored();
void aboutToUnloadSession(QString sessionName);

View File

@@ -11,6 +11,7 @@
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/documentmanager.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/icontext.h>
#include <coreplugin/icore.h>
#include <coreplugin/iwizardfactory.h>
@@ -44,6 +45,7 @@ using namespace Utils;
using namespace Utils::StyleHelper::SpacingTokens;
const char PROJECT_BASE_ID[] = "Welcome.OpenRecentProject";
static const qsizetype kMaxPathsDisplay = 5;
namespace ProjectExplorer {
namespace Internal {
@@ -87,6 +89,25 @@ static bool withIcon()
return s(100) > 60; // Hide icons if spacings are scaled to below 60%
}
static FilePaths pathsForSession(const QString &session, QString *title = nullptr)
{
const FilePaths projects = ProjectManager::projectsForSessionName(session);
if (projects.size()) {
if (title) {
//: title in expanded session items in welcome mode
*title = Tr::tr("Projects");
}
return projects;
}
const FilePaths allPaths = SessionManager::openFilesForSessionName(
session, kMaxPathsDisplay + 1 /* +1 so we know if there are more */);
if (title) {
//: title in expanded session items in welcome mode
*title = Tr::tr("Files");
}
return allPaths;
}
ProjectModel::ProjectModel(QObject *parent)
: QAbstractListModel(parent)
{
@@ -272,18 +293,6 @@ protected:
}
};
static FilePaths pathsForSessionName(const QString &session)
{
const FilePath fileName = SessionManager::sessionNameToFileName(session);
PersistentSettingsReader reader;
if (fileName.exists()) {
if (!reader.load(fileName))
return {};
}
// qDebug() << reader.restoreValue("EditorSettings").toByteArray();
return {};
}
class SessionDelegate : public BaseDelegate
{
protected:
@@ -335,17 +344,17 @@ public:
// | |(w:6) | +------------+ +-------------+ | | | | |
// | | | |(VPaddingXs)| |(VPaddingXs) | | | | | |
// |------------+--------+--------+------------+--------+-------------+--------+-------+ | | --+
// | +-- | (VPaddingXxs) | | | |
// | | +------------------------------+(HPaddingXs)| | |
// | | | <projectName> | | | |
// | | +------------------------------+ | | |
// | Per project in session --+ | (ExPaddingGapS) | |(sessionScrollBarGap)| |
// | | +------------------------------+ | | |
// | | | <projectPath> | | | |
// | | +------------------------------+ | | +-- Expansion
// | | (VPaddingXxs) | | | |
// | +------------------------------+(HPaddingXs)| | |
// | | <Projects | Files> | | | |
// | +------------------------------+ | | |
// | | (ExPaddingGapS) | |(sessionScrollBarGap)| |
// | +-- +------------------------------+ | | |
// | | | <path> | | | |
// | Per open project or file --+ +------------------------------+ | | +-- Expansion
// | +-- | (VPaddingXxs) | | | |
// +----------------------------------------------------+------------------------------+------------+ | |
// | (VPaddingXs) | | |
// | (VGapXs) | | |
// +---------------------------------------+--------------+-----------------------------------------+ | |
// +-- | <cloneButton>|<renameButton>|<deleteButton> | | |
// | +---------------------------------------+--------------+-----------------------------------------+ | |
@@ -454,47 +463,49 @@ public:
int yy = hdR.bottom();
if (expanded) {
const QFont projectNameFont = sessionProjectNameTF.font();
const QFontMetrics projectNameFm(projectNameFont);
const int projectNameLineHeight = sessionProjectNameTF.lineHeight();
const QFont projectPathFont = projectPathTF.font();
const QFontMetrics projectPathFm(projectPathFont);
const int projectPathLineHeight = projectPathTF.lineHeight();
const QFont titleFont = sessionProjectNameTF.font();
const QFontMetrics titleNameFm(titleFont);
const int titleLineHeight = sessionProjectNameTF.lineHeight();
const QFont pathFont = projectPathTF.font();
const QFontMetrics pathFm(pathFont);
const int pathLineHeight = projectPathTF.lineHeight();
const int textWidth = bgR.right() - s(HPaddingXs) - textX;
const auto getDisplayPath = [](const FilePath &p) {
return p.osType() == OsTypeWindows ? p.displayName() : p.withTildeHomePath();
};
const FilePaths projects = ProjectManager::projectsForSessionName(sessionName);
for (const FilePath &projectPath : projects) {
QString title;
const FilePaths allPaths = pathsForSession(sessionName, &title);
const qsizetype count = allPaths.size();
const FilePaths paths = allPaths.first(std::min(kMaxPathsDisplay, count));
const QStringList pathDisplay = Utils::transform(paths, getDisplayPath)
+ (count > kMaxPathsDisplay ? QStringList("...")
: QStringList());
if (pathDisplay.size()) {
yy += s(VPaddingXxs);
// title
{
painter->setFont(projectNameFont);
painter->setFont(titleFont);
painter->setPen(sessionProjectNameTF.color());
const QRect projectNameR(textX, yy, textWidth, projectNameLineHeight);
const QString projectNameElided =
projectNameFm.elidedText(projectPath.completeBaseName(), Qt::ElideMiddle,
textWidth);
painter->drawText(projectNameR, sessionProjectNameTF.drawTextFlags,
projectNameElided);
yy += projectNameLineHeight;
const QRect titleR(textX, yy, textWidth, titleLineHeight);
const QString titleElided
= titleNameFm.elidedText(title, Qt::ElideMiddle, textWidth);
painter->drawText(titleR, sessionProjectNameTF.drawTextFlags, titleElided);
yy += titleLineHeight;
yy += s(ExPaddingGapS);
}
{
const QString displayPath =
projectPath.osType() == OsTypeWindows ? projectPath.displayName()
: projectPath.withTildeHomePath();
painter->setFont(projectPathFont);
painter->setFont(pathFont);
painter->setPen(projectPathTF.color());
const QRect projectPathR(textX, yy, textWidth, projectPathLineHeight);
const QString projectPathElided =
projectPathFm.elidedText(displayPath, Qt::ElideMiddle, textWidth);
painter->drawText(projectPathR, projectPathTF.drawTextFlags,
projectPathElided);
yy += projectPathLineHeight;
for (const QString &displayPath : pathDisplay) {
const QRect pathR(textX, yy, textWidth, pathLineHeight);
const QString pathElided
= pathFm.elidedText(displayPath, Qt::ElideMiddle, textWidth);
painter->drawText(pathR, projectPathTF.drawTextFlags, pathElided);
yy += pathLineHeight;
yy += s(VPaddingXxs);
}
}
yy += s(VPaddingXxs);
}
if (projects.isEmpty()) {
// check if there are files to show instead
const FilePaths paths = pathsForSessionName(sessionName);
}
yy += s(VGapXs);
@@ -560,17 +571,14 @@ public:
int h = headerHeight();
if (expanded(idx)) {
const QString sessionName = idx.data(Qt::DisplayRole).toString();
const FilePaths projects = ProjectManager::projectsForSessionName(sessionName);
const int projectEntryHeight =
s(VPaddingXxs)
+ projectNameTF.lineHeight()
+ s(ExPaddingGapS)
+ projectPathTF.lineHeight()
+ s(VPaddingXxs);
h += projects.size() * projectEntryHeight
+ s(VGapXs)
+ actionButtonHeight()
+ s(VGapXs);
const FilePaths paths = pathsForSession(sessionName);
const int displayPathCount = std::min(kMaxPathsDisplay + 1, paths.size());
const int contentHeight
= displayPathCount == 0
? 0
: s(VPaddingXxs) + sessionProjectNameTF.lineHeight() + s(ExPaddingGapS)
+ displayPathCount * (projectPathTF.lineHeight() + s(VPaddingXxs));
h += contentHeight + s(VGapXs) + actionButtonHeight() + s(VGapXs);
}
return QSize(-1, h + itemSpacing());
}