From 39b826c6845271c1f35a123ba90819c7e286c769 Mon Sep 17 00:00:00 2001 From: Andre Hartmann Date: Fri, 30 Aug 2024 09:25:12 +0200 Subject: [PATCH] ProjectExplorer: Add VCS log for selected directory Change-Id: Ie4ad575eaa4cd1adea1e10a65dc04f1aa945b300 Reviewed-by: Orgad Shaneh --- src/plugins/bazaar/bazaarplugin.cpp | 4 +++ src/plugins/clearcase/clearcaseplugin.cpp | 3 ++ src/plugins/coreplugin/iversioncontrol.h | 6 ++++ src/plugins/coreplugin/vcsmanager.cpp | 1 + src/plugins/cvs/cvsplugin.cpp | 3 ++ src/plugins/fossil/fossilplugin.cpp | 9 ++++++ src/plugins/git/gitplugin.cpp | 3 ++ src/plugins/mercurial/mercurialplugin.cpp | 3 ++ src/plugins/perforce/perforceplugin.cpp | 3 ++ .../projectexplorer/projectexplorer.cpp | 32 +++++++++++++++++++ src/plugins/projectexplorer/projectexplorer.h | 1 + src/plugins/projectexplorer/projecttree.cpp | 9 ++++++ src/plugins/subversion/subversionplugin.cpp | 3 ++ 13 files changed, 80 insertions(+) diff --git a/src/plugins/bazaar/bazaarplugin.cpp b/src/plugins/bazaar/bazaarplugin.cpp index e1a9d0dce75..b01aa813f09 100644 --- a/src/plugins/bazaar/bazaarplugin.cpp +++ b/src/plugins/bazaar/bazaarplugin.cpp @@ -143,6 +143,10 @@ public: bool vcsMove(const Utils::FilePath &from, const Utils::FilePath &to) final; bool vcsCreateRepository(const Utils::FilePath &directory) final; void vcsAnnotate(const Utils::FilePath &file, int line) final; + void vcsLog(const Utils::FilePath &topLevel, const Utils::FilePath &relativeDirectory) final { + const QStringList options = {"--limit=" + QString::number(settings().logCount())}; + m_client.log(topLevel, {relativeDirectory.path()}, options); + } void vcsDescribe(const Utils::FilePath &source, const QString &id) final { m_client.view(source, id); } VcsCommand *createInitialCheckoutCommand(const QString &url, diff --git a/src/plugins/clearcase/clearcaseplugin.cpp b/src/plugins/clearcase/clearcaseplugin.cpp index ea7963a0b5c..6a4e2048279 100644 --- a/src/plugins/clearcase/clearcaseplugin.cpp +++ b/src/plugins/clearcase/clearcaseplugin.cpp @@ -139,6 +139,9 @@ public: bool vcsCreateRepository(const FilePath &directory) final; void vcsAnnotate(const FilePath &file, int line) final; + void vcsLog(const Utils::FilePath &topLevel, const Utils::FilePath &relativeDirectory) final { + history(topLevel, {relativeDirectory.path()}); + } void vcsDescribe(const FilePath &source, const QString &changeNr) final; QString vcsOpenText() const final; diff --git a/src/plugins/coreplugin/iversioncontrol.h b/src/plugins/coreplugin/iversioncontrol.h index 31e35437770..98899229204 100644 --- a/src/plugins/coreplugin/iversioncontrol.h +++ b/src/plugins/coreplugin/iversioncontrol.h @@ -155,6 +155,12 @@ public: */ virtual void vcsAnnotate(const Utils::FilePath &file, int line) = 0; + /*! + * Shows the log for the \a relativeDirectory within \a toplevel. + */ + virtual void vcsLog(const Utils::FilePath &topLevel, + const Utils::FilePath &relativeDirectory) = 0; + /*! * Display text for Open operation */ diff --git a/src/plugins/coreplugin/vcsmanager.cpp b/src/plugins/coreplugin/vcsmanager.cpp index 16a4f68ba49..5a189f39471 100644 --- a/src/plugins/coreplugin/vcsmanager.cpp +++ b/src/plugins/coreplugin/vcsmanager.cpp @@ -507,6 +507,7 @@ public: bool vcsMove(const FilePath &, const FilePath &) final { return false; } bool vcsCreateRepository(const FilePath &) final { return false; } void vcsAnnotate(const FilePath &, int) final {} + void vcsLog(const Utils::FilePath &, const Utils::FilePath &) final {}; void vcsDescribe(const FilePath &, const QString &) final {} private: diff --git a/src/plugins/cvs/cvsplugin.cpp b/src/plugins/cvs/cvsplugin.cpp index 78839306581..24ae4a2b17d 100644 --- a/src/plugins/cvs/cvsplugin.cpp +++ b/src/plugins/cvs/cvsplugin.cpp @@ -175,6 +175,9 @@ public: bool vcsMove(const Utils::FilePath &, const Utils::FilePath &) final { return false; } bool vcsCreateRepository(const Utils::FilePath &directory) final; void vcsAnnotate(const Utils::FilePath &filePath, int line) final; + void vcsLog(const Utils::FilePath &topLevel, const Utils::FilePath &relativeDirectory) final { + filelog(topLevel, relativeDirectory.path(), true); + } QString vcsOpenText() const final; diff --git a/src/plugins/fossil/fossilplugin.cpp b/src/plugins/fossil/fossilplugin.cpp index 6401f58b658..77e9f62d921 100644 --- a/src/plugins/fossil/fossilplugin.cpp +++ b/src/plugins/fossil/fossilplugin.cpp @@ -91,6 +91,15 @@ public: void vcsAnnotate(const FilePath &file, int line) final; void vcsDescribe(const FilePath &source, const QString &id) final; + void vcsLog(const Utils::FilePath &topLevel, const Utils::FilePath &relativeDirectory) final { + FossilClient::SupportedFeatures features = fossilClient().supportedFeatures(); + QStringList options = {"-n", QString::number(fossilClient().settings().logCount())}; + + if (features.testFlag(FossilClient::TimelineWidthFeature)) + options << "-W" << QString::number(fossilClient().settings().timelineWidth()); + + fossilClient().log(topLevel, {relativeDirectory.path()}, options); + } VcsCommand *createInitialCheckoutCommand(const QString &url, const FilePath &baseDirectory, diff --git a/src/plugins/git/gitplugin.cpp b/src/plugins/git/gitplugin.cpp index 7afe9fcfac7..857c467a7bf 100644 --- a/src/plugins/git/gitplugin.cpp +++ b/src/plugins/git/gitplugin.cpp @@ -165,6 +165,9 @@ public: bool vcsCreateRepository(const FilePath &directory) final; void vcsAnnotate(const FilePath &filePath, int line) final; + void vcsLog(const Utils::FilePath &topLevel, const Utils::FilePath &relativeDirectory) final { + gitClient().log(topLevel, relativeDirectory.toString(), true); + } void vcsDescribe(const FilePath &source, const QString &id) final { gitClient().show(source, id); } QString vcsTopic(const FilePath &directory) final; diff --git a/src/plugins/mercurial/mercurialplugin.cpp b/src/plugins/mercurial/mercurialplugin.cpp index 23f8abffa14..fe16c6caea5 100644 --- a/src/plugins/mercurial/mercurialplugin.cpp +++ b/src/plugins/mercurial/mercurialplugin.cpp @@ -72,6 +72,9 @@ public: bool vcsMove(const FilePath &from, const FilePath &to) final; bool vcsCreateRepository(const FilePath &directory) final; void vcsAnnotate(const FilePath &filePath, int line) final; + void vcsLog(const Utils::FilePath &topLevel, const Utils::FilePath &relativeDirectory) final { + mercurialClient().log(topLevel, {relativeDirectory.path()}); + } void vcsDescribe(const FilePath &source, const QString &id) final { mercurialClient().view(source, id); diff --git a/src/plugins/perforce/perforceplugin.cpp b/src/plugins/perforce/perforceplugin.cpp index eb153552dcd..665f54b5769 100644 --- a/src/plugins/perforce/perforceplugin.cpp +++ b/src/plugins/perforce/perforceplugin.cpp @@ -168,6 +168,9 @@ public: bool vcsMove(const Utils::FilePath &from, const Utils::FilePath &to) final; bool vcsCreateRepository(const Utils::FilePath &directory) final; void vcsAnnotate(const Utils::FilePath &filePath, int line) final; + void vcsLog(const Utils::FilePath &topLevel, const Utils::FilePath &relativeDirectory) final { + changelists(topLevel, relativeDirectory.path()); + } void vcsDescribe(const Utils::FilePath &source, const QString &n) final; QString vcsOpenText() const final; QString vcsMakeWritableText() const final; diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index c6fac116980..581e14f3006 100644 --- a/src/plugins/projectexplorer/projectexplorer.cpp +++ b/src/plugins/projectexplorer/projectexplorer.cpp @@ -237,6 +237,7 @@ const char ADDNEWSUBPROJECT[] = "ProjectExplorer.AddNewSubproject"; const char REMOVEPROJECT[] = "ProjectExplorer.RemoveProject"; const char OPENFILE[] = "ProjectExplorer.OpenFile"; const char SEARCHONFILESYSTEM[] = "ProjectExplorer.SearchOnFileSystem"; +const char VCS_LOG_DIRECTORY[] = "ProjectExplorer.VcsLog"; const char OPENTERMINALHERE[] = "ProjectExplorer.OpenTerminalHere"; const char SHOWINFILESYSTEMVIEW[] = "ProjectExplorer.OpenFileSystemView"; const char DUPLICATEFILE[] = "ProjectExplorer.DuplicateFile"; @@ -497,6 +498,7 @@ public: void removeProject(); void openFile(); void searchOnFileSystem(); + void vcsLogDirectory(); void showInGraphicalShell(); void showInFileSystemPane(); void removeFile(); @@ -602,6 +604,7 @@ public: Action *m_closeProjectFilesActionFileMenu; Action *m_closeProjectFilesActionContextMenu; QAction *m_searchOnFileSystem; + QAction *m_vcsLogAction = nullptr; QAction *m_showInGraphicalShell; QAction *m_showFileSystemPane; QAction *m_openTerminalHere; @@ -1130,6 +1133,14 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er msubProjectContextMenu->addAction(cmd, Constants::G_PROJECT_LAST); mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_LAST); + // VCS log directory action + dd->m_vcsLogAction = new QAction(Tr::tr("VCS Log Directory"), this); + cmd = ActionManager::registerAction(dd->m_vcsLogAction, Constants::VCS_LOG_DIRECTORY, projectTreeContext); + cmd->setAttribute(Command::CA_UpdateText); + mfolderContextMenu->addAction(cmd, Constants::G_FOLDER_CONFIG); + msubProjectContextMenu->addAction(cmd, Constants::G_PROJECT_LAST); + mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_LAST); + dd->m_showInGraphicalShell = new QAction(Core::FileUtils::msgGraphicalShellAction(), this); cmd = ActionManager::registerAction(dd->m_showInGraphicalShell, Core::Constants::SHOWINGRAPHICALSHELL, @@ -1817,6 +1828,8 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er dd, &ProjectExplorerPluginPrivate::openFile); connect(dd->m_searchOnFileSystem, &QAction::triggered, dd, &ProjectExplorerPluginPrivate::searchOnFileSystem); + connect(dd->m_vcsLogAction, &QAction::triggered, dd, + &ProjectExplorerPluginPrivate::vcsLogDirectory); connect(dd->m_showInGraphicalShell, &QAction::triggered, dd, &ProjectExplorerPluginPrivate::showInGraphicalShell); // the following can delete the projects view that triggered the action, so make sure we @@ -3256,6 +3269,7 @@ void ProjectExplorerPluginPrivate::updateContextMenuActions(Node *currentNode) m_showInGraphicalShell->setVisible(true); m_showFileSystemPane->setVisible(true); m_searchOnFileSystem->setVisible(true); + m_vcsLogAction->setVisible(true); ActionContainer *runMenu = ActionManager::actionContainer(Constants::RUNMENUCONTEXTMENU); runMenu->menu()->clear(); @@ -3376,6 +3390,7 @@ void ProjectExplorerPluginPrivate::updateContextMenuActions(Node *currentNode) m_showInGraphicalShell->setVisible(false); m_showFileSystemPane->setVisible(false); m_searchOnFileSystem->setVisible(false); + m_vcsLogAction->setVisible(false); } if (supports(HideFileActions)) { @@ -3662,6 +3677,18 @@ void ProjectExplorerPluginPrivate::searchOnFileSystem() TextEditor::FindInFiles::findOnFileSystem(currentNode->path().toString()); } +void ProjectExplorerPluginPrivate::vcsLogDirectory() +{ + const Node *currentNode = ProjectTree::currentNode(); + QTC_ASSERT(currentNode, return); + const FilePath directory = currentNode->directory(); + FilePath topLevel; + if (IVersionControl *vc = VcsManager::findVersionControlForDirectory(directory, &topLevel)) { + const FilePath relativeDirectory = directory.relativeChildPath(topLevel); + vc->vcsLog(topLevel, relativeDirectory); + } +} + void ProjectExplorerPluginPrivate::showInGraphicalShell() { Node *currentNode = ProjectTree::currentNode(); @@ -4087,6 +4114,11 @@ void ProjectExplorerPlugin::updateRunActions() dd->doUpdateRunActions(); } +void ProjectExplorerPlugin::updateVcsActions(const QString &vcsDisplayName) +{ + dd->m_vcsLogAction->setText(Tr::tr("%1 Log Directory").arg(vcsDisplayName)); +} + OutputWindow *ProjectExplorerPlugin::buildSystemOutput() { return dd->m_proWindow->buildSystemOutput(); diff --git a/src/plugins/projectexplorer/projectexplorer.h b/src/plugins/projectexplorer/projectexplorer.h index 11f0be1dd33..e1d2116df15 100644 --- a/src/plugins/projectexplorer/projectexplorer.h +++ b/src/plugins/projectexplorer/projectexplorer.h @@ -164,6 +164,7 @@ public: static void removeFromRecentProjects(const Utils::FilePath &filePath); static void updateRunActions(); + static void updateVcsActions(const QString &vcsDisplayName); static Core::OutputWindow *buildSystemOutput(); diff --git a/src/plugins/projectexplorer/projecttree.cpp b/src/plugins/projectexplorer/projecttree.cpp index 5f81f473fe4..6e444ee15e6 100644 --- a/src/plugins/projectexplorer/projecttree.cpp +++ b/src/plugins/projectexplorer/projecttree.cpp @@ -4,6 +4,7 @@ #include "projecttree.h" #include "project.h" +#include "projectexplorer.h" #include "projectexplorerconstants.h" #include "projectexplorertr.h" #include "projectmanager.h" @@ -18,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -338,6 +340,13 @@ void ProjectTree::showContextMenu(ProjectTreeWidget *focus, const QPoint &global QMenu *contextMenu = nullptr; emit s_instance->aboutToShowContextMenu(node); + const Node *currentNode = ProjectTree::currentNode(); + if (currentNode) { + const FilePath directory = currentNode->directory(); + if (Core::IVersionControl *vc = Core::VcsManager::findVersionControlForDirectory(directory)) + ProjectExplorerPlugin::updateVcsActions(vc->displayName()); + } + if (!node) { contextMenu = Core::ActionManager::actionContainer(Constants::M_SESSIONCONTEXT)->menu(); } else if (node->isProjectNodeType()) { diff --git a/src/plugins/subversion/subversionplugin.cpp b/src/plugins/subversion/subversionplugin.cpp index cac2176f1be..320f3c78c5f 100644 --- a/src/plugins/subversion/subversionplugin.cpp +++ b/src/plugins/subversion/subversionplugin.cpp @@ -149,6 +149,9 @@ public: bool vcsCreateRepository(const FilePath &directory) final; void vcsAnnotate(const FilePath &file, int line) final; + void vcsLog(const Utils::FilePath &topLevel, const Utils::FilePath &relativeDirectory) final { + filelog(topLevel, relativeDirectory.path()); + } void vcsDescribe(const FilePath &source, const QString &changeNr) final; VcsCommand *createInitialCheckoutCommand(const QString &url,