diff --git a/src/plugins/vcsbase/checkoutprogresswizardpage.cpp b/src/plugins/vcsbase/checkoutprogresswizardpage.cpp index 1de7d3737615e8ec881351494229e76dac10dc3f..d427a01f7fa6eb217c473bdcbb4a3fe573f3945c 100644 --- a/src/plugins/vcsbase/checkoutprogresswizardpage.cpp +++ b/src/plugins/vcsbase/checkoutprogresswizardpage.cpp @@ -132,7 +132,7 @@ void CheckoutProgressWizardPage::slotError(const QString &text) void CheckoutProgressWizardPage::terminate() { if (m_command) - m_command->terminate(); + m_command->cancel(); } bool CheckoutProgressWizardPage::isComplete() const diff --git a/src/plugins/vcsbase/command.cpp b/src/plugins/vcsbase/command.cpp index 85148aee10acfdbd4a2b8cadc65db1113256b776..27d62ea81faad2c7b51459df240052902d298226 100644 --- a/src/plugins/vcsbase/command.cpp +++ b/src/plugins/vcsbase/command.cpp @@ -42,6 +42,7 @@ #include <QProcess> #include <QProcessEnvironment> #include <QFuture> +#include <QFutureWatcher> #include <QtConcurrentRun> #include <QFileInfo> #include <QCoreApplication> @@ -101,6 +102,8 @@ public: ProgressParser *m_progressParser; VcsBase::VcsBaseOutputWindow *m_outputWindow; bool m_progressiveOutput; + bool m_hadOutput; + QFutureWatcher<void> m_watcher; QList<Job> m_jobs; @@ -121,6 +124,7 @@ CommandPrivate::CommandPrivate(const QString &binary, m_progressParser(0), m_outputWindow(VcsBase::VcsBaseOutputWindow::instance()), m_progressiveOutput(false), + m_hadOutput(false), m_lastExecSuccess(false), m_lastExecExitCode(-1) { @@ -210,6 +214,8 @@ void Command::execute() // For some reason QtConcurrent::run() only works on this QFuture<void> task = QtConcurrent::run(&Command::run, this); + d->m_watcher.setFuture(task); + connect(&d->m_watcher, SIGNAL(canceled()), this, SLOT(cancel())); QString binary = QFileInfo(d->m_binaryPath).baseName(); if (!binary.isEmpty()) binary = binary.replace(0, 1, binary[0].toUpper()); // Upper the first letter @@ -219,9 +225,9 @@ void Command::execute() Core::Id::fromString(binary + QLatin1String(".action"))); } -void Command::terminate() +void Command::cancel() { - emit doTerminate(); + emit terminate(); } bool Command::lastExecutionSuccess() const @@ -247,6 +253,8 @@ void Command::run(QFutureInterface<void> &future) if (d->m_progressParser) d->m_progressParser->setFuture(&future); + else + future.setProgressRange(0, 1); const int count = d->m_jobs.size(); d->m_lastExecExitCode = -1; d->m_lastExecSuccess = true; @@ -265,18 +273,24 @@ void Command::run(QFutureInterface<void> &future) break; } - if (!future.isCanceled()) { - if (!d->m_progressiveOutput) { + const QString canceledMessage = tr("Canceled"); + if (d->m_progressiveOutput) { + if (!d->m_hadOutput && future.isCanceled()) + emit output(canceledMessage); + } else { + if (stdOut.isEmpty() && future.isCanceled()) + emit output(canceledMessage); + else emit output(stdOut); - if (!stdErr.isEmpty()) - emit errorText(stdErr); - } - - emit finished(d->m_lastExecSuccess, d->m_lastExecExitCode, cookie()); - if (d->m_lastExecSuccess) - emit success(cookie()); + if (!stdErr.isEmpty()) + emit errorText(stdErr); } + emit finished(d->m_lastExecSuccess, d->m_lastExecExitCode, cookie()); + if (d->m_lastExecSuccess) + emit success(cookie()); + future.setProgressValue(future.progressMaximum()); + if (d->m_progressParser) d->m_progressParser->setFuture(0); // As it is used asynchronously, we need to delete ourselves @@ -362,7 +376,7 @@ Utils::SynchronousProcessResponse Command::runVcs(const QStringList &arguments, } else { Utils::SynchronousProcess process; process.setExitCodeInterpreter(interpreter); - connect(this, SIGNAL(doTerminate()), &process, SLOT(terminate())); + connect(this, SIGNAL(terminate()), &process, SLOT(terminate())); if (!d->m_workingDirectory.isEmpty()) process.setWorkingDirectory(d->m_workingDirectory); @@ -535,8 +549,10 @@ void Command::bufferedOutput(const QString &text) d->m_progressParser->parseProgress(text); if (d->m_flags & VcsBasePlugin::ShowStdOutInLogWindow) d->m_outputWindow->append(text); - if (d->m_progressiveOutput) + if (d->m_progressiveOutput) { emit output(text); + d->m_hadOutput = true; + } } void Command::bufferedError(const QString &text) diff --git a/src/plugins/vcsbase/command.h b/src/plugins/vcsbase/command.h index bf4006187b3b5de3baa2d52946dde392b04aacb1..821db128e01cbaaabc7758379ad81a601601d96e 100644 --- a/src/plugins/vcsbase/command.h +++ b/src/plugins/vcsbase/command.h @@ -80,7 +80,6 @@ public: void addJob(const QStringList &arguments, Utils::ExitCodeInterpreter *interpreter = 0); void addJob(const QStringList &arguments, int timeout, Utils::ExitCodeInterpreter *interpreter = 0); void execute(); - void terminate(); bool lastExecutionSuccess() const; int lastExecutionExitCode() const; @@ -114,16 +113,21 @@ private: Utils::SynchronousProcessResponse runSynchronous(const QStringList &arguments, int timeoutMS, Utils::ExitCodeInterpreter *interpreter = 0); -private slots: - void bufferedOutput(const QString &text); - void bufferedError(const QString &text); +public slots: + void cancel(); signals: void output(const QString &); void errorText(const QString &); void finished(bool ok, int exitCode, const QVariant &cookie); void success(const QVariant &cookie); - void doTerminate(); + +private slots: + void bufferedOutput(const QString &text); + void bufferedError(const QString &text); + +signals: + void terminate(); // Internal private: class Internal::CommandPrivate *const d;