diff --git a/src/plugins/cpaster/cpasterplugin.cpp b/src/plugins/cpaster/cpasterplugin.cpp
index 572e3f862178a4ec0a773c2ae10f82a23d86bee5..3f2b1e1bd834cf69aaf284dcaec7e9e6fd9dd916 100644
--- a/src/plugins/cpaster/cpasterplugin.cpp
+++ b/src/plugins/cpaster/cpasterplugin.cpp
@@ -43,13 +43,18 @@
 #include <coreplugin/actionmanager/command.h>
 #include <coreplugin/coreconstants.h>
 #include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/mimedatabase.h>
 #include <coreplugin/icore.h>
 #include <coreplugin/messagemanager.h>
 #include <coreplugin/uniqueidmanager.h>
+#include <utils/qtcassert.h>
 #include <texteditor/itexteditor.h>
 
 #include <QtCore/QtPlugin>
 #include <QtCore/QDebug>
+#include <QtCore/QDir>
+#include <QtCore/QFileInfo>
+#include <QtCore/QTemporaryFile>
 #include <QtGui/QAction>
 #include <QtGui/QApplication>
 #include <QtGui/QClipboard>
@@ -130,6 +135,16 @@ void CodepasterPlugin::extensionsInitialized()
 {
 }
 
+void CodepasterPlugin::shutdown()
+{
+    // Delete temporary, fetched files
+    foreach(const QString &fetchedSnippet, m_fetchedSnippets) {
+        QFile file(fetchedSnippet);
+        if (file.exists())
+            file.remove();
+    }
+}
+
 void CodepasterPlugin::post()
 {
     IEditor* editor = EditorManager::instance()->currentEditor();
@@ -250,18 +265,100 @@ void CodepasterPlugin::finishPost(const QString &link)
                                                            m_settingsPage->displayOutput());
 }
 
+// Extract the characters that can be used for a file name from a title
+// "CodePaster.com-34" -> "CodePastercom34".
+static inline QString filePrefixFromTitle(const QString &title)
+{
+    QString rc;
+    const int titleSize = title.size();
+    rc.reserve(titleSize);
+    for (int i = 0; i < titleSize; i++)
+        if (title.at(i).isLetterOrNumber())
+            rc.append(title.at(i));
+    if (rc.isEmpty())
+        rc = QLatin1String("qtcreator");
+    return rc;
+}
+
+// Return a temp file pattern with extension or not
+static inline QString tempFilePattern(const QString &prefix,
+                                      const QString &extension = QString())
+{
+    // Get directory
+    QString pattern = QDir::tempPath();
+    if (!pattern.endsWith(QDir::separator()))
+        pattern.append(QDir::separator());
+    // Prefix, placeholder, extension
+    pattern += prefix;
+    pattern += QLatin1String("_XXXXXX");
+    if (!extension.isEmpty()) {
+       pattern += QLatin1Char('.');
+       pattern += extension;
+    }
+    return pattern;
+}
+
+typedef QSharedPointer<QTemporaryFile> TemporaryFilePtr;
+
+// Write an a temporary file.
+TemporaryFilePtr writeTemporaryFile(const QString &namePattern,
+                                    const QString &contents,
+                                    QString *errorMessage)
+{
+    TemporaryFilePtr tempFile(new QTemporaryFile(namePattern));
+    if (!tempFile->open()) {
+        *errorMessage = QString::fromLatin1("Unable to open temporary file %1").arg(tempFile->errorString());
+        return TemporaryFilePtr();
+    }
+    tempFile->write(contents.toUtf8());
+    tempFile->close();
+    return tempFile;
+}
+
 void CodepasterPlugin::finishFetch(const QString &titleDescription,
                                    const QString &content,
                                    bool error)
 {
-    QString title = titleDescription;
+    Core::MessageManager *messageManager = ICore::instance()->messageManager();
+    // Failure?
     if (error) {
-        ICore::instance()->messageManager()->printToOutputPane(content, true);
-    } else {
-        EditorManager* manager = EditorManager::instance();
-        IEditor* editor = manager->openEditorWithContents(Core::Constants::K_DEFAULT_TEXT_EDITOR_ID, &title, content);
-        manager->activateEditor(editor);
+        messageManager->printToOutputPane(content, true);
+        return;
+    }
+    // Write the file out and do a mime type detection on the content. Note
+    // that for the initial detection, there must not be a suffix
+    // as we want mime type detection to trigger on the content and not on
+    // higher-prioritized suffixes.
+    const QString filePrefix = filePrefixFromTitle(titleDescription);
+    QString errorMessage;
+    TemporaryFilePtr tempFile = writeTemporaryFile(tempFilePattern(filePrefix), content, &errorMessage);
+    if (tempFile.isNull()) {
+        messageManager->printToOutputPane(errorMessage);
+        return;
+    }
+    // If the mime type has a preferred suffix (cpp/h/patch...), use that for
+    // the temporary file. This is to make it more convenient to "Save as"
+    // for the user and also to be able to tell a patch or diff in the VCS plugins
+    // by looking at the file name of FileManager::currentFile() without expensive checking.
+    if (const Core::MimeType mimeType = Core::ICore::instance()->mimeDatabase()->findByFile(QFileInfo(tempFile->fileName()))) {
+        const QString preferredSuffix = mimeType.preferredSuffix();
+        if (!preferredSuffix.isEmpty()) {
+            tempFile = writeTemporaryFile(tempFilePattern(filePrefix, preferredSuffix), content, &errorMessage);
+            if (tempFile.isNull()) {
+                messageManager->printToOutputPane(errorMessage);
+                return;
+            }
+        }
     }
+    // Keep the file and store in list of files to be removed.
+    tempFile->setAutoRemove(false);
+    const QString fileName = tempFile->fileName();
+    m_fetchedSnippets.push_back(fileName);
+    // Open editor with title.
+    Core::IEditor* editor = EditorManager::instance()->openEditor(fileName);
+    QTC_ASSERT(editor, return)
+    editor->setDisplayName(titleDescription);
+    EditorManager::instance()->activateEditor(editor);
 }
 
 Q_EXPORT_PLUGIN(CodepasterPlugin)
diff --git a/src/plugins/cpaster/cpasterplugin.h b/src/plugins/cpaster/cpasterplugin.h
index 9306813d587b86c83ae3faa710fbb2cfd5edb5b8..98e9b39ff1be55a368e975bd15756a696a6e25e6 100644
--- a/src/plugins/cpaster/cpasterplugin.h
+++ b/src/plugins/cpaster/cpasterplugin.h
@@ -32,7 +32,7 @@
 
 #include <extensionsystem/iplugin.h>
 
-#include <QtCore/QList>
+#include <QtCore/QStringList>
 
 QT_BEGIN_NAMESPACE
 class QAction;
@@ -53,8 +53,9 @@ public:
     CodepasterPlugin();
     ~CodepasterPlugin();
 
-    bool initialize(const QStringList &arguments, QString *error_message);
-    void extensionsInitialized();
+    virtual bool initialize(const QStringList &arguments, QString *error_message);
+    virtual void extensionsInitialized();
+    virtual void shutdown();
 
 public slots:
     void post();
@@ -69,6 +70,7 @@ private:
     QAction *m_fetchAction;
     SettingsPage *m_settingsPage;
     QList<Protocol*> m_protocols;
+    QStringList m_fetchedSnippets;
 };
 
 } // namespace CodePaster
diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp
index a2310888c248b97ab2ba0e3ab70b832aa5d59d3c..1a8c9e3b113eeb0ff9a166d6b425d35e273184cb 100644
--- a/src/plugins/git/gitclient.cpp
+++ b/src/plugins/git/gitclient.cpp
@@ -973,6 +973,26 @@ bool GitClient::synchronousCleanList(const QString &workingDirectory,
     return true;
 }
 
+bool GitClient::synchronousApplyPatch(const QString &workingDirectory,
+                                      const QString &file, QString *errorMessage)
+{
+    if (Git::Constants::debug)
+        qDebug() << Q_FUNC_INFO << workingDirectory;
+    QStringList args;
+    args << QLatin1String("apply") << QLatin1String("--whitespace=fix") << file;
+    QByteArray outputText;
+    QByteArray errorText;
+    const bool rc = synchronousGit(workingDirectory, args, &outputText, &errorText);
+    if (rc) {
+        if (!errorText.isEmpty())
+            *errorMessage = tr("There were warnings while applying %1 to %2:\n%3").arg(file, workingDirectory, commandOutputFromLocal8Bit(errorText));
+    } else {
+        *errorMessage = tr("Unable apply patch %1 to %2: %3").arg(file, workingDirectory, commandOutputFromLocal8Bit(errorText));
+        return false;
+    }
+    return true;
+}
+
 // Factory function to create an asynchronous command
 GitCommand *GitClient::createCommand(const QString &workingDirectory,
                              VCSBase::VCSBaseEditor* editor,
diff --git a/src/plugins/git/gitclient.h b/src/plugins/git/gitclient.h
index c81347e32aa76c7a550abd9868ebc6e5dcaca7df..81803fe8b2e7a7898c2d3281b495e226527f1578 100644
--- a/src/plugins/git/gitclient.h
+++ b/src/plugins/git/gitclient.h
@@ -106,6 +106,7 @@ public:
                           const QStringList &files = QStringList(),
                           QString *errorMessage = 0);
     bool synchronousCleanList(const QString &workingDirectory, QStringList *files, QString *errorMessage);
+    bool synchronousApplyPatch(const QString &workingDirectory, const QString &file, QString *errorMessage);
     bool synchronousInit(const QString &workingDirectory);
     bool synchronousCheckoutFiles(const QString &workingDirectory,
                                   QStringList files = QStringList(),
diff --git a/src/plugins/git/gitplugin.cpp b/src/plugins/git/gitplugin.cpp
index ccd876d7cf734163aa74a39ca55baa5ce1c356c8..56ab327b0acbfc6735f76fde20882665a825defa 100644
--- a/src/plugins/git/gitplugin.cpp
+++ b/src/plugins/git/gitplugin.cpp
@@ -50,6 +50,8 @@
 #include <coreplugin/actionmanager/actioncontainer.h>
 #include <coreplugin/actionmanager/command.h>
 #include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/editormanager/ieditor.h>
+#include <coreplugin/filemanager.h>
 
 #include <utils/qtcassert.h>
 #include <utils/parameteraction.h>
@@ -126,6 +128,7 @@ GitPlugin::GitPlugin() :
     m_undoAction(0),
     m_redoAction(0),
     m_menuAction(0),
+    m_applyCurrentFilePatchAction(0),
     m_gitClient(0),
     m_changeSelectionDialog(0),
     m_submitActionTriggered(false)
@@ -386,6 +389,20 @@ bool GitPlugin::initialize(const QStringList &arguments, QString *errorMessage)
                            tr("Log Repository"), QLatin1String("Git.LogRepository"),
                            globalcontext, true, &GitClient::graphLog);
 
+    // Apply current file as patch is handled specially.
+    parameterActionCommand =
+            createParameterAction(actionManager, gitContainer,
+                                  tr("Apply Patch"), tr("Apply \"%1\""),
+                                  QLatin1String("Git.ApplyCurrentFilePatch"),
+                                  globalcontext, true);
+    m_applyCurrentFilePatchAction = parameterActionCommand.first;
+    connect(m_applyCurrentFilePatchAction, SIGNAL(triggered()), this,
+            SLOT(applyCurrentFilePatch()));
+
+    createRepositoryAction(actionManager, gitContainer,
+                           tr("Apply Patch..."), QLatin1String("Git.ApplyPatch"),
+                           globalcontext, true, SLOT(promptApplyPatch()));
+
     createRepositoryAction(actionManager, gitContainer,
                            tr("Undo Repository Changes"), QLatin1String("Git.UndoRepository"),
                            globalcontext, false, SLOT(undoRepositoryChanges()));
@@ -805,6 +822,74 @@ void GitPlugin::cleanRepository(const QString &directory)
     dialog.exec();
 }
 
+// If the file is modified in an editor, make sure it is saved.
+static bool ensureFileSaved(const QString &fileName)
+{
+    const QList<Core::IEditor*> editors = Core::EditorManager::instance()->editorsForFileName(fileName);
+    if (editors.isEmpty())
+        return true;
+    Core::IFile *file = editors.front()->file();
+    if (!file || !file->isModified())
+        return true;
+    Core::FileManager *fm = Core::ICore::instance()->fileManager();
+    bool canceled;
+    QList<Core::IFile *> files;
+    files << file;
+    fm->saveModifiedFiles(files, &canceled);
+    return !canceled;
+}
+
+void GitPlugin::applyCurrentFilePatch()
+{
+    const VCSBase::VCSBasePluginState state = currentState();
+    QTC_ASSERT(state.hasPatchFile() && state.hasTopLevel(), return);
+    const QString patchFile = state.currentPatchFile();
+    if (!ensureFileSaved(patchFile))
+        return;
+    applyPatch(state.topLevel(), patchFile);
+}
+
+void GitPlugin::promptApplyPatch()
+{
+    const VCSBase::VCSBasePluginState state = currentState();
+    QTC_ASSERT(state.hasTopLevel(), return);
+    applyPatch(state.topLevel(), QString());
+}
+
+void GitPlugin::applyPatch(const QString &workingDirectory, QString file)
+{
+    // Ensure user has been notified about pending changes
+    switch (m_gitClient->ensureStash(workingDirectory)) {
+    case GitClient::StashUnchanged:
+    case GitClient::Stashed:
+    case GitClient::NotStashed:
+        break;
+    default:
+        return;
+    }
+    // Prompt for file
+    if (file.isEmpty()) {
+        const QString filter = tr("Patches (*.patch *.diff)");
+        file =  QFileDialog::getOpenFileName(Core::ICore::instance()->mainWindow(),
+                                             tr("Choose patch"),
+                                             QString(), filter);
+        if (file.isEmpty())
+            return;
+    }
+    // Run!
+    VCSBase::VCSBaseOutputWindow *outwin = VCSBase::VCSBaseOutputWindow::instance();
+    QString errorMessage;
+    if (m_gitClient->synchronousApplyPatch(workingDirectory, file, &errorMessage)) {
+        if (errorMessage.isEmpty()) {
+            outwin->append(tr("Patch %1 successfully applied to %2").arg(file, workingDirectory));
+        } else {
+            outwin->append(errorMessage);
+        }
+    } else {
+        outwin->appendError(errorMessage);
+    }
+}
+
 void GitPlugin::stash()
 {
     // Simple stash without prompt, reset repo.
@@ -866,6 +951,8 @@ void GitPlugin::updateActions(VCSBase::VCSBasePlugin::ActionState as)
     const QString fileName = currentState().currentFileName();
     foreach (Utils::ParameterAction *fileAction, m_fileActions)
         fileAction->setParameter(fileName);
+    // If the current file looks like a patch, offer to apply
+    m_applyCurrentFilePatchAction->setParameter(currentState().currentPatchFileDisplayName());
 
     const QString projectName = currentState().currentProjectName();
     foreach (Utils::ParameterAction *projectAction, m_projectActions)
diff --git a/src/plugins/git/gitplugin.h b/src/plugins/git/gitplugin.h
index 413f45d3e9f2fb2a4f7fbc7569c76ff4e33c6563..11c691fa509e864108b994afea37f2189c96db94 100644
--- a/src/plugins/git/gitplugin.h
+++ b/src/plugins/git/gitplugin.h
@@ -115,6 +115,8 @@ private slots:
     void unstageFile();
     void cleanProject();
     void cleanRepository();
+    void applyCurrentFilePatch();
+    void promptApplyPatch();
     void gitClientMemberFuncRepositoryAction();
 
     void showCommit();
@@ -170,6 +172,7 @@ private:
     Core::IEditor *openSubmitEditor(const QString &fileName, const CommitData &cd);
     void cleanCommitMessageFile();
     void cleanRepository(const QString &directory);
+    void applyPatch(const QString &workingDirectory, QString file = QString());
 
     static GitPlugin *m_instance;
     Core::ICore *m_core;
@@ -187,6 +190,7 @@ private:
     QVector<Utils::ParameterAction *> m_fileActions;
     QVector<Utils::ParameterAction *> m_projectActions;
     QVector<QAction *> m_repositoryActions;
+    Utils::ParameterAction *m_applyCurrentFilePatchAction;
 
     GitClient                   *m_gitClient;
     ChangeSelectionDialog       *m_changeSelectionDialog;
diff --git a/src/plugins/vcsbase/VCSBase.mimetypes.xml b/src/plugins/vcsbase/VCSBase.mimetypes.xml
index b5821a75a6105b4ca7b90e80cb4f315ca16dfa35..501171c1eec1c8b9bbe781eec3b2ece08bc221d0 100644
--- a/src/plugins/vcsbase/VCSBase.mimetypes.xml
+++ b/src/plugins/vcsbase/VCSBase.mimetypes.xml
@@ -4,5 +4,14 @@
         <sub-class-of type="text/plain"/>
         <comment>Differences between files</comment>
         <glob pattern="*.patch"/>
+        <glob pattern="*.diff"/>
+        <!-- Find unified diffs from code pasting utilities by checking for "+++ foo.cpp"
+	     Note that this must have a higher priority than any content
+	     rule for C++ as we want diffs to take preference when looking
+	     at a C++ patch.
+	  -->
+        <magic priority="10">
+           <match value="+++ " type="string" offset="0:10000"/>
+        </magic>
     </mime-type>
 </mime-info>
diff --git a/src/plugins/vcsbase/vcsbaseplugin.cpp b/src/plugins/vcsbase/vcsbaseplugin.cpp
index bfa7f80ddecd5b7ecdc9db727df1979bb9fadd05..43321a66374c2d91ce5d07d192ad724cc0c5c952 100644
--- a/src/plugins/vcsbase/vcsbaseplugin.cpp
+++ b/src/plugins/vcsbase/vcsbaseplugin.cpp
@@ -37,6 +37,8 @@
 #include <coreplugin/ifile.h>
 #include <coreplugin/iversioncontrol.h>
 #include <coreplugin/filemanager.h>
+#include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/editormanager/ieditor.h>
 #include <coreplugin/vcsmanager.h>
 #include <projectexplorer/projectexplorer.h>
 #include <projectexplorer/project.h>
@@ -45,6 +47,7 @@
 #include <QtCore/QDebug>
 #include <QtCore/QDir>
 #include <QtCore/QSharedData>
+#include <QtCore/QScopedPointer>
 
 #include <QtGui/QAction>
 #include <QtGui/QMessageBox>
@@ -62,6 +65,7 @@ namespace Internal {
 
 struct State {
     void clearFile();
+    void clearPatchFile();
     void clearProject();
     inline void clear();
 
@@ -73,6 +77,9 @@ struct State {
 
     QString currentFile;
     QString currentFileName;
+    QString currentPatchFile;
+    QString currentPatchFileDisplayName;
+
     QString currentFileDirectory;
     QString currentFileTopLevel;
 
@@ -89,6 +96,12 @@ void State::clearFile()
     currentFileTopLevel.clear();
 }
 
+void State::clearPatchFile()
+{
+    currentPatchFile.clear();
+    currentPatchFileDisplayName.clear();
+}
+
 void State::clearProject()
 {
     currentProjectPath.clear();
@@ -99,6 +112,7 @@ void State::clearProject()
 void State::clear()
 {
     clearFile();
+    clearPatchFile();
     clearProject();
 }
 
@@ -106,6 +120,7 @@ bool State::equals(const State &rhs) const
 {
     return currentFile == rhs.currentFile
             && currentFileName == rhs.currentFileName
+            && currentPatchFile == rhs.currentPatchFile
             && currentFileTopLevel == rhs.currentFileTopLevel
             && currentProjectPath == rhs.currentProjectPath
             && currentProjectName == rhs.currentProjectName
@@ -168,6 +183,14 @@ StateListener::StateListener(QObject *parent) :
                 this, SLOT(slotStateChanged()));
 }
 
+static inline QString displayNameOfEditor(const QString &fileName)
+{
+    const QList<Core::IEditor*> editors = Core::EditorManager::instance()->editorsForFileName(fileName);
+    if (!editors.isEmpty())
+        return editors.front()->displayName();
+    return QString();
+}
+
 void StateListener::slotStateChanged()
 {
     const ProjectExplorer::ProjectExplorerPlugin *pe = ProjectExplorer::ProjectExplorerPlugin::instance();
@@ -179,16 +202,35 @@ void StateListener::slotStateChanged()
     // folder?
     State state;
     state.currentFile = core->fileManager()->currentFile();
+    QScopedPointer<QFileInfo> currentFileInfo; // Instantiate QFileInfo only once if required.
     if (!state.currentFile.isEmpty()) {
-        if (state.currentFile.contains(QLatin1Char('#')) || state.currentFile.startsWith(QDir::tempPath()))
+        const bool isTempFile = state.currentFile.startsWith(QDir::tempPath());
+        // Quick check: Does it look like a patch?
+        const bool isPatch = state.currentFile.endsWith(QLatin1String(".patch"))
+                             || state.currentFile.endsWith(QLatin1String(".diff"));
+        if (isPatch) {
+            // Patch: Figure out a name to display. If it is a temp file, it could be
+            // Codepaster. Use the display name of the editor.
+            state.currentPatchFile = state.currentFile;
+            if (isTempFile)
+                state.currentPatchFileDisplayName = displayNameOfEditor(state.currentPatchFile);
+            if (state.currentPatchFileDisplayName.isEmpty()) {
+                currentFileInfo.reset(new QFileInfo(state.currentFile));
+                state.currentPatchFileDisplayName = currentFileInfo->fileName();
+            }
+        }
+        // For actual version control operations on it:
+        // Do not show temporary files and project folders ('#')
+        if (isTempFile || state.currentFile.contains(QLatin1Char('#')))
             state.currentFile.clear();
     }
     // Get the file and its control. Do not use the file unless we find one
     Core::IVersionControl *fileControl = 0;
     if (!state.currentFile.isEmpty()) {
-        const QFileInfo fi(state.currentFile);
-        state.currentFileDirectory = fi.absolutePath();
-        state.currentFileName = fi.fileName();
+        if (currentFileInfo.isNull())
+            currentFileInfo.reset(new QFileInfo(state.currentFile));
+        state.currentFileDirectory = currentFileInfo->absolutePath();
+        state.currentFileName = currentFileInfo->fileName();
         fileControl = vcsManager->findVersionControlForDirectory(state.currentFileDirectory,
                                                                  &state.currentFileTopLevel);
         if (!fileControl)
@@ -212,6 +254,8 @@ void StateListener::slotStateChanged()
     }
     // Assemble state and emit signal.
     Core::IVersionControl *vc = state.currentFile.isEmpty() ? projectControl : fileControl;
+    if (!vc) // Need a repository to patch
+        state.clearPatchFile();
     if (debug)
         qDebug() << state << (vc ? vc->displayName() : QString(QLatin1String("No version control")));
     emit stateChanged(state, vc);
@@ -269,6 +313,16 @@ QString VCSBasePluginState::relativeCurrentFile() const
     return QDir(data->m_state.currentFileTopLevel).relativeFilePath(data->m_state.currentFile);
 }
 
+QString VCSBasePluginState::currentPatchFile() const
+{
+    return data->m_state.currentPatchFile;
+}
+
+QString VCSBasePluginState::currentPatchFileDisplayName() const
+{
+    return data->m_state.currentPatchFileDisplayName;
+}
+
 QString VCSBasePluginState::currentProjectPath() const
 {
     return data->m_state.currentProjectPath;
@@ -333,6 +387,11 @@ bool VCSBasePluginState::hasFile() const
     return data->m_state.hasFile();
 }
 
+bool VCSBasePluginState::hasPatchFile() const
+{
+    return !data->m_state.currentPatchFile.isEmpty();
+}
+
 bool VCSBasePluginState::hasProject() const
 {
     return data->m_state.hasProject();
diff --git a/src/plugins/vcsbase/vcsbaseplugin.h b/src/plugins/vcsbase/vcsbaseplugin.h
index 49e75780c980becc45b1a535dcfcdc5a328fec4c..de9e8412923327fd52ad11487140bee7b3bbdd2d 100644
--- a/src/plugins/vcsbase/vcsbaseplugin.h
+++ b/src/plugins/vcsbase/vcsbaseplugin.h
@@ -68,6 +68,9 @@ class VCSBasePlugin;
  * according to the new state. This is done centrally to avoid
  * single plugins repeatedly invoking searches/QFileInfo on files,
  * etc.
+ * Independently, there are accessors for current patch files, which return
+ * a file name if the current file could be a patch file which could be applied
+ * and a repository exists.
  *
  * If current file/project are managed
  * by different version controls, the project is discarded and only
@@ -92,6 +95,7 @@ public:
 
     bool isEmpty() const;
     bool hasFile() const;
+    bool hasPatchFile() const;
     bool hasProject() const;
     bool hasTopLevel() const;
 
@@ -103,6 +107,11 @@ public:
     // Convenience: Returns file relative to top level.
     QString relativeCurrentFile() const;
 
+    // If the current file looks like a patch and there is a top level,
+    // it will end up here (for VCS that offer patch functionality).
+    QString currentPatchFile() const;
+    QString currentPatchFileDisplayName() const;
+
     // Current project.
     QString currentProjectPath() const;
     QString currentProjectName() const;