Git: show modification states

Change-Id: I94d91e34489e6bb2e23cabe8f0c93dfc01ca7812
Reviewed-by: André Hartmann <aha_1980@gmx.de>
This commit is contained in:
Renaud Guezennec
2024-08-29 11:13:46 +02:00
parent 9f93e2261b
commit e58907b703
8 changed files with 96 additions and 26 deletions

View File

@@ -9,6 +9,7 @@
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/hostosinfo.h> #include <utils/hostosinfo.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/theme/theme.h>
#include <QDir> #include <QDir>
#include <QRegularExpression> #include <QRegularExpression>
@@ -63,10 +64,10 @@ FilePaths IVersionControl::additionalToolsPath() const
return {}; return {};
} }
bool IVersionControl::hasModification(const FilePath &path) const IVersionControl::FileState IVersionControl::modificationState(const FilePath &path) const
{ {
Q_UNUSED(path) Q_UNUSED(path)
return false; return IVersionControl::FileState::NoModification;
} }
void IVersionControl::monitorDirectory(const Utils::FilePath &path) void IVersionControl::monitorDirectory(const Utils::FilePath &path)
@@ -225,4 +226,43 @@ bool IVersionControl::handleLink(const FilePath &workingDirectory, const QString
return true; return true;
} }
QColor IVersionControl::vcStateToColor(const IVersionControl::FileState &state)
{
using CIVF = Core::IVersionControl::FileState;
using UT = Utils::Theme;
switch (state) {
case CIVF::ModifiedState:
return Utils::creatorColor(UT::VcsBase_FileModified_TextColor);
case CIVF::AddedState:
return Utils::creatorColor(UT::VcsBase_FileAdded_TextColor);
case CIVF::RenamedState:
return Utils::creatorColor(UT::VcsBase_FileRenamed_TextColor);
case CIVF::DeletedState:
return Utils::creatorColor(UT::VcsBase_FileDeleted_TextColor);
case CIVF::UnmanagedState:
return Utils::creatorColor(UT::VcsBase_FileUnmerged_TextColor);
default:
return Utils::creatorColor(UT::PaletteText);
}
}
QString IVersionControl::modificationToText(const IVersionControl::FileState &state)
{
using CIVF = Core::IVersionControl::FileState;
switch (state) {
case CIVF::AddedState:
return Tr::tr("Version control state: added");
case CIVF::ModifiedState:
return Tr::tr("Version control state: modified");
case CIVF::DeletedState:
return Tr::tr("Version control state: deleted");
case CIVF::RenamedState:
return Tr::tr("Version control state: renamed");
case CIVF::UnmanagedState:
return Tr::tr("Version control state: untracked");
default:
return {};
}
}
} // namespace Core } // namespace Core

View File

@@ -42,6 +42,16 @@ public:
OpenMandatory /*!< Files must always be opened by the VCS */ OpenMandatory /*!< Files must always be opened by the VCS */
}; };
enum class FileState : quint8 {
NoModification = 0x00,
ModifiedState,
AddedState,
DeletedState,
RenamedState,
UnmanagedState
};
Q_ENUM(FileState)
IVersionControl(); IVersionControl();
~IVersionControl() override; ~IVersionControl() override;
@@ -96,7 +106,7 @@ public:
/*! /*!
* Returns true if the file has modification compared to version control * Returns true if the file has modification compared to version control
*/ */
virtual bool hasModification(const Utils::FilePath &path) const; virtual Core::IVersionControl::FileState modificationState(const Utils::FilePath &path) const;
/*! /*!
* Starts monitoring modified files inside path * Starts monitoring modified files inside path
@@ -226,6 +236,9 @@ public:
QString refreshTopic(const Utils::FilePath &repository); QString refreshTopic(const Utils::FilePath &repository);
void setTopicRefresher(const TopicRefresher &topicRefresher); void setTopicRefresher(const TopicRefresher &topicRefresher);
static QColor vcStateToColor(const IVersionControl::FileState &state);
static QString modificationToText(const IVersionControl::FileState &state);
signals: signals:
void repositoryChanged(const Utils::FilePath &repository); void repositoryChanged(const Utils::FilePath &repository);
void filesChanged(const QStringList &files); void filesChanged(const QStringList &files);

View File

@@ -882,13 +882,13 @@ FilePaths GitClient::unmanagedFiles(const FilePaths &filePaths) const
return res; return res;
} }
bool GitClient::hasModification(const Utils::FilePath &workingDirectory, IVersionControl::FileState GitClient::modificationState(const Utils::FilePath &workingDirectory,
const Utils::FilePath &fileName) const const Utils::FilePath &fileName) const
{ {
const ModificationInfo &info = m_modifInfos[workingDirectory]; const ModificationInfo &info = m_modifInfos[workingDirectory];
int length = workingDirectory.toString().size(); int length = workingDirectory.toString().size();
const QString fileNameFromRoot = fileName.absoluteFilePath().path().mid(length + 1); const QString fileNameFromRoot = fileName.absoluteFilePath().path().mid(length + 1);
return info.modifiedFiles.contains(fileNameFromRoot); return info.modifiedFiles.value(fileNameFromRoot, IVersionControl::FileState::NoModification);
} }
void GitClient::stopMonitoring(const Utils::FilePath &path) void GitClient::stopMonitoring(const Utils::FilePath &path)
@@ -920,6 +920,7 @@ void GitClient::monitorDirectory(const Utils::FilePath &path)
void GitClient::updateModificationInfos() void GitClient::updateModificationInfos()
{ {
using IVCF = IVersionControl::FileState;
for (const ModificationInfo &infoTemp : std::as_const(m_modifInfos)) { for (const ModificationInfo &infoTemp : std::as_const(m_modifInfos)) {
const FilePath path = infoTemp.rootPath; const FilePath path = infoTemp.rootPath;
@@ -930,22 +931,31 @@ void GitClient::updateModificationInfos()
ModificationInfo &info = m_modifInfos[path]; ModificationInfo &info = m_modifInfos[path];
const QStringList res = result.cleanedStdOut().split("\n", Qt::SkipEmptyParts); const QStringList res = result.cleanedStdOut().split("\n", Qt::SkipEmptyParts);
QSet<QString> modifiedFiles; QHash<QString, IVCF> modifiedFiles;
for (const QString &line : res) { for (const QString &line : res) {
if (line.size() <= 3) if (line.size() <= 3)
continue; continue;
static const QSet<QChar> gitStates{'M', 'A'}; static const QHash<QChar, IVCF> gitStates {
{'M', IVCF::ModifiedState},
{'A', IVCF::AddedState},
{'R', IVCF::RenamedState},
{'D', IVCF::DeletedState},
{'?', IVCF::UnmanagedState},
};
if (gitStates.contains(line.at(0)) || gitStates.contains(line.at(1))) const IVCF &modification = std::max(gitStates.value(line.at(0), IVCF::NoModification),
modifiedFiles.insert(line.mid(3).trimmed()); gitStates.value(line.at(1), IVCF::NoModification));
if (modification != IVCF::NoModification)
modifiedFiles.insert(line.mid(3).trimmed(), modification);
} }
const QSet<QString> oldfiles = info.modifiedFiles; const QHash<QString, IVCF> oldfiles = info.modifiedFiles;
info.modifiedFiles = modifiedFiles; info.modifiedFiles = modifiedFiles;
QStringList newList = modifiedFiles.values(); QStringList newList = modifiedFiles.keys();
QStringList list = oldfiles.values(); QStringList list = oldfiles.keys();
newList.sort(); newList.sort();
list.sort(); list.sort();
QStringList statusChangedFiles; QStringList statusChangedFiles;

View File

@@ -122,7 +122,7 @@ public:
struct ModificationInfo struct ModificationInfo
{ {
Utils::FilePath rootPath; Utils::FilePath rootPath;
QSet<QString> modifiedFiles; QHash<QString, Core::IVersionControl::FileState> modifiedFiles;
}; };
GitClient(); GitClient();
@@ -140,7 +140,7 @@ public:
Utils::FilePath findGitDirForRepository(const Utils::FilePath &repositoryDir) const; Utils::FilePath findGitDirForRepository(const Utils::FilePath &repositoryDir) const;
bool managesFile(const Utils::FilePath &workingDirectory, const QString &fileName) const; bool managesFile(const Utils::FilePath &workingDirectory, const QString &fileName) const;
Utils::FilePaths unmanagedFiles(const Utils::FilePaths &filePaths) const; Utils::FilePaths unmanagedFiles(const Utils::FilePaths &filePaths) const;
bool hasModification(const Utils::FilePath &workingDirectory, Core::IVersionControl::FileState modificationState(const Utils::FilePath &workingDirectory,
const Utils::FilePath &fileName) const; const Utils::FilePath &fileName) const;
void monitorDirectory(const Utils::FilePath &path); void monitorDirectory(const Utils::FilePath &path);
void stopMonitoring(const Utils::FilePath &path); void stopMonitoring(const Utils::FilePath &path);

View File

@@ -157,7 +157,7 @@ public:
FilePaths unmanagedFiles(const FilePaths &filePaths) const final; FilePaths unmanagedFiles(const FilePaths &filePaths) const final;
bool isConfigured() const final; bool isConfigured() const final;
bool hasModification(const Utils::FilePath &path) const final; IVersionControl::FileState modificationState(const Utils::FilePath &path) const final;
void monitorDirectory(const Utils::FilePath &path) final; void monitorDirectory(const Utils::FilePath &path) final;
void stopMonitoringDirectory(const Utils::FilePath &path) final; void stopMonitoringDirectory(const Utils::FilePath &path) final;
bool supportsOperation(Operation operation) const final; bool supportsOperation(Operation operation) const final;
@@ -1763,10 +1763,10 @@ bool GitPluginPrivate::isConfigured() const
return !gitClient().vcsBinary({}).isEmpty(); return !gitClient().vcsBinary({}).isEmpty();
} }
bool GitPluginPrivate::hasModification(const Utils::FilePath &path) const IVersionControl::FileState GitPluginPrivate::modificationState(const Utils::FilePath &path) const
{ {
const Utils::FilePath projectDir = gitClient().findRepositoryForDirectory(path.absolutePath()); const Utils::FilePath projectDir = gitClient().findRepositoryForDirectory(path.absolutePath());
return gitClient().hasModification(projectDir, path); return gitClient().modificationState(projectDir, path);
} }
void GitPluginPrivate::monitorDirectory(const Utils::FilePath &path) void GitPluginPrivate::monitorDirectory(const Utils::FilePath &path)

View File

@@ -215,8 +215,11 @@ QVariant FlatModel::data(const QModelIndex &index, int role) const
tooltip += "<p>" + Tr::tr("No kits are enabled for this project. " tooltip += "<p>" + Tr::tr("No kits are enabled for this project. "
"Enable kits in the \"Projects\" mode."); "Enable kits in the \"Projects\" mode.");
} }
} else if (fileNode && fileNode->hasModification()) { } else if (fileNode) {
tooltip += "<p>" + Tr::tr("Version control state: modified"); const QString &stateText =
IVersionControl::modificationToText(fileNode->modificationState());
if (!stateText.isEmpty())
tooltip += "<p>" + stateText;
} }
return tooltip; return tooltip;
} }
@@ -243,8 +246,11 @@ QVariant FlatModel::data(const QModelIndex &index, int role) const
return font; return font;
} }
case Qt::ForegroundRole: case Qt::ForegroundRole:
if (fileNode && fileNode->hasModification()) if (fileNode) {
return Utils::creatorColor(Utils::Theme::VcsBase_FileModified_TextColor); Core::IVersionControl::FileState state = fileNode->modificationState();
if (state != Core::IVersionControl::FileState::NoModification)
return Core::IVersionControl::vcStateToColor(state);
}
return node->isEnabled() ? QVariant() return node->isEnabled() ? QVariant()
: Utils::creatorColor(Utils::Theme::TextColorDisabled); : Utils::creatorColor(Utils::Theme::TextColorDisabled);
case Project::FilePathRole: case Project::FilePathRole:

View File

@@ -261,17 +261,17 @@ void FileNode::setHasError(bool error) const
m_hasError = error; m_hasError = error;
} }
bool FileNode::hasModification() const Core::IVersionControl::FileState FileNode::modificationState() const
{ {
if (isGenerated()) if (isGenerated())
return false; return Core::IVersionControl::FileState::NoModification;
const FilePath file = filePath(); const FilePath file = filePath();
const FilePath dir = file.absolutePath(); const FilePath dir = file.absolutePath();
if (Core::IVersionControl *vc = Core::VcsManager::findVersionControlForDirectory(dir)) if (Core::IVersionControl *vc = Core::VcsManager::findVersionControlForDirectory(dir))
return vc->hasModification(file); return vc->modificationState(file);
return false; return Core::IVersionControl::FileState::NoModification;
} }
bool FileNode::useUnavailableMarker() const bool FileNode::useUnavailableMarker() const

View File

@@ -8,6 +8,7 @@
#include <QIcon> #include <QIcon>
#include <QStringList> #include <QStringList>
#include <coreplugin/iversioncontrol.h>
#include <utils/filepath.h> #include <utils/filepath.h>
#include <utils/id.h> #include <utils/id.h>
@@ -202,7 +203,7 @@ public:
void setHasError(const bool error); void setHasError(const bool error);
void setHasError(const bool error) const; void setHasError(const bool error) const;
bool hasModification() const; Core::IVersionControl::FileState modificationState() const;
QIcon icon() const; QIcon icon() const;
void setIcon(const QIcon icon); void setIcon(const QIcon icon);