From 01877b2c86d6abccd2f1a26683268a535e45831b Mon Sep 17 00:00:00 2001
From: Friedemann Kleint <Friedemann.Kleint@nokia.com>
Date: Thu, 1 Oct 2009 17:32:26 +0200
Subject: [PATCH] VCS: perforce, cvs, subversion: Goto current line in blame.

---
 src/plugins/cvs/cvsplugin.cpp               |  3 +++
 src/plugins/git/gitclient.cpp               |  4 +--
 src/plugins/git/gitclient.h                 |  2 +-
 src/plugins/git/gitplugin.cpp               |  6 +++--
 src/plugins/perforce/perforceplugin.cpp     |  6 +++--
 src/plugins/subversion/subversionplugin.cpp |  7 +++--
 src/plugins/vcsbase/vcsbaseeditor.cpp       | 30 +++++++++++++++++++++
 src/plugins/vcsbase/vcsbaseeditor.h         |  9 +++++++
 8 files changed, 58 insertions(+), 9 deletions(-)

diff --git a/src/plugins/cvs/cvsplugin.cpp b/src/plugins/cvs/cvsplugin.cpp
index cb9ffe037a5..922f6229f3f 100644
--- a/src/plugins/cvs/cvsplugin.cpp
+++ b/src/plugins/cvs/cvsplugin.cpp
@@ -760,14 +760,17 @@ void CVSPlugin::annotate(const QString &file)
 
     // Re-use an existing view if possible to support
     // the common usage pattern of continuously changing and diffing a file
+    const int lineNumber = VCSBase::VCSBaseEditor::lineNumberOfCurrentEditor(file);
 
     if (Core::IEditor *editor = locateEditor("annotateFileName", file)) {
         editor->createNew(response.stdOut);
+        VCSBase::VCSBaseEditor::gotoLineOfEditor(editor, lineNumber);
         Core::EditorManager::instance()->activateEditor(editor);
     } else {
         const QString title = QString::fromLatin1("cvs annotate %1").arg(QFileInfo(file).fileName());
         Core::IEditor *newEditor = showOutputInEditor(title, response.stdOut, VCSBase::AnnotateOutput, file, codec);
         newEditor->setProperty("annotateFileName", file);
+        VCSBase::VCSBaseEditor::gotoLineOfEditor(newEditor, lineNumber);
     }
 }
 
diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp
index 4d64437ec39..d413ef75d41 100644
--- a/src/plugins/git/gitclient.cpp
+++ b/src/plugins/git/gitclient.cpp
@@ -298,10 +298,10 @@ void GitClient::show(const QString &source, const QString &id)
     executeGit(workDir, arguments, editor);
 }
 
-void GitClient::blame(const QString &workingDirectory, const QString &fileName)
+void GitClient::blame(const QString &workingDirectory, const QString &fileName, int lineNumber /* = -1 */)
 {
     if (Git::Constants::debug)
-        qDebug() << "blame" << workingDirectory << fileName;
+        qDebug() << "blame" << workingDirectory << fileName << lineNumber;
     QStringList arguments(QLatin1String("blame"));
     arguments << QLatin1String("--") << fileName;
 
diff --git a/src/plugins/git/gitclient.h b/src/plugins/git/gitclient.h
index 5064d639804..26014eee541 100644
--- a/src/plugins/git/gitclient.h
+++ b/src/plugins/git/gitclient.h
@@ -80,7 +80,7 @@ public:
 
     void status(const QString &workingDirectory);
     void log(const QString &workingDirectory, const QString &fileName);
-    void blame(const QString &workingDirectory, const QString &fileName);
+    void blame(const QString &workingDirectory, const QString &fileName, int lineNumber = -1);
     void showCommit(const QString &workingDirectory, const QString &commit);
     void checkout(const QString &workingDirectory, const QString &file);
     void checkoutBranch(const QString &workingDirectory, const QString &branch);
diff --git a/src/plugins/git/gitplugin.cpp b/src/plugins/git/gitplugin.cpp
index 81d2fa2fa96..38b9b52f91f 100644
--- a/src/plugins/git/gitplugin.cpp
+++ b/src/plugins/git/gitplugin.cpp
@@ -481,7 +481,7 @@ void GitPlugin::statusFile()
 
 void GitPlugin::logFile()
 {
-    const QFileInfo fileInfo = currentFile();
+    const QFileInfo fileInfo = currentFile();    
     const QString fileName = fileInfo.fileName();
     const QString workingDirectory = fileInfo.absolutePath();
     m_gitClient->log(workingDirectory, fileName);
@@ -492,7 +492,9 @@ void GitPlugin::blameFile()
     const QFileInfo fileInfo = currentFile();
     const QString fileName = fileInfo.fileName();
     const QString workingDirectory = fileInfo.absolutePath();
-    m_gitClient->blame(workingDirectory, fileName);
+
+    m_gitClient->blame(workingDirectory, fileName,
+                       VCSBase::VCSBaseEditor::lineNumberOfCurrentEditor(fileInfo.absoluteFilePath()));
 }
 
 void GitPlugin::logProject()
diff --git a/src/plugins/perforce/perforceplugin.cpp b/src/plugins/perforce/perforceplugin.cpp
index a26ec7d4959..0777d21235b 100644
--- a/src/plugins/perforce/perforceplugin.cpp
+++ b/src/plugins/perforce/perforceplugin.cpp
@@ -651,9 +651,11 @@ void PerforcePlugin::annotate(const QString &fileName)
     const PerforceResponse result = runP4Cmd(args, QStringList(),
                                              CommandToWindow|StdErrToWindow|ErrorToWindow, codec);
     if (!result.error) {
+        const int lineNumber = VCSBase::VCSBaseEditor::lineNumberOfCurrentEditor(fileName);
         const QFileInfo fi(fileName);
-        showOutputInEditor(tr("p4 annotate %1").arg(fi.fileName()),
-            result.stdOut, VCSBase::AnnotateOutput, codec);
+        Core::IEditor *ed = showOutputInEditor(tr("p4 annotate %1").arg(fi.fileName()),
+                                               result.stdOut, VCSBase::AnnotateOutput, codec);
+        VCSBase::VCSBaseEditor::gotoLineOfEditor(ed, lineNumber);
     }
 }
 
diff --git a/src/plugins/subversion/subversionplugin.cpp b/src/plugins/subversion/subversionplugin.cpp
index 23ffd205ad8..dd6bdd7103f 100644
--- a/src/plugins/subversion/subversionplugin.cpp
+++ b/src/plugins/subversion/subversionplugin.cpp
@@ -690,7 +690,7 @@ void SubversionPlugin::startCommit(const QStringList &files)
         return;
     }
     m_commitMessageFileName = changeTmpFile.fileName();
-    // TODO: Retrieve submit template from
+    // TODO: Regitctrieve submit template from
     const QString submitTemplate;
     // Create a submit
     changeTmpFile.write(submitTemplate.toUtf8());
@@ -780,14 +780,17 @@ void SubversionPlugin::annotate(const QString &file)
 
     // Re-use an existing view if possible to support
     // the common usage pattern of continuously changing and diffing a file
+    const int lineNumber = VCSBase::VCSBaseEditor::lineNumberOfCurrentEditor(file);
 
     if (Core::IEditor *editor = locateEditor("annotateFileName", file)) {
         editor->createNew(response.stdOut);
-        Core::EditorManager::instance()->activateEditor(editor);
+        VCSBase::VCSBaseEditor::gotoLineOfEditor(editor, lineNumber);
+        Core::EditorManager::instance()->activateEditor(editor);        
     } else {
         const QString title = QString::fromLatin1("svn annotate %1").arg(QFileInfo(file).fileName());
         Core::IEditor *newEditor = showOutputInEditor(title, response.stdOut, VCSBase::AnnotateOutput, file, codec);
         newEditor->setProperty("annotateFileName", file);
+        VCSBase::VCSBaseEditor::gotoLineOfEditor(newEditor, lineNumber);
     }
 }
 
diff --git a/src/plugins/vcsbase/vcsbaseeditor.cpp b/src/plugins/vcsbase/vcsbaseeditor.cpp
index dc0f3cad0fa..4536445054b 100644
--- a/src/plugins/vcsbase/vcsbaseeditor.cpp
+++ b/src/plugins/vcsbase/vcsbaseeditor.cpp
@@ -36,6 +36,7 @@
 #include <coreplugin/editormanager/editormanager.h>
 #include <coreplugin/uniqueidmanager.h>
 #include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/ifile.h>
 #include <extensionsystem/pluginmanager.h>
 #include <projectexplorer/editorconfiguration.h>
 #include <projectexplorer/projectexplorer.h>
@@ -601,4 +602,33 @@ VCSBaseEditor *VCSBaseEditor::getVcsBaseEditor(const Core::IEditor *editor)
     return 0;
 }
 
+// Return line number of current editor if it matches.
+int VCSBaseEditor::lineNumberOfCurrentEditor(const QString &currentFile)
+{
+    Core::IEditor *ed = Core::EditorManager::instance()->currentEditor();
+    if (!ed)
+        return -1;
+    if (!currentFile.isEmpty()) {
+        const Core::IFile *ifile  = ed->file();
+        if (!ifile || ifile->fileName() != currentFile)
+            return -1;
+    }
+    const TextEditor::BaseTextEditorEditable *eda = qobject_cast<const TextEditor::BaseTextEditorEditable *>(ed);
+    if (!eda)
+        return -1;
+    return eda->currentLine();
+}
+
+bool VCSBaseEditor::gotoLineOfEditor(Core::IEditor *e, int lineNumber)
+{
+    if (lineNumber >= 0 && e) {
+        if (TextEditor::BaseTextEditorEditable *be = qobject_cast<TextEditor::BaseTextEditorEditable*>(e)) {
+            be->gotoLine(lineNumber);
+            return true;
+        }
+    }
+    return false;
+}
+
+
 } // namespace VCSBase
diff --git a/src/plugins/vcsbase/vcsbaseeditor.h b/src/plugins/vcsbase/vcsbaseeditor.h
index 33f8f0ab23c..286f950cd62 100644
--- a/src/plugins/vcsbase/vcsbaseeditor.h
+++ b/src/plugins/vcsbase/vcsbaseeditor.h
@@ -119,6 +119,15 @@ public:
     // manager which is a BaseTextEditable.
     static VCSBaseEditor *getVcsBaseEditor(const Core::IEditor *editor);
 
+    // Utility to find the line number of the current editor. Optionally,
+    // pass in the file name to match it. To be used when jumping to current
+    // line number in a 'annnotate current file' slot, which checks if the
+    // current file originates from the current editor or the project selection.
+    static int lineNumberOfCurrentEditor(const QString &currentFile = QString());
+
+    //Helper to go to line of editor if it is a text editor
+    static bool gotoLineOfEditor(Core::IEditor *e, int lineNumber);
+
 signals:
     void describeRequested(const QString &source, const QString &change);
 
-- 
GitLab