forked from qt-creator/qt-creator
VcsBase: Create common base diff editor controller
Reuse it in subversion and git plugins. It makes subversion diff more asynchronous than before. Make VcsBase plugin dependand on DiffEditor plugin. Change-Id: Iafea2941b890a95a269362e022af2dc03cdea550 Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
This commit is contained in:
@@ -43,7 +43,6 @@
|
||||
#include <coreplugin/idocument.h>
|
||||
#include <coreplugin/iversioncontrol.h>
|
||||
#include <coreplugin/vcsmanager.h>
|
||||
#include <coreplugin/progressmanager/progressmanager.h>
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/asconst.h>
|
||||
@@ -54,9 +53,9 @@
|
||||
#include <utils/qtcprocess.h>
|
||||
#include <utils/synchronousprocess.h>
|
||||
#include <utils/temporaryfile.h>
|
||||
#include <utils/runextensions.h>
|
||||
|
||||
#include <vcsbase/submitfilemodel.h>
|
||||
#include <vcsbase/vcsbasediffeditorcontroller.h>
|
||||
#include <vcsbase/vcsbaseeditor.h>
|
||||
#include <vcsbase/vcsbaseeditorconfig.h>
|
||||
#include <vcsbase/vcsbaseplugin.h>
|
||||
@@ -112,138 +111,31 @@ const unsigned silentFlags = unsigned(VcsCommand::SuppressCommandLogging
|
||||
| VcsCommand::SuppressStdErr
|
||||
| VcsCommand::SuppressFailMessage);
|
||||
|
||||
static void readPatch(QFutureInterface<QList<FileData>> &futureInterface,
|
||||
const QString &patch)
|
||||
{
|
||||
bool ok;
|
||||
const QList<FileData> &fileDataList = DiffUtils::readPatch(patch, &ok);
|
||||
futureInterface.reportResult(fileDataList);
|
||||
}
|
||||
|
||||
/////////////////////////////////////
|
||||
|
||||
class BaseController : public DiffEditorController
|
||||
class GitDiffEditorController : public VcsBaseDiffEditorController
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
BaseController(IDocument *document, const QString &dir);
|
||||
~BaseController();
|
||||
GitDiffEditorController(IDocument *document, const QString &workingDirectory);
|
||||
|
||||
protected:
|
||||
void runCommand(const QList<QStringList> &args, QTextCodec *codec = 0);
|
||||
virtual void processCommandOutput(const QString &output);
|
||||
void runCommand(const QList<QStringList> &args, QTextCodec *codec = nullptr);
|
||||
|
||||
QStringList addConfigurationArguments(const QStringList &args) const;
|
||||
QStringList addHeadWhenCommandInProgress() const;
|
||||
|
||||
void setStartupFile(const QString &startupFile) { m_startupFile = startupFile; }
|
||||
QString startupFile() const { return m_startupFile; }
|
||||
QString directory() const { return m_directory; }
|
||||
|
||||
private:
|
||||
void processDiff(const QString &patch);
|
||||
void storeOutput(const QString &output);
|
||||
void cancelReload();
|
||||
void commandFinished(bool success);
|
||||
void processingFinished();
|
||||
|
||||
const QString m_directory;
|
||||
QString m_startupFile;
|
||||
QString m_output;
|
||||
QPointer<VcsCommand> m_command;
|
||||
QFutureWatcher<QList<FileData>> m_processWatcher;
|
||||
};
|
||||
|
||||
BaseController::BaseController(IDocument *document, const QString &dir) :
|
||||
DiffEditorController(document),
|
||||
m_directory(dir),
|
||||
m_command(0)
|
||||
GitDiffEditorController::GitDiffEditorController(IDocument *document, const QString &workingDirectory) :
|
||||
VcsBaseDiffEditorController(document, GitPlugin::client(), workingDirectory)
|
||||
{
|
||||
connect(&m_processWatcher, &QFutureWatcher<QList<FileData>>::finished,
|
||||
this, &BaseController::processingFinished);
|
||||
}
|
||||
|
||||
BaseController::~BaseController()
|
||||
void GitDiffEditorController::runCommand(const QList<QStringList> &args, QTextCodec *codec)
|
||||
{
|
||||
cancelReload();
|
||||
VcsBaseDiffEditorController::runCommand(args, diffExecutionFlags(), codec);
|
||||
}
|
||||
|
||||
void BaseController::cancelReload()
|
||||
{
|
||||
if (m_command) {
|
||||
m_command->disconnect();
|
||||
m_command->cancel();
|
||||
m_command.clear();
|
||||
}
|
||||
|
||||
if (m_processWatcher.future().isRunning()) {
|
||||
m_processWatcher.future().cancel();
|
||||
m_processWatcher.setFuture(QFuture<QList<FileData>>());
|
||||
}
|
||||
m_output = QString();
|
||||
}
|
||||
|
||||
void BaseController::commandFinished(bool success)
|
||||
{
|
||||
if (m_command)
|
||||
m_command.clear();
|
||||
|
||||
if (!success) {
|
||||
cancelReload();
|
||||
reloadFinished(success);
|
||||
return;
|
||||
}
|
||||
|
||||
processCommandOutput(m_output);
|
||||
}
|
||||
|
||||
void BaseController::runCommand(const QList<QStringList> &args, QTextCodec *codec)
|
||||
{
|
||||
cancelReload();
|
||||
|
||||
m_command = new VcsCommand(directory(), GitPlugin::client()->processEnvironment());
|
||||
m_command->setCodec(codec ? codec : EditorManager::defaultTextCodec());
|
||||
connect(m_command.data(), &VcsCommand::stdOutText, this, &BaseController::storeOutput);
|
||||
connect(m_command.data(), &VcsCommand::finished, this, &BaseController::commandFinished);
|
||||
m_command->addFlags(diffExecutionFlags());
|
||||
|
||||
for (const QStringList &arg : args) {
|
||||
QTC_ASSERT(!arg.isEmpty(), continue);
|
||||
|
||||
m_command->addJob(GitPlugin::client()->vcsBinary(), arg, GitPlugin::client()->vcsTimeoutS());
|
||||
}
|
||||
|
||||
m_command->execute();
|
||||
}
|
||||
|
||||
void BaseController::storeOutput(const QString &output)
|
||||
{
|
||||
m_output = output;
|
||||
}
|
||||
|
||||
void BaseController::processCommandOutput(const QString &output)
|
||||
{
|
||||
processDiff(output);
|
||||
}
|
||||
|
||||
void BaseController::processDiff(const QString &patch)
|
||||
{
|
||||
m_processWatcher.setFuture(Utils::runAsync(&readPatch, patch));
|
||||
|
||||
Core::ProgressManager::addTask(m_processWatcher.future(),
|
||||
tr("Processing diff"), "DiffEditor");
|
||||
}
|
||||
|
||||
void BaseController::processingFinished()
|
||||
{
|
||||
const QList<FileData> fileDataList = m_processWatcher.future().result();
|
||||
|
||||
setDiffFiles(fileDataList, directory(), startupFile());
|
||||
reloadFinished(true);
|
||||
}
|
||||
|
||||
QStringList BaseController::addConfigurationArguments(const QStringList &args) const
|
||||
QStringList GitDiffEditorController::addConfigurationArguments(const QStringList &args) const
|
||||
{
|
||||
QTC_ASSERT(!args.isEmpty(), return args);
|
||||
|
||||
@@ -261,23 +153,23 @@ QStringList BaseController::addConfigurationArguments(const QStringList &args) c
|
||||
return realArgs;
|
||||
}
|
||||
|
||||
QStringList BaseController::addHeadWhenCommandInProgress() const
|
||||
QStringList GitDiffEditorController::addHeadWhenCommandInProgress() const
|
||||
{
|
||||
// This is workaround for lack of support for merge commits and resolving conflicts,
|
||||
// we compare the current state of working tree to the HEAD of current branch
|
||||
// instead of showing unsupported combined diff format.
|
||||
GitClient::CommandInProgress commandInProgress = GitPlugin::client()->checkCommandInProgress(directory());
|
||||
GitClient::CommandInProgress commandInProgress = GitPlugin::client()->checkCommandInProgress(workingDirectory());
|
||||
if (commandInProgress != GitClient::NoCommand)
|
||||
return {HEAD};
|
||||
return QStringList();
|
||||
}
|
||||
|
||||
class RepositoryDiffController : public BaseController
|
||||
class RepositoryDiffController : public GitDiffEditorController
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
RepositoryDiffController(IDocument *document, const QString &dir) :
|
||||
BaseController(document, dir)
|
||||
GitDiffEditorController(document, dir)
|
||||
{ }
|
||||
|
||||
void reload() override;
|
||||
@@ -290,12 +182,12 @@ void RepositoryDiffController::reload()
|
||||
runCommand(QList<QStringList>() << addConfigurationArguments(args));
|
||||
}
|
||||
|
||||
class FileDiffController : public BaseController
|
||||
class FileDiffController : public GitDiffEditorController
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
FileDiffController(IDocument *document, const QString &dir, const QString &fileName) :
|
||||
BaseController(document, dir),
|
||||
GitDiffEditorController(document, dir),
|
||||
m_fileName(fileName)
|
||||
{ }
|
||||
|
||||
@@ -314,13 +206,13 @@ void FileDiffController::reload()
|
||||
runCommand(QList<QStringList>() << addConfigurationArguments(args));
|
||||
}
|
||||
|
||||
class FileListDiffController : public BaseController
|
||||
class FileListDiffController : public GitDiffEditorController
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
FileListDiffController(IDocument *document, const QString &dir,
|
||||
const QStringList &stagedFiles, const QStringList &unstagedFiles) :
|
||||
BaseController(document, dir),
|
||||
GitDiffEditorController(document, dir),
|
||||
m_stagedFiles(stagedFiles),
|
||||
m_unstagedFiles(unstagedFiles)
|
||||
{ }
|
||||
@@ -351,13 +243,13 @@ void FileListDiffController::reload()
|
||||
runCommand(argLists);
|
||||
}
|
||||
|
||||
class ProjectDiffController : public BaseController
|
||||
class ProjectDiffController : public GitDiffEditorController
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ProjectDiffController(IDocument *document, const QString &dir,
|
||||
const QStringList &projectPaths) :
|
||||
BaseController(document, dir),
|
||||
GitDiffEditorController(document, dir),
|
||||
m_projectPaths(projectPaths)
|
||||
{ }
|
||||
|
||||
@@ -374,13 +266,13 @@ void ProjectDiffController::reload()
|
||||
runCommand(QList<QStringList>() << addConfigurationArguments(args));
|
||||
}
|
||||
|
||||
class BranchDiffController : public BaseController
|
||||
class BranchDiffController : public GitDiffEditorController
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
BranchDiffController(IDocument *document, const QString &dir,
|
||||
const QString &branch) :
|
||||
BaseController(document, dir),
|
||||
GitDiffEditorController(document, dir),
|
||||
m_branch(branch)
|
||||
{ }
|
||||
|
||||
@@ -397,12 +289,12 @@ void BranchDiffController::reload()
|
||||
runCommand(QList<QStringList>() << addConfigurationArguments(args));
|
||||
}
|
||||
|
||||
class ShowController : public BaseController
|
||||
class ShowController : public GitDiffEditorController
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ShowController(IDocument *document, const QString &dir, const QString &id) :
|
||||
BaseController(document, dir),
|
||||
GitDiffEditorController(document, dir),
|
||||
m_id(id),
|
||||
m_state(Idle)
|
||||
{ }
|
||||
@@ -421,7 +313,7 @@ void ShowController::reload()
|
||||
// stage 1
|
||||
m_state = GettingDescription;
|
||||
const QStringList args = {"show", "-s", noColorOption, showFormatC, m_id};
|
||||
runCommand(QList<QStringList>() << args, GitPlugin::client()->encoding(directory(), "i18n.commitEncoding"));
|
||||
runCommand(QList<QStringList>() << args, GitPlugin::client()->encoding(workingDirectory(), "i18n.commitEncoding"));
|
||||
setStartupFile(VcsBasePlugin::source(document()));
|
||||
}
|
||||
|
||||
@@ -429,7 +321,7 @@ void ShowController::processCommandOutput(const QString &output)
|
||||
{
|
||||
QTC_ASSERT(m_state != Idle, return);
|
||||
if (m_state == GettingDescription) {
|
||||
setDescription(GitPlugin::client()->extendedShowDescription(directory(), output));
|
||||
setDescription(GitPlugin::client()->extendedShowDescription(workingDirectory(), output));
|
||||
// stage 2
|
||||
m_state = GettingDiff;
|
||||
const QStringList args = {"show", "--format=format:", // omit header, already generated
|
||||
@@ -437,7 +329,7 @@ void ShowController::processCommandOutput(const QString &output)
|
||||
runCommand(QList<QStringList>() << addConfigurationArguments(args));
|
||||
} else if (m_state == GettingDiff) {
|
||||
m_state = Idle;
|
||||
BaseController::processCommandOutput(output);
|
||||
GitDiffEditorController::processCommandOutput(output);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -30,6 +30,7 @@
|
||||
|
||||
#include <vcsbase/vcscommand.h>
|
||||
#include <vcsbase/vcsbaseconstants.h>
|
||||
#include <vcsbase/vcsbasediffeditorcontroller.h>
|
||||
#include <vcsbase/vcsbaseeditor.h>
|
||||
#include <vcsbase/vcsbaseeditorconfig.h>
|
||||
#include <vcsbase/vcsbaseplugin.h>
|
||||
@@ -167,46 +168,40 @@ QStringList SubversionClient::escapeFiles(const QStringList &files)
|
||||
return Utils::transform(files, &SubversionClient::escapeFile);
|
||||
}
|
||||
|
||||
class DiffController : public DiffEditorController
|
||||
class SubversionDiffEditorController : public VcsBaseDiffEditorController
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
DiffController(IDocument *document, const SubversionClient *client, const QString &directory);
|
||||
SubversionDiffEditorController(IDocument *document,
|
||||
const QString &workingDirectory);
|
||||
|
||||
void setFilesList(const QStringList &filesList);
|
||||
void setChangeNumber(int changeNumber);
|
||||
|
||||
protected:
|
||||
void reload() override;
|
||||
|
||||
private slots:
|
||||
void slotTextualDiffOutputReceived(const QString &contents);
|
||||
void processCommandOutput(const QString &output) override;
|
||||
|
||||
private:
|
||||
QString getDescription() const;
|
||||
void postCollectTextualDiffOutput();
|
||||
QProcessEnvironment processEnvironment() const;
|
||||
void requestDescription();
|
||||
void requestDiff();
|
||||
|
||||
const SubversionClient *m_client;
|
||||
QString m_workingDirectory;
|
||||
enum State { Idle, GettingDescription, GettingDiff };
|
||||
State m_state;
|
||||
QStringList m_filesList;
|
||||
int m_changeNumber = 0;
|
||||
};
|
||||
|
||||
DiffController::DiffController(IDocument *document, const SubversionClient *client, const QString &directory) :
|
||||
DiffEditorController(document),
|
||||
m_client(client),
|
||||
m_workingDirectory(directory)
|
||||
SubversionDiffEditorController::SubversionDiffEditorController(
|
||||
IDocument *document,
|
||||
const QString &workingDirectory)
|
||||
: VcsBaseDiffEditorController(document, SubversionPlugin::instance()->client(), workingDirectory)
|
||||
, m_state(Idle)
|
||||
{
|
||||
forceContextLineCount(3); // SVN can not change that when using internal diff
|
||||
}
|
||||
|
||||
QProcessEnvironment DiffController::processEnvironment() const
|
||||
{
|
||||
return m_client->processEnvironment();
|
||||
}
|
||||
|
||||
void DiffController::setFilesList(const QStringList &filesList)
|
||||
void SubversionDiffEditorController::setFilesList(const QStringList &filesList)
|
||||
{
|
||||
if (isReloading())
|
||||
return;
|
||||
@@ -214,7 +209,7 @@ void DiffController::setFilesList(const QStringList &filesList)
|
||||
m_filesList = SubversionClient::escapeFiles(filesList);
|
||||
}
|
||||
|
||||
void DiffController::setChangeNumber(int changeNumber)
|
||||
void SubversionDiffEditorController::setChangeNumber(int changeNumber)
|
||||
{
|
||||
if (isReloading())
|
||||
return;
|
||||
@@ -222,33 +217,24 @@ void DiffController::setChangeNumber(int changeNumber)
|
||||
m_changeNumber = qMax(changeNumber, 0);
|
||||
}
|
||||
|
||||
QString DiffController::getDescription() const
|
||||
void SubversionDiffEditorController::requestDescription()
|
||||
{
|
||||
m_state = GettingDescription;
|
||||
|
||||
QStringList args(QLatin1String("log"));
|
||||
args << SubversionClient::addAuthenticationOptions(m_client->settings());
|
||||
args << SubversionClient::addAuthenticationOptions(client()->settings());
|
||||
args << QLatin1String("-r");
|
||||
args << QString::number(m_changeNumber);
|
||||
const SubversionResponse logResponse =
|
||||
SubversionPlugin::instance()->runSvn(m_workingDirectory, args,
|
||||
m_client->vcsTimeoutS(),
|
||||
VcsCommand::SshPasswordPrompt);
|
||||
|
||||
if (logResponse.error)
|
||||
return QString();
|
||||
|
||||
return logResponse.stdOut;
|
||||
runCommand(QList<QStringList>() << args, VcsCommand::SshPasswordPrompt);
|
||||
}
|
||||
|
||||
void DiffController::postCollectTextualDiffOutput()
|
||||
void SubversionDiffEditorController::requestDiff()
|
||||
{
|
||||
auto command = new VcsCommand(m_workingDirectory, processEnvironment());
|
||||
command->setCodec(EditorManager::defaultTextCodec());
|
||||
connect(command, &VcsCommand::stdOutText, this, &DiffController::slotTextualDiffOutputReceived);
|
||||
// command->addFlags(diffExecutionFlags());
|
||||
m_state = GettingDiff;
|
||||
|
||||
QStringList args;
|
||||
args << QLatin1String("diff");
|
||||
args << m_client->addAuthenticationOptions(m_client->settings());
|
||||
args << SubversionClient::addAuthenticationOptions(client()->settings());
|
||||
args << QLatin1String("--internal-diff");
|
||||
if (ignoreWhitespace())
|
||||
args << QLatin1String("-x") << QLatin1String("-uw");
|
||||
@@ -258,40 +244,43 @@ void DiffController::postCollectTextualDiffOutput()
|
||||
} else {
|
||||
args << m_filesList;
|
||||
}
|
||||
|
||||
command->addJob(m_client->vcsBinary(), args, m_client->vcsTimeoutS());
|
||||
command->execute();
|
||||
runCommand(QList<QStringList>() << args, 0);
|
||||
}
|
||||
|
||||
void DiffController::slotTextualDiffOutputReceived(const QString &contents)
|
||||
void SubversionDiffEditorController::reload()
|
||||
{
|
||||
bool ok;
|
||||
QList<FileData> fileDataList
|
||||
= DiffUtils::readPatch(contents, &ok);
|
||||
setDiffFiles(fileDataList, m_workingDirectory);
|
||||
|
||||
reloadFinished(true);
|
||||
if (m_changeNumber) {
|
||||
requestDescription();
|
||||
} else {
|
||||
requestDiff();
|
||||
}
|
||||
}
|
||||
|
||||
void DiffController::reload()
|
||||
void SubversionDiffEditorController::processCommandOutput(const QString &output)
|
||||
{
|
||||
const QString description = m_changeNumber
|
||||
? getDescription() : QString();
|
||||
postCollectTextualDiffOutput();
|
||||
setDescription(description);
|
||||
QTC_ASSERT(m_state != Idle, return);
|
||||
if (m_state == GettingDescription) {
|
||||
setDescription(output);
|
||||
|
||||
requestDiff();
|
||||
} else if (m_state == GettingDiff) {
|
||||
m_state = Idle;
|
||||
VcsBaseDiffEditorController::processCommandOutput(output);
|
||||
}
|
||||
}
|
||||
|
||||
DiffController *SubversionClient::findOrCreateDiffEditor(const QString &documentId,
|
||||
SubversionDiffEditorController *SubversionClient::findOrCreateDiffEditor(const QString &documentId,
|
||||
const QString &source,
|
||||
const QString &title,
|
||||
const QString &workingDirectory) const
|
||||
{
|
||||
IDocument *document = DiffEditorController::findOrCreateDocument(documentId, title);
|
||||
DiffController *controller = qobject_cast<DiffController *>(
|
||||
SubversionDiffEditorController *controller = qobject_cast<SubversionDiffEditorController *>(
|
||||
DiffEditorController::controller(document));
|
||||
if (!controller)
|
||||
controller = new DiffController(document, this, workingDirectory);
|
||||
controller = new SubversionDiffEditorController(document, workingDirectory);
|
||||
VcsBasePlugin::setSource(document, source);
|
||||
EditorManager::activateEditorForDocument(document);
|
||||
return controller;
|
||||
}
|
||||
|
||||
@@ -304,7 +293,7 @@ void SubversionClient::diff(const QString &workingDirectory, const QStringList &
|
||||
+ QLatin1String(".Diff.") + VcsBaseEditor::getTitleId(workingDirectory, files);
|
||||
const QString title = vcsEditorTitle(vcsCmdString, documentId);
|
||||
|
||||
DiffController *controller = findOrCreateDiffEditor(documentId, workingDirectory, title,
|
||||
SubversionDiffEditorController *controller = findOrCreateDiffEditor(documentId, workingDirectory, title,
|
||||
workingDirectory);
|
||||
controller->setFilesList(files);
|
||||
controller->requestReload();
|
||||
@@ -335,7 +324,7 @@ void SubversionClient::describe(const QString &workingDirectory, int changeNumbe
|
||||
QStringList(),
|
||||
QString::number(changeNumber));
|
||||
|
||||
DiffController *controller = findOrCreateDiffEditor(documentId, workingDirectory, title, workingDirectory);
|
||||
SubversionDiffEditorController *controller = findOrCreateDiffEditor(documentId, workingDirectory, title, workingDirectory);
|
||||
controller->setChangeNumber(changeNumber);
|
||||
controller->requestReload();
|
||||
}
|
||||
|
@@ -35,7 +35,7 @@ namespace Subversion {
|
||||
namespace Internal {
|
||||
|
||||
class SubversionSettings;
|
||||
class DiffController;
|
||||
class SubversionDiffEditorController;
|
||||
|
||||
class SubversionClient : public VcsBase::VcsBaseClient
|
||||
{
|
||||
@@ -78,7 +78,7 @@ protected:
|
||||
Core::Id vcsEditorKind(VcsCommandTag cmd) const override;
|
||||
|
||||
private:
|
||||
DiffController *findOrCreateDiffEditor(const QString &documentId, const QString &source,
|
||||
SubversionDiffEditorController *findOrCreateDiffEditor(const QString &documentId, const QString &source,
|
||||
const QString &title, const QString &workingDirectory) const;
|
||||
|
||||
mutable Utils::FileName m_svnVersionBinary;
|
||||
|
@@ -27,7 +27,8 @@ HEADERS += vcsbase_global.h \
|
||||
vcsbaseclientsettings.h \
|
||||
vcsbaseeditorconfig.h \
|
||||
submitfieldwidget.h \
|
||||
submiteditorwidget.h
|
||||
submiteditorwidget.h \
|
||||
vcsbasediffeditorcontroller.h
|
||||
|
||||
SOURCES += vcsplugin.cpp \
|
||||
vcsbaseplugin.cpp \
|
||||
@@ -54,7 +55,8 @@ SOURCES += vcsplugin.cpp \
|
||||
vcsbaseclientsettings.cpp \
|
||||
vcsbaseeditorconfig.cpp \
|
||||
submitfieldwidget.cpp \
|
||||
submiteditorwidget.cpp
|
||||
submiteditorwidget.cpp \
|
||||
vcsbasediffeditorcontroller.cpp
|
||||
|
||||
RESOURCES += vcsbase.qrc
|
||||
|
||||
|
@@ -12,6 +12,7 @@ QtcPlugin {
|
||||
Depends { name: "TextEditor" }
|
||||
Depends { name: "ProjectExplorer" }
|
||||
Depends { name: "CppTools" }
|
||||
Depends { name: "DiffEditor" }
|
||||
|
||||
pluginRecommends: [
|
||||
"CodePaster"
|
||||
@@ -53,6 +54,8 @@ QtcPlugin {
|
||||
"vcsbaseclientsettings.cpp",
|
||||
"vcsbaseclientsettings.h",
|
||||
"vcsbaseconstants.h",
|
||||
"vcsbasediffeditorcontroller.cpp",
|
||||
"vcsbasediffeditorcontroller.h",
|
||||
"vcsbaseeditor.cpp",
|
||||
"vcsbaseeditor.h",
|
||||
"vcsbaseeditorconfig.cpp",
|
||||
|
@@ -8,6 +8,7 @@ QTC_PLUGIN_DEPENDS += \
|
||||
coreplugin \
|
||||
texteditor \
|
||||
projectexplorer \
|
||||
cpptools
|
||||
cpptools \
|
||||
diffeditor
|
||||
QTC_PLUGIN_RECOMMENDS += \
|
||||
cpaster
|
||||
|
195
src/plugins/vcsbase/vcsbasediffeditorcontroller.cpp
Normal file
195
src/plugins/vcsbase/vcsbasediffeditorcontroller.cpp
Normal file
@@ -0,0 +1,195 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2017 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "vcsbasediffeditorcontroller.h"
|
||||
#include "vcsbaseclient.h"
|
||||
#include "vcscommand.h"
|
||||
|
||||
#include <coreplugin/editormanager/editormanager.h>
|
||||
#include <coreplugin/progressmanager/progressmanager.h>
|
||||
#include <diffeditor/diffutils.h>
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/runextensions.h>
|
||||
|
||||
#include <QPointer>
|
||||
|
||||
using namespace DiffEditor;
|
||||
using namespace Core;
|
||||
|
||||
namespace VcsBase {
|
||||
|
||||
static void readPatch(QFutureInterface<QList<FileData>> &futureInterface,
|
||||
const QString &patch)
|
||||
{
|
||||
bool ok;
|
||||
const QList<FileData> &fileDataList = DiffUtils::readPatch(patch, &ok);
|
||||
futureInterface.reportResult(fileDataList);
|
||||
}
|
||||
|
||||
class VcsBaseDiffEditorControllerPrivate
|
||||
{
|
||||
public:
|
||||
VcsBaseDiffEditorControllerPrivate(VcsBaseDiffEditorController *controller,
|
||||
VcsBaseClientImpl *client,
|
||||
const QString &workingDirectory);
|
||||
~VcsBaseDiffEditorControllerPrivate();
|
||||
|
||||
void processingFinished();
|
||||
void processDiff(const QString &patch);
|
||||
void cancelReload();
|
||||
void commandFinished(bool success);
|
||||
|
||||
VcsBaseDiffEditorController *q;
|
||||
VcsBaseClientImpl *m_client;
|
||||
const QString m_directory;
|
||||
QString m_startupFile;
|
||||
QString m_output;
|
||||
QPointer<VcsCommand> m_command;
|
||||
QFutureWatcher<QList<FileData>> m_processWatcher;
|
||||
};
|
||||
|
||||
VcsBaseDiffEditorControllerPrivate::VcsBaseDiffEditorControllerPrivate(VcsBaseDiffEditorController *controller,
|
||||
VcsBaseClientImpl *client,
|
||||
const QString &workingDirectory)
|
||||
: q(controller)
|
||||
, m_client(client)
|
||||
, m_directory(workingDirectory)
|
||||
{
|
||||
QObject::connect(&m_processWatcher, &QFutureWatcher<QList<FileData>>::finished, q,
|
||||
[this] () { processingFinished(); });
|
||||
}
|
||||
|
||||
VcsBaseDiffEditorControllerPrivate::~VcsBaseDiffEditorControllerPrivate()
|
||||
{
|
||||
cancelReload();
|
||||
}
|
||||
|
||||
void VcsBaseDiffEditorControllerPrivate::processingFinished()
|
||||
{
|
||||
const QList<FileData> fileDataList = m_processWatcher.future().result();
|
||||
|
||||
q->setDiffFiles(fileDataList, q->workingDirectory(), q->startupFile());
|
||||
q->reloadFinished(true);
|
||||
}
|
||||
|
||||
void VcsBaseDiffEditorControllerPrivate::processDiff(const QString &patch)
|
||||
{
|
||||
m_processWatcher.setFuture(Utils::runAsync(&readPatch, patch));
|
||||
|
||||
ProgressManager::addTask(m_processWatcher.future(),
|
||||
q->tr("Processing diff"), "DiffEditor");
|
||||
}
|
||||
|
||||
void VcsBaseDiffEditorControllerPrivate::cancelReload()
|
||||
{
|
||||
if (m_command) {
|
||||
m_command->disconnect();
|
||||
m_command->cancel();
|
||||
m_command.clear();
|
||||
}
|
||||
|
||||
if (m_processWatcher.future().isRunning()) {
|
||||
m_processWatcher.future().cancel();
|
||||
m_processWatcher.setFuture(QFuture<QList<FileData>>());
|
||||
}
|
||||
m_output = QString();
|
||||
}
|
||||
|
||||
void VcsBaseDiffEditorControllerPrivate::commandFinished(bool success)
|
||||
{
|
||||
if (m_command)
|
||||
m_command.clear();
|
||||
|
||||
if (!success) {
|
||||
cancelReload();
|
||||
q->reloadFinished(success);
|
||||
return;
|
||||
}
|
||||
|
||||
q->processCommandOutput(m_output);
|
||||
}
|
||||
|
||||
/////////////////////
|
||||
|
||||
VcsBaseDiffEditorController::VcsBaseDiffEditorController(IDocument *document,
|
||||
VcsBaseClientImpl *client,
|
||||
const QString &workingDirectory)
|
||||
: DiffEditorController(document)
|
||||
, d(new VcsBaseDiffEditorControllerPrivate(this, client, workingDirectory))
|
||||
{
|
||||
}
|
||||
|
||||
VcsBaseDiffEditorController::~VcsBaseDiffEditorController()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
void VcsBaseDiffEditorController::runCommand(const QList<QStringList> &args, unsigned flags, QTextCodec *codec)
|
||||
{
|
||||
d->cancelReload();
|
||||
|
||||
d->m_command = new VcsCommand(workingDirectory(), d->m_client->processEnvironment());
|
||||
d->m_command->setCodec(codec ? codec : EditorManager::defaultTextCodec());
|
||||
connect(d->m_command.data(), &VcsCommand::stdOutText, this,
|
||||
[this] (const QString &output) { d->m_output = output; });
|
||||
connect(d->m_command.data(), &VcsCommand::finished, this,
|
||||
[this] (bool success) { d->commandFinished(success); });
|
||||
d->m_command->addFlags(flags);
|
||||
|
||||
for (const QStringList &arg : args) {
|
||||
QTC_ASSERT(!arg.isEmpty(), continue);
|
||||
|
||||
d->m_command->addJob(d->m_client->vcsBinary(), arg, d->m_client->vcsTimeoutS());
|
||||
}
|
||||
|
||||
d->m_command->execute();
|
||||
}
|
||||
|
||||
void VcsBaseDiffEditorController::processCommandOutput(const QString &output)
|
||||
{
|
||||
d->processDiff(output);
|
||||
}
|
||||
|
||||
VcsBaseClientImpl *VcsBaseDiffEditorController::client() const
|
||||
{
|
||||
return d->m_client;
|
||||
}
|
||||
|
||||
QString VcsBaseDiffEditorController::workingDirectory() const
|
||||
{
|
||||
return d->m_directory;
|
||||
}
|
||||
|
||||
void VcsBaseDiffEditorController::setStartupFile(const QString &startupFile)
|
||||
{
|
||||
d->m_startupFile = startupFile;
|
||||
}
|
||||
|
||||
QString VcsBaseDiffEditorController::startupFile() const
|
||||
{
|
||||
return d->m_startupFile;
|
||||
}
|
||||
|
||||
} // namespace VcsBase
|
62
src/plugins/vcsbase/vcsbasediffeditorcontroller.h
Normal file
62
src/plugins/vcsbase/vcsbasediffeditorcontroller.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2017 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "vcsbase_global.h"
|
||||
#include <diffeditor/diffeditorcontroller.h>
|
||||
|
||||
namespace Core { class IDocument; }
|
||||
|
||||
namespace VcsBase {
|
||||
|
||||
class VcsBaseClientImpl;
|
||||
class VcsBaseDiffEditorControllerPrivate;
|
||||
|
||||
class VCSBASE_EXPORT VcsBaseDiffEditorController : public DiffEditor::DiffEditorController
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
VcsBaseDiffEditorController(Core::IDocument *document,
|
||||
VcsBaseClientImpl *client,
|
||||
const QString &workingDirectory);
|
||||
~VcsBaseDiffEditorController();
|
||||
|
||||
protected:
|
||||
void runCommand(const QList<QStringList> &args, unsigned flags, QTextCodec *codec = nullptr);
|
||||
virtual void processCommandOutput(const QString &output);
|
||||
|
||||
VcsBaseClientImpl *client() const;
|
||||
QString workingDirectory() const;
|
||||
void setStartupFile(const QString &startupFile);
|
||||
QString startupFile() const;
|
||||
|
||||
private:
|
||||
friend class VcsBaseDiffEditorControllerPrivate;
|
||||
VcsBaseDiffEditorControllerPrivate *d;
|
||||
};
|
||||
|
||||
} //namespace VcsBase
|
Reference in New Issue
Block a user