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/hostosinfo.h>
#include <utils/qtcassert.h>
#include <utils/theme/theme.h>
#include <QDir>
#include <QRegularExpression>
@@ -63,10 +64,10 @@ FilePaths IVersionControl::additionalToolsPath() const
return {};
}
bool IVersionControl::hasModification(const FilePath &path) const
IVersionControl::FileState IVersionControl::modificationState(const FilePath &path) const
{
Q_UNUSED(path)
return false;
return IVersionControl::FileState::NoModification;
}
void IVersionControl::monitorDirectory(const Utils::FilePath &path)
@@ -225,4 +226,43 @@ bool IVersionControl::handleLink(const FilePath &workingDirectory, const QString
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

View File

@@ -42,6 +42,16 @@ public:
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() override;
@@ -96,7 +106,7 @@ public:
/*!
* 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
@@ -226,6 +236,9 @@ public:
QString refreshTopic(const Utils::FilePath &repository);
void setTopicRefresher(const TopicRefresher &topicRefresher);
static QColor vcStateToColor(const IVersionControl::FileState &state);
static QString modificationToText(const IVersionControl::FileState &state);
signals:
void repositoryChanged(const Utils::FilePath &repository);
void filesChanged(const QStringList &files);

View File

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

View File

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

View File

@@ -157,7 +157,7 @@ public:
FilePaths unmanagedFiles(const FilePaths &filePaths) 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 stopMonitoringDirectory(const Utils::FilePath &path) final;
bool supportsOperation(Operation operation) const final;
@@ -1763,10 +1763,10 @@ bool GitPluginPrivate::isConfigured() const
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());
return gitClient().hasModification(projectDir, path);
return gitClient().modificationState(projectDir, 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. "
"Enable kits in the \"Projects\" mode.");
}
} else if (fileNode && fileNode->hasModification()) {
tooltip += "<p>" + Tr::tr("Version control state: modified");
} else if (fileNode) {
const QString &stateText =
IVersionControl::modificationToText(fileNode->modificationState());
if (!stateText.isEmpty())
tooltip += "<p>" + stateText;
}
return tooltip;
}
@@ -243,8 +246,11 @@ QVariant FlatModel::data(const QModelIndex &index, int role) const
return font;
}
case Qt::ForegroundRole:
if (fileNode && fileNode->hasModification())
return Utils::creatorColor(Utils::Theme::VcsBase_FileModified_TextColor);
if (fileNode) {
Core::IVersionControl::FileState state = fileNode->modificationState();
if (state != Core::IVersionControl::FileState::NoModification)
return Core::IVersionControl::vcStateToColor(state);
}
return node->isEnabled() ? QVariant()
: Utils::creatorColor(Utils::Theme::TextColorDisabled);
case Project::FilePathRole:

View File

@@ -261,17 +261,17 @@ void FileNode::setHasError(bool error) const
m_hasError = error;
}
bool FileNode::hasModification() const
Core::IVersionControl::FileState FileNode::modificationState() const
{
if (isGenerated())
return false;
return Core::IVersionControl::FileState::NoModification;
const FilePath file = filePath();
const FilePath dir = file.absolutePath();
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

View File

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