summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/plugins/projectexplorer/buildmanager.cpp44
-rw-r--r--src/plugins/projectexplorer/buildmanager.h1
-rw-r--r--src/plugins/projectexplorer/buildstep.cpp30
-rw-r--r--src/plugins/projectexplorer/buildstep.h4
4 files changed, 75 insertions, 4 deletions
diff --git a/src/plugins/projectexplorer/buildmanager.cpp b/src/plugins/projectexplorer/buildmanager.cpp
index d729439ad6..13f54b1c63 100644
--- a/src/plugins/projectexplorer/buildmanager.cpp
+++ b/src/plugins/projectexplorer/buildmanager.cpp
@@ -84,6 +84,7 @@ struct BuildManagerPrivate {
ProjectExplorerPlugin *m_projectExplorerPlugin;
bool m_running;
QFutureWatcher<bool> m_watcher;
+ QFutureInterface<bool> m_futureInterfaceForAysnc;
BuildStep *m_currentBuildStep;
QString m_currentConfiguration;
// used to decide if we are building a project to decide when to emit buildStateChanged(Project *)
@@ -91,6 +92,8 @@ struct BuildManagerPrivate {
Project *m_previousBuildStepProject;
// is set to true while canceling, so that nextBuildStep knows that the BuildStep finished because of canceling
bool m_canceling;
+ bool m_doNotEnterEventLoop;
+ QEventLoop *m_eventLoop;
// Progress reporting to the progress manager
int m_progress;
@@ -103,6 +106,8 @@ BuildManagerPrivate::BuildManagerPrivate() :
m_running(false)
, m_previousBuildStepProject(0)
, m_canceling(false)
+ , m_doNotEnterEventLoop(false)
+ , m_eventLoop(0)
, m_maxProgress(0)
, m_progressFutureInterface(0)
{
@@ -190,7 +195,20 @@ void BuildManager::cancel()
if (d->m_running) {
d->m_canceling = true;
d->m_watcher.cancel();
- d->m_watcher.waitForFinished();
+ if (d->m_currentBuildStep->runInGuiThread()) {
+ // This is evil. A nested event loop.
+ d->m_currentBuildStep->cancel();
+ if (d->m_doNotEnterEventLoop) {
+ d->m_doNotEnterEventLoop = false;
+ } else {
+ d->m_eventLoop = new QEventLoop;
+ d->m_eventLoop->exec();
+ delete d->m_eventLoop;
+ d->m_eventLoop = 0;
+ }
+ } else {
+ d->m_watcher.waitForFinished();
+ }
// The cancel message is added to the output window via a single shot timer
// since the canceling is likely to have generated new addToOutputWindow signals
@@ -332,6 +350,21 @@ void BuildManager::addToOutputWindow(const QString &string, BuildStep::OutputFor
d->m_outputWindow->appendText(stringToWrite, format);
}
+void BuildManager::buildStepFinishedAsync()
+{
+ disconnect(d->m_currentBuildStep, SIGNAL(finished()),
+ this, SLOT(buildStepFinishedAsync()));
+ d->m_futureInterfaceForAysnc = QFutureInterface<bool>();
+ if (d->m_canceling) {
+ if (d->m_eventLoop)
+ d->m_eventLoop->exit();
+ else
+ d->m_doNotEnterEventLoop = true;
+ } else {
+ nextBuildQueue();
+ }
+}
+
void BuildManager::nextBuildQueue()
{
if (d->m_canceling)
@@ -393,7 +426,14 @@ void BuildManager::nextStep()
.arg(projectName), BuildStep::MessageOutput);
d->m_previousBuildStepProject = d->m_currentBuildStep->buildConfiguration()->target()->project();
}
- d->m_watcher.setFuture(QtConcurrent::run(&BuildStep::run, d->m_currentBuildStep));
+ if (d->m_currentBuildStep->runInGuiThread()) {
+ connect (d->m_currentBuildStep, SIGNAL(finished()),
+ this, SLOT(buildStepFinishedAsync()));
+ d->m_watcher.setFuture(d->m_futureInterfaceForAysnc.future());
+ d->m_currentBuildStep->run(d->m_futureInterfaceForAysnc);
+ } else {
+ d->m_watcher.setFuture(QtConcurrent::run(&BuildStep::run, d->m_currentBuildStep));
+ }
} else {
d->m_running = false;
d->m_previousBuildStepProject = 0;
diff --git a/src/plugins/projectexplorer/buildmanager.h b/src/plugins/projectexplorer/buildmanager.h
index 574a2cc77a..1933cacdc4 100644
--- a/src/plugins/projectexplorer/buildmanager.h
+++ b/src/plugins/projectexplorer/buildmanager.h
@@ -87,6 +87,7 @@ private slots:
void addToOutputWindow(const QString &string, ProjectExplorer::BuildStep::OutputFormat,
ProjectExplorer::BuildStep::OutputNewlineSetting = BuildStep::DoAppendNewline);
+ void buildStepFinishedAsync();
void nextBuildQueue();
void progressChanged();
void progressTextChanged();
diff --git a/src/plugins/projectexplorer/buildstep.cpp b/src/plugins/projectexplorer/buildstep.cpp
index e4c397a362..2a5ddaa961 100644
--- a/src/plugins/projectexplorer/buildstep.cpp
+++ b/src/plugins/projectexplorer/buildstep.cpp
@@ -69,13 +69,18 @@
\fn void ProjectExplorer::BuildStep::run(QFutureInterface<bool> &fi)
Reimplement this. This function is called when the target is build.
- This function is NOT run in the gui thread. It runs in its own thread
- If you need an event loop, you need to create one.
+ By default this function is NOT run in the gui thread. It runs in its
+ own thread. If you need an event loop, you need to create one.
+ This function should block until the task is done
The absolute minimal implementation is:
\code
fi.reportResult(true);
\endcode
+
+ By returning true from \sa runInGuiThread() this function is called in the
+ gui thread. Then the function should not block and instead the
+ finished() signal should be emitted.
*/
/*!
@@ -106,6 +111,17 @@
It should be in plain text, with the format in the parameter.
*/
+/*!
+ \fn void ProjectExplorer::BuildStep::cancel() const
+
+ This function needs to be reimplemented only for BuildSteps that return false from \sa runInGuiThread.
+*/
+
+/*!
+ \fn void ProjectExplorer::BuildStep::finished()
+ \brief This signal needs to be emitted if the BuildStep runs in the gui thread.
+*/
+
using namespace ProjectExplorer;
BuildStep::BuildStep(BuildStepList *bsl, const QString &id) :
@@ -150,6 +166,16 @@ bool BuildStep::immutable() const
return false;
}
+bool BuildStep::runInGuiThread() const
+{
+ return false;
+}
+
+void BuildStep::cancel()
+{
+ // Do nothing
+}
+
IBuildStepFactory::IBuildStepFactory(QObject *parent) :
QObject(parent)
{ }
diff --git a/src/plugins/projectexplorer/buildstep.h b/src/plugins/projectexplorer/buildstep.h
index b4b3d116eb..886f6c048f 100644
--- a/src/plugins/projectexplorer/buildstep.h
+++ b/src/plugins/projectexplorer/buildstep.h
@@ -68,6 +68,8 @@ public:
virtual BuildStepConfigWidget *createConfigWidget() = 0;
virtual bool immutable() const;
+ virtual bool runInGuiThread() const;
+ virtual void cancel();
BuildConfiguration *buildConfiguration() const;
DeployConfiguration *deployConfiguration() const;
@@ -81,6 +83,8 @@ signals:
void addOutput(const QString &string, ProjectExplorer::BuildStep::OutputFormat format,
ProjectExplorer::BuildStep::OutputNewlineSetting newlineSetting = DoAppendNewline) const;
+
+ void finished();
};
class PROJECTEXPLORER_EXPORT IBuildStepFactory :