From 30b4955ed7aa1ac3b78e9eb9385c033311b3a620 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 10 Mar 2017 09:05:52 +0100 Subject: [PATCH] ProjectExplorer: Add a SimpleRunControl implementation Essentially a RunControl with and ApplicationLauncher member like it is used directly or in disguise in the LocalApplicationRunControl, Nim and Python. Extenting that to RemoteLinux/Qnx is possible, but left to the next patch. Change-Id: I91b3199d3d6a418fe4e5be7a5d61689c581a5121 Reviewed-by: Tobias Hunger --- src/plugins/nim/nim.pro | 2 - src/plugins/nim/nim.qbs | 1 - src/plugins/nim/project/nimruncontrol.cpp | 92 -------------- src/plugins/nim/project/nimruncontrol.h | 56 --------- .../nim/project/nimruncontrolfactory.cpp | 3 +- .../localapplicationruncontrol.cpp | 85 +------------ .../projectexplorer/runconfiguration.cpp | 93 +++++++++++++- .../projectexplorer/runconfiguration.h | 22 +++- .../pythoneditor/pythoneditorplugin.cpp | 119 +++--------------- 9 files changed, 130 insertions(+), 343 deletions(-) delete mode 100644 src/plugins/nim/project/nimruncontrol.cpp delete mode 100644 src/plugins/nim/project/nimruncontrol.h diff --git a/src/plugins/nim/nim.pro b/src/plugins/nim/nim.pro index 85e3881e92c..1a27ab50cf0 100644 --- a/src/plugins/nim/nim.pro +++ b/src/plugins/nim/nim.pro @@ -29,7 +29,6 @@ HEADERS += \ project/nimcompilerbuildstepfactory.h \ project/nimcompilercleanstepfactory.h \ project/nimbuildconfigurationwidget.h \ - project/nimruncontrol.h \ project/nimruncontrolfactory.h \ editor/nimeditorfactory.h \ settings/nimcodestylesettingspage.h \ @@ -59,7 +58,6 @@ SOURCES += \ project/nimcompilerbuildstepfactory.cpp \ project/nimcompilercleanstepfactory.cpp \ project/nimbuildconfigurationwidget.cpp \ - project/nimruncontrol.cpp \ project/nimruncontrolfactory.cpp \ editor/nimeditorfactory.cpp \ settings/nimcodestylesettingspage.cpp \ diff --git a/src/plugins/nim/nim.qbs b/src/plugins/nim/nim.qbs index 94ec0a0de4e..d8fb94f0d9a 100644 --- a/src/plugins/nim/nim.qbs +++ b/src/plugins/nim/nim.qbs @@ -49,7 +49,6 @@ QtcPlugin { "nimrunconfiguration.h", "nimrunconfiguration.cpp", "nimrunconfigurationfactory.h", "nimrunconfigurationfactory.cpp", "nimrunconfigurationwidget.h", "nimrunconfigurationwidget.cpp", - "nimruncontrol.h", "nimruncontrol.cpp", "nimruncontrolfactory.h", "nimruncontrolfactory.cpp", "nimtoolchain.h", "nimtoolchain.cpp", "nimtoolchainfactory.h", "nimtoolchainfactory.cpp", diff --git a/src/plugins/nim/project/nimruncontrol.cpp b/src/plugins/nim/project/nimruncontrol.cpp deleted file mode 100644 index 3e5ea4eee56..00000000000 --- a/src/plugins/nim/project/nimruncontrol.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) Filippo Cucchetto -** Contact: http://www.qt.io/licensing -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "nimruncontrol.h" -#include "nimrunconfiguration.h" - -#include -#include -#include - -#include - -using namespace ProjectExplorer; -using namespace Utils; - -namespace Nim { - -NimRunControl::NimRunControl(NimRunConfiguration *rc, Core::Id mode) - : RunControl(rc, mode) - , m_runnable(rc->runnable().as()) -{ - connect(&m_applicationLauncher, &ApplicationLauncher::appendMessage, - this, &NimRunControl::slotAppendMessage); - connect(&m_applicationLauncher, &ApplicationLauncher::processStarted, - this, &NimRunControl::processStarted); - connect(&m_applicationLauncher, &ApplicationLauncher::processExited, - this, &NimRunControl::processExited); -} - -void NimRunControl::start() -{ - reportApplicationStart(); - m_applicationLauncher.start(m_runnable); - setApplicationProcessHandle(m_applicationLauncher.applicationPID()); - bringApplicationToForeground(); -} - -ProjectExplorer::RunControl::StopResult NimRunControl::stop() -{ - m_applicationLauncher.stop(); - return StoppedSynchronously; -} - -void NimRunControl::processStarted() -{ - // Console processes only know their pid after being started - setApplicationProcessHandle(m_applicationLauncher.applicationPID()); -} - -void NimRunControl::processExited(int exitCode, QProcess::ExitStatus status) -{ - setApplicationProcessHandle(ProcessHandle()); - QString msg; - if (status == QProcess::CrashExit) { - msg = tr("%1 crashed") - .arg(QDir::toNativeSeparators(m_runnable.executable)); - } else { - msg = tr("%1 exited with code %2") - .arg(QDir::toNativeSeparators(m_runnable.executable)).arg(exitCode); - } - appendMessage(msg + QLatin1Char('\n'), NormalMessageFormat); - reportApplicationStop(); -} - -void NimRunControl::slotAppendMessage(const QString &err, OutputFormat format) -{ - appendMessage(err, format); -} - -} diff --git a/src/plugins/nim/project/nimruncontrol.h b/src/plugins/nim/project/nimruncontrol.h deleted file mode 100644 index 0eba08e8cea..00000000000 --- a/src/plugins/nim/project/nimruncontrol.h +++ /dev/null @@ -1,56 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) Filippo Cucchetto -** Contact: http://www.qt.io/licensing -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#pragma once - -#include -#include - -#include - -namespace Nim { - -class NimRunConfiguration; - -class NimRunControl : public ProjectExplorer::RunControl -{ - Q_DECLARE_TR_FUNCTIONS(Nim::NimRunControl) - -public: - NimRunControl(NimRunConfiguration *runConfiguration, Core::Id mode); - - void start() override; - StopResult stop() override; - -private: - void processStarted(); - void processExited(int exitCode, QProcess::ExitStatus status); - void slotAppendMessage(const QString &err, Utils::OutputFormat isError); - - ProjectExplorer::ApplicationLauncher m_applicationLauncher; - ProjectExplorer::StandardRunnable m_runnable; -}; - -} diff --git a/src/plugins/nim/project/nimruncontrolfactory.cpp b/src/plugins/nim/project/nimruncontrolfactory.cpp index 3f02586ed7d..170e79f82db 100644 --- a/src/plugins/nim/project/nimruncontrolfactory.cpp +++ b/src/plugins/nim/project/nimruncontrolfactory.cpp @@ -25,7 +25,6 @@ #include "nimruncontrolfactory.h" #include "nimrunconfiguration.h" -#include "nimruncontrol.h" namespace Nim { @@ -39,7 +38,7 @@ ProjectExplorer::RunControl *NimRunControlFactory::create(ProjectExplorer::RunCo { Q_UNUSED(errorMessage) QTC_ASSERT(canRun(runConfiguration, mode), return 0); - return new NimRunControl(static_cast(runConfiguration), mode); + return new ProjectExplorer::SimpleRunControl(runConfiguration, mode); } } diff --git a/src/plugins/projectexplorer/localapplicationruncontrol.cpp b/src/plugins/projectexplorer/localapplicationruncontrol.cpp index 9cd27dc166e..bb13231ae9d 100644 --- a/src/plugins/projectexplorer/localapplicationruncontrol.cpp +++ b/src/plugins/projectexplorer/localapplicationruncontrol.cpp @@ -25,7 +25,6 @@ #include "localapplicationruncontrol.h" #include "runnables.h" -#include "environmentaspect.h" #include #include @@ -34,91 +33,11 @@ #include #include -#include - using namespace Utils; namespace ProjectExplorer { namespace Internal { -class LocalApplicationRunControl : public RunControl -{ - Q_OBJECT - -public: - LocalApplicationRunControl(RunConfiguration *runConfiguration, Core::Id mode); - - void start() override; - StopResult stop() override; - -private: - void processStarted(); - void processExited(int exitCode, QProcess::ExitStatus status); - - ApplicationLauncher m_applicationLauncher; -}; - -LocalApplicationRunControl::LocalApplicationRunControl(RunConfiguration *rc, Core::Id mode) - : RunControl(rc, mode) -{ - setRunnable(rc->runnable()); - setIcon(Utils::Icons::RUN_SMALL_TOOLBAR); - connect(&m_applicationLauncher, &ApplicationLauncher::appendMessage, - this, static_cast(&RunControl::appendMessage)); - connect(&m_applicationLauncher, &ApplicationLauncher::processStarted, - this, &LocalApplicationRunControl::processStarted); - connect(&m_applicationLauncher, &ApplicationLauncher::processExited, - this, &LocalApplicationRunControl::processExited); -} - -void LocalApplicationRunControl::start() -{ - QTC_ASSERT(runnable().is(), return); - auto r = runnable().as(); - reportApplicationStart(); - if (r.executable.isEmpty()) { - appendMessage(tr("No executable specified.") + QLatin1Char('\n'), Utils::ErrorMessageFormat); - reportApplicationStop(); - } else if (!QFileInfo::exists(r.executable)) { - appendMessage(tr("Executable %1 does not exist.") - .arg(QDir::toNativeSeparators(r.executable)) + QLatin1Char('\n'), - Utils::ErrorMessageFormat); - reportApplicationStop(); - } else { - QString msg = tr("Starting %1...").arg(QDir::toNativeSeparators(r.executable)) + QLatin1Char('\n'); - appendMessage(msg, Utils::NormalMessageFormat); - m_applicationLauncher.start(r); - setApplicationProcessHandle(m_applicationLauncher.applicationPID()); - } -} - -LocalApplicationRunControl::StopResult LocalApplicationRunControl::stop() -{ - m_applicationLauncher.stop(); - return StoppedSynchronously; -} - -void LocalApplicationRunControl::processStarted() -{ - // Console processes only know their pid after being started - setApplicationProcessHandle(m_applicationLauncher.applicationPID()); - bringApplicationToForeground(); -} - -void LocalApplicationRunControl::processExited(int exitCode, QProcess::ExitStatus status) -{ - QString msg; - QString exe = runnable().as().executable; - if (status == QProcess::CrashExit) - msg = tr("%1 crashed.").arg(QDir::toNativeSeparators(exe)); - else - msg = tr("%1 exited with code %2").arg(QDir::toNativeSeparators(exe)).arg(exitCode); - appendMessage(msg + QLatin1Char('\n'), Utils::NormalMessageFormat); - reportApplicationStop(); -} - -// LocalApplicationRunControlFactory - static bool isLocal(RunConfiguration *runConfiguration) { Target *target = runConfiguration ? runConfiguration->target() : nullptr; @@ -142,10 +61,8 @@ bool LocalApplicationRunControlFactory::canRun(RunConfiguration *runConfiguratio RunControl *LocalApplicationRunControlFactory::create(RunConfiguration *runConfiguration, Core::Id mode, QString *errorMessage) { Q_UNUSED(errorMessage) - return new LocalApplicationRunControl(runConfiguration, mode); + return new SimpleRunControl(runConfiguration, mode); } } // namespace Internal } // namespace ProjectExplorer - -#include "localapplicationruncontrol.moc" diff --git a/src/plugins/projectexplorer/runconfiguration.cpp b/src/plugins/projectexplorer/runconfiguration.cpp index 9ad838d3ca4..5f3e99c0c5d 100644 --- a/src/plugins/projectexplorer/runconfiguration.cpp +++ b/src/plugins/projectexplorer/runconfiguration.cpp @@ -32,18 +32,22 @@ #include "buildconfiguration.h" #include "environmentaspect.h" #include "kitinformation.h" +#include "runnables.h" + #include #include -#include #include +#include #include +#include #include #include -#include +#include #include +#include #ifdef Q_OS_OSX #include @@ -785,4 +789,89 @@ bool Runnable::canReUseOutputPane(const Runnable &other) const return d ? d->canReUseOutputPane(other.d) : (other.d.get() == 0); } + +// SimpleRunControlPrivate + +namespace Internal { + +class SimpleRunControlPrivate +{ +public: + ApplicationLauncher m_launcher; +}; + +} // Internal + +SimpleRunControl::SimpleRunControl(RunConfiguration *runConfiguration, Core::Id mode) + : RunControl(runConfiguration, mode), d(new Internal::SimpleRunControlPrivate) +{ + setRunnable(runConfiguration->runnable()); + setIcon(Utils::Icons::RUN_SMALL_TOOLBAR); +} + +SimpleRunControl::~SimpleRunControl() +{ + delete d; +} + +ApplicationLauncher &SimpleRunControl::applicationLauncher() +{ + return d->m_launcher; +} + +void SimpleRunControl::start() +{ + reportApplicationStart(); + d->m_launcher.disconnect(this); + + connect(&d->m_launcher, &ApplicationLauncher::appendMessage, + this, static_cast(&RunControl::appendMessage)); + connect(&d->m_launcher, &ApplicationLauncher::processStarted, + this, &SimpleRunControl::onProcessStarted); + connect(&d->m_launcher, &ApplicationLauncher::processExited, + this, &SimpleRunControl::onProcessFinished); + + QTC_ASSERT(runnable().is(), return); + auto r = runnable().as(); + if (r.executable.isEmpty()) { + appendMessage(RunControl::tr("No executable specified.") + QLatin1Char('\n'), Utils::ErrorMessageFormat); + reportApplicationStop(); + } else if (!QFileInfo::exists(r.executable)) { + appendMessage(RunControl::tr("Executable %1 does not exist.") + .arg(QDir::toNativeSeparators(r.executable)) + QLatin1Char('\n'), + Utils::ErrorMessageFormat); + reportApplicationStop(); + } else { + QString msg = RunControl::tr("Starting %1...").arg(QDir::toNativeSeparators(r.executable)) + QLatin1Char('\n'); + appendMessage(msg, Utils::NormalMessageFormat); + d->m_launcher.start(r); + setApplicationProcessHandle(d->m_launcher.applicationPID()); + } +} + +RunControl::StopResult SimpleRunControl::stop() +{ + d->m_launcher.stop(); + return StoppedSynchronously; +} + +void SimpleRunControl::onProcessStarted() +{ + // Console processes only know their pid after being started + setApplicationProcessHandle(d->m_launcher.applicationPID()); + bringApplicationToForeground(); +} + +void SimpleRunControl::onProcessFinished(int exitCode, QProcess::ExitStatus status) +{ + QString msg; + QString exe = runnable().as().executable; + if (status == QProcess::CrashExit) + msg = tr("%1 crashed.").arg(QDir::toNativeSeparators(exe)); + else + msg = tr("%1 exited with code %2").arg(QDir::toNativeSeparators(exe)).arg(exitCode); + appendMessage(msg + QLatin1Char('\n'), Utils::NormalMessageFormat); + reportApplicationStop(); +} + } // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/runconfiguration.h b/src/plugins/projectexplorer/runconfiguration.h index 753b3bf494f..e6ad09513e8 100644 --- a/src/plugins/projectexplorer/runconfiguration.h +++ b/src/plugins/projectexplorer/runconfiguration.h @@ -51,7 +51,10 @@ class RunConfigWidget; class RunControl; class Target; -namespace Internal { class RunControlPrivate; } +namespace Internal { +class RunControlPrivate; +class SimpleRunControlPrivate; +} // Internal /** * An interface for a hunk of global or per-project @@ -414,4 +417,21 @@ private: Internal::RunControlPrivate *d; }; +class PROJECTEXPLORER_EXPORT SimpleRunControl : public RunControl +{ +public: + SimpleRunControl(RunConfiguration *runConfiguration, Core::Id mode); + ~SimpleRunControl(); + + ApplicationLauncher &applicationLauncher(); + void start() override; + StopResult stop() override; + + virtual void onProcessStarted(); + virtual void onProcessFinished(int exitCode, QProcess::ExitStatus status); + +private: + Internal::SimpleRunControlPrivate *d; +}; + } // namespace ProjectExplorer diff --git a/src/plugins/pythoneditor/pythoneditorplugin.cpp b/src/plugins/pythoneditor/pythoneditorplugin.cpp index da63b5232ac..f926c13ecd1 100644 --- a/src/plugins/pythoneditor/pythoneditorplugin.cpp +++ b/src/plugins/pythoneditor/pythoneditorplugin.cpp @@ -197,6 +197,7 @@ public: bool fromMap(const QVariantMap &map) override; bool isEnabled() const override { return m_enabled; } QString disabledReason() const override; + Runnable runnable() const override; bool supportsDebugger() const { return true; } QString mainScript() const { return m_mainScript; } @@ -215,28 +216,6 @@ private: bool m_enabled; }; -class PythonRunControl : public RunControl -{ - Q_OBJECT -public: - PythonRunControl(PythonRunConfiguration *runConfiguration, Core::Id mode); - - void start() override; - StopResult stop() override; - -private: - void processStarted(); - void processExited(int exitCode, QProcess::ExitStatus status); - void slotAppendMessage(const QString &err, Utils::OutputFormat isError); - - ApplicationLauncher m_applicationLauncher; - QString m_interpreter; - QString m_mainScript; - QString m_commandLineArguments; - Utils::Environment m_environment; - ApplicationLauncher::Mode m_runMode; -}; - //////////////////////////////////////////////////////////////// PythonRunConfiguration::PythonRunConfiguration(Target *parent, Core::Id id) : @@ -307,6 +286,17 @@ QString PythonRunConfiguration::disabledReason() const return QString(); } +Runnable PythonRunConfiguration::runnable() const +{ + StandardRunnable r; + QtcProcess::addArg(&r.commandLineArguments, m_mainScript); + QtcProcess::addArgs(&r.commandLineArguments, extraAspect()->arguments()); + r.executable = m_interpreter; + r.runMode = extraAspect()->runMode(); + r.environment = extraAspect()->environment(); + return r; +} + QString PythonRunConfiguration::arguments() const { auto aspect = extraAspect(); @@ -732,95 +722,18 @@ public: bool PythonRunControlFactory::canRun(RunConfiguration *runConfiguration, Core::Id mode) const { - return mode == ProjectExplorer::Constants::NORMAL_RUN_MODE - && dynamic_cast(runConfiguration); + auto rc = dynamic_cast(runConfiguration); + return mode == ProjectExplorer::Constants::NORMAL_RUN_MODE && rc && !rc->interpreter().isEmpty(); } RunControl *PythonRunControlFactory::create(RunConfiguration *runConfiguration, Core::Id mode, QString *errorMessage) { Q_UNUSED(errorMessage) QTC_ASSERT(canRun(runConfiguration, mode), return 0); - return new PythonRunControl(static_cast(runConfiguration), mode); + return new SimpleRunControl(runConfiguration, mode); } -// PythonRunControl - -PythonRunControl::PythonRunControl(PythonRunConfiguration *rc, Core::Id mode) - : RunControl(rc, mode) -{ - setIcon(Utils::Icons::RUN_SMALL_TOOLBAR); - - m_interpreter = rc->interpreter(); - m_mainScript = rc->mainScript(); - m_runMode = rc->extraAspect()->runMode(); - m_commandLineArguments = rc->extraAspect()->arguments(); - m_environment = rc->extraAspect()->environment(); - - connect(&m_applicationLauncher, &ApplicationLauncher::appendMessage, - this, &PythonRunControl::slotAppendMessage); - connect(&m_applicationLauncher, &ApplicationLauncher::processStarted, - this, &PythonRunControl::processStarted); - connect(&m_applicationLauncher, &ApplicationLauncher::processExited, - this, &PythonRunControl::processExited); -} - -void PythonRunControl::start() -{ - reportApplicationStart(); - if (m_interpreter.isEmpty()) { - appendMessage(tr("No Python interpreter specified.") + '\n', Utils::ErrorMessageFormat); - reportApplicationStop(); - } else if (!QFileInfo::exists(m_interpreter)) { - appendMessage(tr("Python interpreter %1 does not exist.").arg(QDir::toNativeSeparators(m_interpreter)) + '\n', - Utils::ErrorMessageFormat); - reportApplicationStop(); - } else { - QString msg = tr("Starting %1...").arg(QDir::toNativeSeparators(m_interpreter)) + '\n'; - appendMessage(msg, Utils::NormalMessageFormat); - - StandardRunnable r; - QtcProcess::addArg(&r.commandLineArguments, m_mainScript); - QtcProcess::addArgs(&r.commandLineArguments, m_commandLineArguments); - r.executable = m_interpreter; - r.runMode = m_runMode; - r.environment = m_environment; - m_applicationLauncher.start(r); - - setApplicationProcessHandle(m_applicationLauncher.applicationPID()); - } -} - -PythonRunControl::StopResult PythonRunControl::stop() -{ - m_applicationLauncher.stop(); - return StoppedSynchronously; -} - -void PythonRunControl::slotAppendMessage(const QString &err, Utils::OutputFormat format) -{ - appendMessage(err, format); -} - -void PythonRunControl::processStarted() -{ - // Console processes only know their pid after being started - setApplicationProcessHandle(m_applicationLauncher.applicationPID()); - bringApplicationToForeground(); -} - -void PythonRunControl::processExited(int exitCode, QProcess::ExitStatus status) -{ - QString msg; - if (status == QProcess::CrashExit) { - msg = tr("%1 crashed") - .arg(QDir::toNativeSeparators(m_interpreter)); - } else { - msg = tr("%1 exited with code %2") - .arg(QDir::toNativeSeparators(m_interpreter)).arg(exitCode); - } - appendMessage(msg + '\n', Utils::NormalMessageFormat); - reportApplicationStop(); -} +// PythonRunConfigurationWidget void PythonRunConfigurationWidget::setInterpreter(const QString &interpreter) {