diff --git a/src/plugins/perforce/perforceplugin.cpp b/src/plugins/perforce/perforceplugin.cpp
index d3fcc1d17dec20a86b0b8655b332d801a23d5ebb..65efbc977f3fb7a5e05516eaced425ac3a5ea638 100644
--- a/src/plugins/perforce/perforceplugin.cpp
+++ b/src/plugins/perforce/perforceplugin.cpp
@@ -106,6 +106,27 @@ static inline QString debugCodec(const QTextCodec *c)
     return c ? QString::fromAscii(c->name()) : QString::fromAscii("Null codec");
 }
 
+// Return the project files relevant for VCS
+static const QStringList currentProjectFiles(QString *name)
+{
+    QStringList files = VCSBase::VCSBaseSubmitEditor::currentProjectFiles(true, name);
+    if (!files.empty()) {
+        // Filter out mkspecs/qconfig.pri
+        QString exclusion = QLatin1String("mkspecs");
+        exclusion += QDir::separator();
+        exclusion += QLatin1String("qconfig.pri");
+        for (QStringList::iterator it = files.begin(); it != files.end(); ) {
+            if (it->endsWith(exclusion)) {
+                it = files.erase(it);
+                break;
+            } else {
+                ++it;
+            }
+        }
+    }
+    return files;
+}
+
 const char * const PerforcePlugin::PERFORCE_MENU = "Perforce.Menu";
 const char * const PerforcePlugin::EDIT = "Perforce.Edit";
 const char * const PerforcePlugin::ADD = "Perforce.Add";
@@ -450,7 +471,7 @@ void PerforcePlugin::diffCurrentFile()
 void PerforcePlugin::diffCurrentProject()
 {
     QString name;
-    const QStringList nativeFiles = VCSBase::VCSBaseSubmitEditor::currentProjectFiles(true, &name);
+    const QStringList nativeFiles = currentProjectFiles(&name);
     p4Diff(nativeFiles, name);
 }
 
@@ -509,7 +530,7 @@ void PerforcePlugin::submit()
 
     // Assemble file list of project
     QString name;
-    const QStringList nativeFiles = VCSBase::VCSBaseSubmitEditor::currentProjectFiles(true, &name);
+    const QStringList nativeFiles = currentProjectFiles(&name);
     PerforceResponse result2 = runP4Cmd(QStringList(QLatin1String("fstat")), nativeFiles,
                                         CommandToWindow|StdErrToWindow|ErrorToWindow);
     if (result2.error) {
@@ -846,7 +867,9 @@ Core::IEditor * PerforcePlugin::showOutputInEditor(const QString& title, const Q
     e->setSuggestedFileName(s);
     if (codec)
         e->setCodec(codec);
-    return e->editableInterface();
+    Core::IEditor *ie = e->editableInterface();
+    Core::EditorManager::instance()->activateEditor(ie);
+    return ie;
 }
 
 QStringList PerforcePlugin::environment() const
diff --git a/src/plugins/subversion/subversionplugin.cpp b/src/plugins/subversion/subversionplugin.cpp
index 5645031eb484681251eeb2912e2de8c0a35f5112..67e56eacf65d1c65996c40408e8f39cf01a40401 100644
--- a/src/plugins/subversion/subversionplugin.cpp
+++ b/src/plugins/subversion/subversionplugin.cpp
@@ -1039,7 +1039,9 @@ Core::IEditor * SubversionPlugin::showOutputInEditor(const QString& title, const
         e->setSource(source);
     if (codec)
         e->setCodec(codec);
-    return e->editableInterface();
+    Core::IEditor *ie = e->editableInterface();
+    Core::EditorManager::instance()->activateEditor(ie);
+    return ie;
 }
 
 SubversionSettings SubversionPlugin::settings() const
diff --git a/src/plugins/vcsbase/diffhighlighter.cpp b/src/plugins/vcsbase/diffhighlighter.cpp
index 57c8cd4b25e376ce19e7ff9c4d087b47d9ec70bd..e4f434c28d0260ccc201eb2f801429b3dd51c24c 100644
--- a/src/plugins/vcsbase/diffhighlighter.cpp
+++ b/src/plugins/vcsbase/diffhighlighter.cpp
@@ -115,4 +115,9 @@ void DiffHighlighter::setFormats(const QVector<QTextCharFormat> &s)
     }
 }
 
+QRegExp DiffHighlighter::filePattern() const
+{
+    return m_d->m_filePattern;
+}
+
 } // namespace VCSBase
diff --git a/src/plugins/vcsbase/diffhighlighter.h b/src/plugins/vcsbase/diffhighlighter.h
index 93da9b1daddbcf81a92645ae0f8d508cf1845ba7..83a4a36d4daa5e8f289b422844b7d928ea16aa4c 100644
--- a/src/plugins/vcsbase/diffhighlighter.h
+++ b/src/plugins/vcsbase/diffhighlighter.h
@@ -79,6 +79,8 @@ public:
     // Set formats from a sequence of type QTextCharFormat
     void setFormats(const QVector<QTextCharFormat> &s);
 
+    QRegExp filePattern() const;
+
 private:
     DiffHighlighterPrivate *m_d;
 };
diff --git a/src/plugins/vcsbase/vcsbaseeditor.cpp b/src/plugins/vcsbase/vcsbaseeditor.cpp
index 21442b3144c08a1a25a3bb7425d963a2695164af..2376f3b83e3dae74bc18841ef6b652317a3750e9 100644
--- a/src/plugins/vcsbase/vcsbaseeditor.cpp
+++ b/src/plugins/vcsbase/vcsbaseeditor.cpp
@@ -35,12 +35,14 @@
 
 #include <coreplugin/editormanager/editormanager.h>
 #include <coreplugin/uniqueidmanager.h>
+#include <coreplugin/editormanager/editormanager.h>
 #include <extensionsystem/pluginmanager.h>
 #include <projectexplorer/editorconfiguration.h>
 #include <projectexplorer/projectexplorer.h>
 #include <projectexplorer/session.h>
 #include <texteditor/fontsettings.h>
 #include <texteditor/texteditorconstants.h>
+#include <utils/qtcassert.h>
 
 #include <QtCore/QDebug>
 #include <QtCore/QFileInfo>
@@ -55,10 +57,13 @@
 #include <QtGui/QMenu>
 #include <QtGui/QTextCursor>
 #include <QtGui/QTextEdit>
+#include <QtGui/QComboBox>
+#include <QtGui/QToolBar>
 
 namespace VCSBase {
 
 // VCSBaseEditorEditable: An editable with no support for duplicates
+// Creates a browse combo in the toolbar for diff output.
 class VCSBaseEditorEditable : public TextEditor::BaseTextEditorEditable
 {
 public:
@@ -73,12 +78,12 @@ public:
 private:
     const char *m_kind;
     QList<int> m_context;
-
 };
 
 VCSBaseEditorEditable::VCSBaseEditorEditable(VCSBaseEditor *editor,
-                                             const VCSBaseEditorParameters *type)
-    : BaseTextEditorEditable(editor), m_kind(type->kind)
+                                             const VCSBaseEditorParameters *type)  :
+    BaseTextEditorEditable(editor),
+    m_kind(type->kind)
 {
     Core::UniqueIDManager *uidm = Core::UniqueIDManager::instance();
     m_context << uidm->uniqueIdentifier(QLatin1String(type->context))
@@ -90,6 +95,34 @@ QList<int> VCSBaseEditorEditable::context() const
     return m_context;
 }
 
+// Diff editable: creates a browse combo in the toolbar for diff output.
+class VCSBaseDiffEditorEditable : public VCSBaseEditorEditable
+{
+public:
+    VCSBaseDiffEditorEditable(VCSBaseEditor *, const VCSBaseEditorParameters *type);
+
+    virtual QToolBar *toolBar()                { return m_toolBar; }
+    QComboBox *diffFileBrowseComboBox() const  { return m_diffFileBrowseComboBox; }
+
+private:
+    QComboBox *m_diffFileBrowseComboBox;
+    QToolBar *m_toolBar;
+};
+
+VCSBaseDiffEditorEditable::VCSBaseDiffEditorEditable(VCSBaseEditor *e, const VCSBaseEditorParameters *type) :
+    VCSBaseEditorEditable(e, type),
+    m_diffFileBrowseComboBox(new QComboBox),
+    m_toolBar(new QToolBar)
+{
+    m_diffFileBrowseComboBox->setMinimumContentsLength(20);
+    m_diffFileBrowseComboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
+    // Make the combo box prefer to expand
+    QSizePolicy policy = m_diffFileBrowseComboBox->sizePolicy();
+    policy.setHorizontalPolicy(QSizePolicy::Expanding);
+    m_diffFileBrowseComboBox->setSizePolicy(policy);
+    m_toolBar->addWidget(m_diffFileBrowseComboBox);
+}
+
 // ----------- VCSBaseEditorPrivate
 
 struct VCSBaseEditorPrivate
@@ -97,13 +130,20 @@ struct VCSBaseEditorPrivate
     VCSBaseEditorPrivate(const VCSBaseEditorParameters *type, QObject *parent);
 
     const VCSBaseEditorParameters *m_parameters;
+
     QAction *m_describeAction;
     QString m_currentChange;
     QString m_source;
+
+    QRegExp m_diffFilePattern;
+    QList<int> m_diffSections; // line number where this section starts
+    int m_cursorLine;
 };
 
-VCSBaseEditorPrivate::VCSBaseEditorPrivate(const VCSBaseEditorParameters *type, QObject *parent)
-    : m_parameters(type), m_describeAction(new QAction(parent))
+VCSBaseEditorPrivate::VCSBaseEditorPrivate(const VCSBaseEditorParameters *type, QObject *parent)  :
+        m_parameters(type),
+        m_describeAction(new QAction(parent)),
+        m_cursorLine(-1)
 {
 }
 
@@ -131,8 +171,13 @@ void VCSBaseEditor::init()
         // Annotation highlighting depends on contents, which is set later on
         connect(this, SIGNAL(textChanged()), this, SLOT(slotActivateAnnotation()));
         break;
-    case DiffOutput:
-        baseTextDocument()->setSyntaxHighlighter(createDiffHighlighter());
+    case DiffOutput: {
+        DiffHighlighter *dh = createDiffHighlighter();
+        baseTextDocument()->setSyntaxHighlighter(dh);
+        d->m_diffFilePattern = dh->filePattern();
+        connect(this, SIGNAL(textChanged()), this, SLOT(slotPopulateDiffBrowser()));
+        connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(slotDiffCursorPositionChanged()));
+    }
         break;
     }
 }
@@ -178,7 +223,87 @@ bool VCSBaseEditor::isModified() const
 
 TextEditor::BaseTextEditorEditable *VCSBaseEditor::createEditableInterface()
 {
-    return new VCSBaseEditorEditable(this, d->m_parameters);
+    if (d->m_parameters->type != DiffOutput)
+        return new VCSBaseEditorEditable(this, d->m_parameters);
+    // Diff: set up diff file browsing
+    VCSBaseDiffEditorEditable *de = new VCSBaseDiffEditorEditable(this, d->m_parameters);
+    QComboBox *diffBrowseComboBox = de->diffFileBrowseComboBox();
+    connect(diffBrowseComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(slotDiffBrowse(int)));
+    return de;
+}
+
+void VCSBaseEditor::slotPopulateDiffBrowser()
+{
+    VCSBaseDiffEditorEditable *de = static_cast<VCSBaseDiffEditorEditable*>(editableInterface());
+    QComboBox *diffBrowseComboBox = de->diffFileBrowseComboBox();
+    diffBrowseComboBox->clear();
+    d->m_diffSections.clear();
+    // Create a list of section line numbers (diffed files)
+    // and populate combo with filenames.
+    const QTextBlock cend = document()->end();
+    int lineNumber = 0;
+    QString lastFileName;
+    for (QTextBlock it = document()->begin(); it != cend; it = it.next(), lineNumber++) {
+        const QString text = it.text();
+        // Check for a new diff section (not repeating the last filename)
+        if (d->m_diffFilePattern.exactMatch(text)) {
+            const QString file = fileNameFromDiffSpecification(it);
+            if (!file.isEmpty() && lastFileName != file) {
+                lastFileName = file;
+                // ignore any headers
+                d->m_diffSections.push_back(d->m_diffSections.empty() ? 0 : lineNumber);
+                diffBrowseComboBox->addItem(QFileInfo(file).fileName());
+            }
+        }
+    }
+}
+
+void VCSBaseEditor::slotDiffBrowse(int index)        
+{
+    // goto diffed file as indicated by index/line number
+    if (index < 0 || index >= d->m_diffSections.size())
+        return;    
+    const int lineNumber = d->m_diffSections.at(index);
+    Core::EditorManager *editorManager = Core::EditorManager::instance();
+    editorManager->addCurrentPositionToNavigationHistory(true);
+    gotoLine(lineNumber + 1, 0); // TextEdit uses 1..n convention
+    editorManager->addCurrentPositionToNavigationHistory();
+}
+
+// Locate a line number in the list of diff sections.
+static int sectionOfLine(int line, const QList<int> &sections)
+{
+    const int sectionCount = sections.size();
+    if (!sectionCount)
+        return -1;
+    // The section at s indicates where the section begins.
+    for (int s = 0; s < sectionCount; s++) {
+        if (line < sections.at(s))
+            return s - 1;
+    }
+    return sectionCount - 1;
+}
+
+void VCSBaseEditor::slotDiffCursorPositionChanged()
+{
+    // Adapt diff file browse combo to new position
+    // if the cursor goes across a file line.
+    QTC_ASSERT(d->m_parameters->type == DiffOutput, return)
+    const int newCursorLine = textCursor().blockNumber();    
+    if (newCursorLine == d->m_cursorLine)
+        return;
+    // Which section does it belong to?
+    d->m_cursorLine = newCursorLine;
+    const int section = sectionOfLine(d->m_cursorLine, d->m_diffSections);
+    if (section != -1) {
+        VCSBaseDiffEditorEditable *de = static_cast<VCSBaseDiffEditorEditable*>(editableInterface());
+        QComboBox *diffBrowseComboBox = de->diffFileBrowseComboBox();
+        if (diffBrowseComboBox->currentIndex() != section) {
+            const bool blocked = diffBrowseComboBox->blockSignals(true);
+            diffBrowseComboBox->setCurrentIndex(section);
+            diffBrowseComboBox->blockSignals(blocked);
+        }
+    }
 }
 
 void VCSBaseEditor::contextMenuEvent(QContextMenuEvent *e)
diff --git a/src/plugins/vcsbase/vcsbaseeditor.h b/src/plugins/vcsbase/vcsbaseeditor.h
index fc1ce94b73dfd5e78ed84a98ced0f62fa635fe3a..29dcb03bf3779c9d1b90777aaa0f2df672eeb208 100644
--- a/src/plugins/vcsbase/vcsbaseeditor.h
+++ b/src/plugins/vcsbase/vcsbaseeditor.h
@@ -142,6 +142,9 @@ public slots:
 private slots:
     void describe();
     void slotActivateAnnotation();
+    void slotPopulateDiffBrowser();
+    void slotDiffBrowse(int);
+    void slotDiffCursorPositionChanged();
 
 private:
     // Implement to return a set of change identifiers in