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
|
bool BuildConfiguration::isEnabled() const
|
||||||
{
|
{
|
||||||
return !buildSystem()->isParsing() && buildSystem()->hasParsingData();
|
return buildSystem()->hasParsingData();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString BuildConfiguration::disabledReason() const
|
QString BuildConfiguration::disabledReason() const
|
||||||
{
|
{
|
||||||
if (buildSystem()->isParsing())
|
|
||||||
return (tr("The project is currently being parsed."));
|
|
||||||
if (!buildSystem()->hasParsingData())
|
if (!buildSystem()->hasParsingData())
|
||||||
return (tr("The project was not parsed successfully."));
|
return (tr("The project was not parsed successfully."));
|
||||||
return QString();
|
return QString();
|
||||||
|
@@ -91,8 +91,8 @@ public:
|
|||||||
bool fromMap(const QVariantMap &map) override;
|
bool fromMap(const QVariantMap &map) override;
|
||||||
QVariantMap toMap() const override;
|
QVariantMap toMap() const override;
|
||||||
|
|
||||||
virtual bool isEnabled() const;
|
bool isEnabled() const;
|
||||||
virtual QString disabledReason() const;
|
QString disabledReason() const;
|
||||||
|
|
||||||
virtual bool regenerateBuildFiles(Node *node);
|
virtual bool regenerateBuildFiles(Node *node);
|
||||||
|
|
||||||
|
@@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include "buildprogress.h"
|
#include "buildprogress.h"
|
||||||
#include "buildsteplist.h"
|
#include "buildsteplist.h"
|
||||||
|
#include "buildsystem.h"
|
||||||
#include "compileoutputwindow.h"
|
#include "compileoutputwindow.h"
|
||||||
#include "deployconfiguration.h"
|
#include "deployconfiguration.h"
|
||||||
#include "kit.h"
|
#include "kit.h"
|
||||||
@@ -46,6 +47,7 @@
|
|||||||
#include <coreplugin/progressmanager/futureprogress.h>
|
#include <coreplugin/progressmanager/futureprogress.h>
|
||||||
#include <coreplugin/progressmanager/progressmanager.h>
|
#include <coreplugin/progressmanager/progressmanager.h>
|
||||||
#include <extensionsystem/pluginmanager.h>
|
#include <extensionsystem/pluginmanager.h>
|
||||||
|
#include <utils/algorithm.h>
|
||||||
#include <utils/outputformatter.h>
|
#include <utils/outputformatter.h>
|
||||||
#include <utils/runextensions.h>
|
#include <utils/runextensions.h>
|
||||||
#include <utils/stringutils.h>
|
#include <utils/stringutils.h>
|
||||||
@@ -57,6 +59,7 @@
|
|||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
|
#include <QSet>
|
||||||
#include <QTime>
|
#include <QTime>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
@@ -215,6 +218,7 @@ public:
|
|||||||
Internal::CompileOutputWindow *m_outputWindow = nullptr;
|
Internal::CompileOutputWindow *m_outputWindow = nullptr;
|
||||||
Internal::TaskWindow *m_taskWindow = nullptr;
|
Internal::TaskWindow *m_taskWindow = nullptr;
|
||||||
|
|
||||||
|
QMetaObject::Connection m_scheduledBuild;
|
||||||
QList<BuildStep *> m_buildQueue;
|
QList<BuildStep *> m_buildQueue;
|
||||||
QList<bool> m_enabledState;
|
QList<bool> m_enabledState;
|
||||||
QStringList m_stepNames;
|
QStringList m_stepNames;
|
||||||
@@ -459,6 +463,12 @@ QString BuildManager::displayNameForStepId(Id stepId)
|
|||||||
|
|
||||||
void BuildManager::cancel()
|
void BuildManager::cancel()
|
||||||
{
|
{
|
||||||
|
if (d->m_scheduledBuild) {
|
||||||
|
disconnect(d->m_scheduledBuild);
|
||||||
|
d->m_scheduledBuild = {};
|
||||||
|
clearBuildQueue();
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (d->m_running) {
|
if (d->m_running) {
|
||||||
if (d->m_canceling)
|
if (d->m_canceling)
|
||||||
return;
|
return;
|
||||||
@@ -502,11 +512,13 @@ void BuildManager::clearBuildQueue()
|
|||||||
d->m_previousBuildStepProject = nullptr;
|
d->m_previousBuildStepProject = nullptr;
|
||||||
d->m_currentBuildStep = nullptr;
|
d->m_currentBuildStep = nullptr;
|
||||||
|
|
||||||
d->m_progressFutureInterface->reportCanceled();
|
if (d->m_progressFutureInterface) {
|
||||||
d->m_progressFutureInterface->reportFinished();
|
d->m_progressFutureInterface->reportCanceled();
|
||||||
d->m_progressWatcher.setFuture(QFuture<void>());
|
d->m_progressFutureInterface->reportFinished();
|
||||||
delete d->m_progressFutureInterface;
|
d->m_progressWatcher.setFuture(QFuture<void>());
|
||||||
d->m_progressFutureInterface = nullptr;
|
delete d->m_progressFutureInterface;
|
||||||
|
d->m_progressFutureInterface = nullptr;
|
||||||
|
}
|
||||||
d->m_futureProgress = nullptr;
|
d->m_futureProgress = nullptr;
|
||||||
d->m_maxProgress = 0;
|
d->m_maxProgress = 0;
|
||||||
|
|
||||||
@@ -544,6 +556,28 @@ void BuildManager::startBuildQueue()
|
|||||||
emit m_instance->buildQueueFinished(true);
|
emit m_instance->buildQueueFinished(true);
|
||||||
return;
|
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) {
|
if (!d->m_running) {
|
||||||
d->m_elapsed.start();
|
d->m_elapsed.start();
|
||||||
// Progress Reporting
|
// Progress Reporting
|
||||||
|
@@ -107,7 +107,6 @@ void BuildSystem::emitParsingStarted()
|
|||||||
QTC_ASSERT(!d->m_isParsing, return);
|
QTC_ASSERT(!d->m_isParsing, return);
|
||||||
|
|
||||||
d->m_isParsing = true;
|
d->m_isParsing = true;
|
||||||
d->m_hasParsingData = false;
|
|
||||||
emit parsingStarted();
|
emit parsingStarted();
|
||||||
emit d->m_target->parsingStarted();
|
emit d->m_target->parsingStarted();
|
||||||
}
|
}
|
||||||
|
@@ -2870,6 +2870,11 @@ void ProjectExplorerPlugin::runRunConfiguration(RunConfiguration *rc,
|
|||||||
{
|
{
|
||||||
if (!rc->isEnabled())
|
if (!rc->isEnabled())
|
||||||
return;
|
return;
|
||||||
|
const auto delay = [rc, runMode] {
|
||||||
|
dd->m_runMode = runMode;
|
||||||
|
dd->m_delayedRunConfiguration = rc;
|
||||||
|
dd->m_shouldHaveRunConfiguration = true;
|
||||||
|
};
|
||||||
const BuildForRunConfigStatus buildStatus = forceSkipDeploy
|
const BuildForRunConfigStatus buildStatus = forceSkipDeploy
|
||||||
? BuildManager::isBuilding(rc->project())
|
? BuildManager::isBuilding(rc->project())
|
||||||
? BuildForRunConfigStatus::Building : BuildForRunConfigStatus::NotBuilding
|
? BuildForRunConfigStatus::Building : BuildForRunConfigStatus::NotBuilding
|
||||||
@@ -2879,14 +2884,13 @@ void ProjectExplorerPlugin::runRunConfiguration(RunConfiguration *rc,
|
|||||||
return;
|
return;
|
||||||
case BuildForRunConfigStatus::Building:
|
case BuildForRunConfigStatus::Building:
|
||||||
QTC_ASSERT(dd->m_runMode == Constants::NO_RUN_MODE, return);
|
QTC_ASSERT(dd->m_runMode == Constants::NO_RUN_MODE, return);
|
||||||
|
delay();
|
||||||
// delay running till after our queued steps were processed
|
|
||||||
dd->m_runMode = runMode;
|
|
||||||
dd->m_delayedRunConfiguration = rc;
|
|
||||||
dd->m_shouldHaveRunConfiguration = true;
|
|
||||||
break;
|
break;
|
||||||
case BuildForRunConfigStatus::NotBuilding:
|
case BuildForRunConfigStatus::NotBuilding:
|
||||||
dd->executeRunConfiguration(rc, runMode);
|
if (rc->isEnabled())
|
||||||
|
dd->executeRunConfiguration(rc, runMode);
|
||||||
|
else
|
||||||
|
delay();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -199,7 +199,7 @@ QbsBuildStep::~QbsBuildStep()
|
|||||||
|
|
||||||
bool QbsBuildStep::init()
|
bool QbsBuildStep::init()
|
||||||
{
|
{
|
||||||
if (qbsBuildSystem()->isParsing() || m_session)
|
if (m_session)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
auto bc = static_cast<QbsBuildConfiguration *>(buildConfiguration());
|
auto bc = static_cast<QbsBuildConfiguration *>(buildConfiguration());
|
||||||
|
@@ -231,11 +231,8 @@ QString QmlProjectRunConfiguration::commandLineArguments() const
|
|||||||
|
|
||||||
bool QmlProjectRunConfiguration::isEnabled() const
|
bool QmlProjectRunConfiguration::isEnabled() const
|
||||||
{
|
{
|
||||||
if (m_qmlMainFileAspect->isQmlFilePresent() && !commandLine().executable().isEmpty()) {
|
return m_qmlMainFileAspect->isQmlFilePresent() && !commandLine().executable().isEmpty()
|
||||||
BuildSystem *bs = activeBuildSystem();
|
&& activeBuildSystem()->hasParsingData();
|
||||||
return !bs->isParsing() && bs->hasParsingData();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QmlProjectRunConfiguration::mainScript() const
|
QString QmlProjectRunConfiguration::mainScript() const
|
||||||
|
Reference in New Issue
Block a user