forked from qt-creator/qt-creator
ProjectExplorer: Allow to schedule a build/run during a project parse
Once we parsed the project initially, subsequent parses typically do not
change things in a major way, so we can expect e.g. run configurations to
stay intact.
It therefore makes sense to allow users to schedule an
application run not only during a build (see 4b92b7ac60
), but also
during a parse. Arguably, this is even more relevant, as parsing is
usually not triggered directly by the user, but happens as a side effect
of editing a document or switching a branch. It is then annoying for
users to have to wait until the respective buttons get enabled again.
Fixes: QTCREATORBUG-24986
Change-Id: I1081ccde668eee794c39b96cd0bad5c3aaa580bc
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -531,13 +531,11 @@ void BuildConfiguration::setUserEnvironmentChanges(const EnvironmentItems &diff)
|
||||
|
||||
bool BuildConfiguration::isEnabled() const
|
||||
{
|
||||
return !buildSystem()->isParsing() && buildSystem()->hasParsingData();
|
||||
return buildSystem()->hasParsingData();
|
||||
}
|
||||
|
||||
QString BuildConfiguration::disabledReason() const
|
||||
{
|
||||
if (buildSystem()->isParsing())
|
||||
return (tr("The project is currently being parsed."));
|
||||
if (!buildSystem()->hasParsingData())
|
||||
return (tr("The project was not parsed successfully."));
|
||||
return QString();
|
||||
|
@@ -91,8 +91,8 @@ public:
|
||||
bool fromMap(const QVariantMap &map) override;
|
||||
QVariantMap toMap() const override;
|
||||
|
||||
virtual bool isEnabled() const;
|
||||
virtual QString disabledReason() const;
|
||||
bool isEnabled() const;
|
||||
QString disabledReason() const;
|
||||
|
||||
virtual bool regenerateBuildFiles(Node *node);
|
||||
|
||||
|
@@ -27,6 +27,7 @@
|
||||
|
||||
#include "buildprogress.h"
|
||||
#include "buildsteplist.h"
|
||||
#include "buildsystem.h"
|
||||
#include "compileoutputwindow.h"
|
||||
#include "deployconfiguration.h"
|
||||
#include "kit.h"
|
||||
@@ -46,6 +47,7 @@
|
||||
#include <coreplugin/progressmanager/futureprogress.h>
|
||||
#include <coreplugin/progressmanager/progressmanager.h>
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/outputformatter.h>
|
||||
#include <utils/runextensions.h>
|
||||
#include <utils/stringutils.h>
|
||||
@@ -57,6 +59,7 @@
|
||||
#include <QList>
|
||||
#include <QMessageBox>
|
||||
#include <QPointer>
|
||||
#include <QSet>
|
||||
#include <QTime>
|
||||
#include <QTimer>
|
||||
|
||||
@@ -215,6 +218,7 @@ public:
|
||||
Internal::CompileOutputWindow *m_outputWindow = nullptr;
|
||||
Internal::TaskWindow *m_taskWindow = nullptr;
|
||||
|
||||
QMetaObject::Connection m_scheduledBuild;
|
||||
QList<BuildStep *> m_buildQueue;
|
||||
QList<bool> m_enabledState;
|
||||
QStringList m_stepNames;
|
||||
@@ -459,6 +463,12 @@ QString BuildManager::displayNameForStepId(Id stepId)
|
||||
|
||||
void BuildManager::cancel()
|
||||
{
|
||||
if (d->m_scheduledBuild) {
|
||||
disconnect(d->m_scheduledBuild);
|
||||
d->m_scheduledBuild = {};
|
||||
clearBuildQueue();
|
||||
return;
|
||||
}
|
||||
if (d->m_running) {
|
||||
if (d->m_canceling)
|
||||
return;
|
||||
@@ -502,11 +512,13 @@ void BuildManager::clearBuildQueue()
|
||||
d->m_previousBuildStepProject = nullptr;
|
||||
d->m_currentBuildStep = nullptr;
|
||||
|
||||
d->m_progressFutureInterface->reportCanceled();
|
||||
d->m_progressFutureInterface->reportFinished();
|
||||
d->m_progressWatcher.setFuture(QFuture<void>());
|
||||
delete d->m_progressFutureInterface;
|
||||
d->m_progressFutureInterface = nullptr;
|
||||
if (d->m_progressFutureInterface) {
|
||||
d->m_progressFutureInterface->reportCanceled();
|
||||
d->m_progressFutureInterface->reportFinished();
|
||||
d->m_progressWatcher.setFuture(QFuture<void>());
|
||||
delete d->m_progressFutureInterface;
|
||||
d->m_progressFutureInterface = nullptr;
|
||||
}
|
||||
d->m_futureProgress = nullptr;
|
||||
d->m_maxProgress = 0;
|
||||
|
||||
@@ -544,6 +556,28 @@ void BuildManager::startBuildQueue()
|
||||
emit m_instance->buildQueueFinished(true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Delay if any of the involved build systems are currently parsing.
|
||||
const auto buildSystems = transform<QSet<BuildSystem *>>(d->m_buildQueue,
|
||||
[](const BuildStep *bs) { return bs->buildSystem(); });
|
||||
for (const BuildSystem * const bs : buildSystems) {
|
||||
if (!bs || !bs->isParsing())
|
||||
continue;
|
||||
d->m_scheduledBuild = QObject::connect(bs, &BuildSystem::parsingFinished,
|
||||
BuildManager::instance(),
|
||||
[](bool parsingSuccess) {
|
||||
if (!d->m_scheduledBuild)
|
||||
return;
|
||||
QObject::disconnect(d->m_scheduledBuild);
|
||||
d->m_scheduledBuild = {};
|
||||
if (parsingSuccess)
|
||||
startBuildQueue();
|
||||
else
|
||||
clearBuildQueue();
|
||||
}, Qt::QueuedConnection);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!d->m_running) {
|
||||
d->m_elapsed.start();
|
||||
// Progress Reporting
|
||||
|
@@ -107,7 +107,6 @@ void BuildSystem::emitParsingStarted()
|
||||
QTC_ASSERT(!d->m_isParsing, return);
|
||||
|
||||
d->m_isParsing = true;
|
||||
d->m_hasParsingData = false;
|
||||
emit parsingStarted();
|
||||
emit d->m_target->parsingStarted();
|
||||
}
|
||||
|
@@ -2870,6 +2870,11 @@ void ProjectExplorerPlugin::runRunConfiguration(RunConfiguration *rc,
|
||||
{
|
||||
if (!rc->isEnabled())
|
||||
return;
|
||||
const auto delay = [rc, runMode] {
|
||||
dd->m_runMode = runMode;
|
||||
dd->m_delayedRunConfiguration = rc;
|
||||
dd->m_shouldHaveRunConfiguration = true;
|
||||
};
|
||||
const BuildForRunConfigStatus buildStatus = forceSkipDeploy
|
||||
? BuildManager::isBuilding(rc->project())
|
||||
? BuildForRunConfigStatus::Building : BuildForRunConfigStatus::NotBuilding
|
||||
@@ -2879,14 +2884,13 @@ void ProjectExplorerPlugin::runRunConfiguration(RunConfiguration *rc,
|
||||
return;
|
||||
case BuildForRunConfigStatus::Building:
|
||||
QTC_ASSERT(dd->m_runMode == Constants::NO_RUN_MODE, return);
|
||||
|
||||
// delay running till after our queued steps were processed
|
||||
dd->m_runMode = runMode;
|
||||
dd->m_delayedRunConfiguration = rc;
|
||||
dd->m_shouldHaveRunConfiguration = true;
|
||||
delay();
|
||||
break;
|
||||
case BuildForRunConfigStatus::NotBuilding:
|
||||
dd->executeRunConfiguration(rc, runMode);
|
||||
if (rc->isEnabled())
|
||||
dd->executeRunConfiguration(rc, runMode);
|
||||
else
|
||||
delay();
|
||||
break;
|
||||
}
|
||||
|
||||
|
@@ -199,7 +199,7 @@ QbsBuildStep::~QbsBuildStep()
|
||||
|
||||
bool QbsBuildStep::init()
|
||||
{
|
||||
if (qbsBuildSystem()->isParsing() || m_session)
|
||||
if (m_session)
|
||||
return false;
|
||||
|
||||
auto bc = static_cast<QbsBuildConfiguration *>(buildConfiguration());
|
||||
|
@@ -231,11 +231,8 @@ QString QmlProjectRunConfiguration::commandLineArguments() const
|
||||
|
||||
bool QmlProjectRunConfiguration::isEnabled() const
|
||||
{
|
||||
if (m_qmlMainFileAspect->isQmlFilePresent() && !commandLine().executable().isEmpty()) {
|
||||
BuildSystem *bs = activeBuildSystem();
|
||||
return !bs->isParsing() && bs->hasParsingData();
|
||||
}
|
||||
return false;
|
||||
return m_qmlMainFileAspect->isQmlFilePresent() && !commandLine().executable().isEmpty()
|
||||
&& activeBuildSystem()->hasParsingData();
|
||||
}
|
||||
|
||||
QString QmlProjectRunConfiguration::mainScript() const
|
||||
|
Reference in New Issue
Block a user