diff options
author | hjk <hjk@qt.io> | 2019-03-13 08:06:08 +0100 |
---|---|---|
committer | hjk <hjk@qt.io> | 2019-03-13 14:44:46 +0000 |
commit | 164ae1428ed450703dbc89e367bbc2afa91476cf (patch) | |
tree | cf7f5fb7d8b5307a11662b92341bc1b607824688 /src/plugins/projectexplorer/runcontrol.h | |
parent | 1fcb8a56e0a12c8a74f548c901bc5874bca9bc30 (diff) |
ProjectExplorer: Move RunControl related classes to separate file pair
Change-Id: I5da56f80336673d595907abcc797f628be680cd5
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
Diffstat (limited to 'src/plugins/projectexplorer/runcontrol.h')
-rw-r--r-- | src/plugins/projectexplorer/runcontrol.h | 330 |
1 files changed, 330 insertions, 0 deletions
diff --git a/src/plugins/projectexplorer/runcontrol.h b/src/plugins/projectexplorer/runcontrol.h new file mode 100644 index 0000000000..7afdbc5c66 --- /dev/null +++ b/src/plugins/projectexplorer/runcontrol.h @@ -0,0 +1,330 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://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 "applicationlauncher.h" +#include "buildtargetinfo.h" +#include "devicesupport/idevice.h" +#include "projectexplorerconstants.h" +#include "runconfiguration.h" + +#include <utils/environment.h> +#include <utils/port.h> +#include <utils/processhandle.h> +#include <utils/qtcassert.h> +#include <utils/icon.h> + +#include <QHash> +#include <QPointer> +#include <QVariant> +#include <QWidget> + +#include <functional> +#include <memory> + +namespace Utils { +class MacroExpander; +class OutputFormatter; +} // Utils + +namespace ProjectExplorer { +class BuildConfiguration; +class GlobalOrProjectAspect; +class Node; +class RunConfigurationFactory; +class RunConfiguration; +class RunConfigurationCreationInfo; +class RunControl; +class RunWorkerFactory; +class Target; + +namespace Internal { +class RunControlPrivate; +class RunWorkerPrivate; +} // Internal + + +class PROJECTEXPLORER_EXPORT Runnable +{ +public: + Runnable() = default; + + QString executable; + QString commandLineArguments; + QString workingDirectory; + Utils::Environment environment; + IDevice::ConstPtr device; // Override the kit's device. Keep unset by default. + QHash<Core::Id, QVariant> extraData; + + // FIXME: Not necessarily a display name + QString displayName() const { return executable; } +}; + +class PROJECTEXPLORER_EXPORT RunWorker : public QObject +{ + Q_OBJECT + +public: + explicit RunWorker(RunControl *runControl); + ~RunWorker() override; + + RunControl *runControl() const; + + void addStartDependency(RunWorker *dependency); + void addStopDependency(RunWorker *dependency); + + void setId(const QString &id); + + void setStartTimeout(int ms, const std::function<void()> &callback = {}); + void setStopTimeout(int ms, const std::function<void()> &callback = {}); + + void recordData(const QString &channel, const QVariant &data); + QVariant recordedData(const QString &channel) const; + + // Part of read-only interface of RunControl for convenience. + void appendMessage(const QString &msg, Utils::OutputFormat format, bool appendNewLine = true); + IDevice::ConstPtr device() const; + const Runnable &runnable() const; + Core::Id runMode() const; + + // States + void initiateStart(); + void reportStarted(); + + void initiateStop(); + void reportStopped(); + + void reportDone(); + + void reportFailure(const QString &msg = QString()); + void setSupportsReRunning(bool reRunningSupported); + bool supportsReRunning() const; + + static QString userMessageForProcessError(QProcess::ProcessError, const QString &programName); + + bool isEssential() const; + void setEssential(bool essential); + +signals: + void started(); + void stopped(); + +protected: + void virtual start(); + void virtual stop(); + void virtual onFinished() {} + +private: + friend class Internal::RunControlPrivate; + friend class Internal::RunWorkerPrivate; + const std::unique_ptr<Internal::RunWorkerPrivate> d; +}; + +class PROJECTEXPLORER_EXPORT RunWorkerFactory +{ +public: + using WorkerCreator = std::function<RunWorker *(RunControl *)>; + using Constraint = std::function<bool(RunConfiguration *)>; + + RunWorkerFactory(); + virtual ~RunWorkerFactory(); + + bool canRun(RunConfiguration *runConfiguration, Core::Id runMode) const; + + void setProducer(const WorkerCreator &producer); + void addConstraint(const Constraint &constraint); + void addSupportedRunMode(Core::Id runMode); + + WorkerCreator producer() const { return m_producer; } + +private: + // FIXME: That's temporary until ownership has been transferred to + // the individual plugins. + friend class ProjectExplorerPlugin; + static void destroyRemainingRunWorkerFactories(); + + QList<Core::Id> m_supportedRunModes; + QList<Constraint> m_constraints; + WorkerCreator m_producer; +}; + +/** + * A RunControl controls the running of an application or tool + * on a target device. It controls start and stop, and handles + * application output. + * + * RunControls are created by RunControlFactories. + */ + +class PROJECTEXPLORER_EXPORT RunControl : public QObject +{ + Q_OBJECT + +public: + explicit RunControl(Core::Id mode); + ~RunControl() override; + + void setRunConfiguration(RunConfiguration *runConfig); + void setTarget(Target *target); + void setKit(Kit *kit); + + void initiateStart(); + void initiateReStart(); + void initiateStop(); + void forceStop(); + void initiateFinish(); + + bool promptToStop(bool *optionalPrompt = nullptr) const; + void setPromptToStop(const std::function<bool(bool *)> &promptToStop); + + bool supportsReRunning() const; + + virtual QString displayName() const; + void setDisplayName(const QString &displayName); + + bool isRunning() const; + bool isStarting() const; + bool isStopping() const; + bool isStopped() const; + + void setIcon(const Utils::Icon &icon); + Utils::Icon icon() const; + + Utils::ProcessHandle applicationProcessHandle() const; + void setApplicationProcessHandle(const Utils::ProcessHandle &handle); + IDevice::ConstPtr device() const; + + RunConfiguration *runConfiguration() const; // FIXME: Remove. + // FIXME: Try to cut down to amount of functions. + Target *target() const; + Project *project() const; + Kit *kit() const; + Utils::MacroExpander *macroExpander() const; + ProjectConfigurationAspect *aspect(Core::Id id) const; + template <typename T> T *aspect() const { + return runConfiguration() ? runConfiguration()->aspect<T>() : nullptr; + } + + template <typename T> + auto aspectData() -> decltype(T::runData(nullptr, this)) { + if (T *asp = aspect<T>()) + return T::runData(asp, this); + return {}; + } + + ISettingsAspect *settings(Core::Id id) const; + QString buildKey() const; + BuildTargetInfo buildTargetInfo() const; + + Utils::OutputFormatter *outputFormatter() const; + Core::Id runMode() const; + + const Runnable &runnable() const; + void setRunnable(const Runnable &runnable); + + static bool showPromptToStopDialog(const QString &title, const QString &text, + const QString &stopButtonText = QString(), + const QString &cancelButtonText = QString(), + bool *prompt = nullptr); + + RunWorker *createWorker(Core::Id id); + + using WorkerCreator = RunWorkerFactory::WorkerCreator; + using Constraint = RunWorkerFactory::Constraint; + + static void registerWorkerCreator(Core::Id id, const WorkerCreator &workerCreator); + + static void registerWorker(Core::Id runMode, const WorkerCreator &producer, + const Constraint &constraint = {}) + { + auto factory = new RunWorkerFactory; + factory->setProducer(producer); + factory->addSupportedRunMode(runMode); + factory->addConstraint(constraint); + } + template <class Worker> + static void registerWorker(Core::Id runMode, const Constraint &constraint) + { + auto factory = new RunWorkerFactory; + factory->setProducer([](RunControl *rc) { return new Worker(rc); }); + factory->addSupportedRunMode(runMode); + factory->addConstraint(constraint); + } + + static WorkerCreator producer(RunConfiguration *runConfiguration, Core::Id runMode); + +signals: + void appendMessage(const QString &msg, Utils::OutputFormat format); + void aboutToStart(); + void started(); + void stopped(); + void finished(); + void applicationProcessHandleChanged(QPrivateSignal); // Use setApplicationProcessHandle + +private: + void setDevice(const IDevice::ConstPtr &device); + + friend class RunWorker; + friend class Internal::RunWorkerPrivate; + + const std::unique_ptr<Internal::RunControlPrivate> d; +}; + + +/** + * A simple TargetRunner for cases where a plain ApplicationLauncher is + * sufficient for running purposes. + */ + +class PROJECTEXPLORER_EXPORT SimpleTargetRunner : public RunWorker +{ + Q_OBJECT + +public: + explicit SimpleTargetRunner(RunControl *runControl); + + void setRunnable(const Runnable &runnable); + + void setDevice(const IDevice::ConstPtr &device); + IDevice::ConstPtr device() const; + +protected: + void start() override; + void stop() override; + +private: + void onProcessStarted(); + void onProcessFinished(int exitCode, QProcess::ExitStatus status); + void onProcessError(QProcess::ProcessError error); + + ApplicationLauncher m_launcher; + Runnable m_runnable; + IDevice::ConstPtr m_device; + bool m_stopReported = false; + bool m_useTerminal = false; +}; + +} // namespace ProjectExplorer |