Commit 69cca88d authored by Daniel Teske's avatar Daniel Teske

Add gui thread mode to BuildStep

Change-Id: I11501635bc5c17db557ea8379eb63c9d3915a05e
Reviewed-on: http://codereview.qt.nokia.com/1316Reviewed-by: default avatarQt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: default avatarChristian Kandeler <christian.kandeler@nokia.com>
parent f3a45d7b
......@@ -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;
......
......@@ -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();
......
......@@ -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)
{ }
......
......@@ -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 :
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment