// Copyright (C) 2019 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #pragma once #include "devicesupport/idevicefwd.h" #include "runconfiguration.h" #include #include #include #include #include #include #include #include // FIXME: Remove #include #include #include namespace Tasking { class Group; } namespace Utils { class Icon; class MacroExpander; class OutputLineParser; class ProcessRunData; class Process; } // Utils namespace ProjectExplorer { class RunConfiguration; class RunControl; class Target; namespace Internal { class RunControlPrivate; class RunWorkerPrivate; class SimpleTargetRunnerPrivate; } // Internal 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 recordData(const Utils::Key &channel, const QVariant &data); QVariant recordedData(const Utils::Key &channel) const; // Part of read-only interface of RunControl for convenience. void appendMessage(const QString &msg, Utils::OutputFormat format, bool appendNewLine = true); IDeviceConstPtr device() const; // States void initiateStart(); void reportStarted(); void initiateStop(); void reportStopped(); void reportDone(); void reportFailure(const QString &msg = QString()); void setSupportsReRunning(bool reRunningSupported); static QString userMessageForProcessError(QProcess::ProcessError, const Utils::FilePath &programName); bool isEssential() const; void setEssential(bool essential); signals: void started(); void stopped(); protected: void virtual start(); void virtual stop(); private: friend class Internal::RunControlPrivate; friend class Internal::RunWorkerPrivate; const std::unique_ptr d; }; class PROJECTEXPLORER_EXPORT RunWorkerFactory { public: using WorkerCreator = std::function; RunWorkerFactory(); ~RunWorkerFactory(); static void dumpAll(); // For debugging only. protected: template void setProduct() { setProducer([](RunControl *rc) { return new Worker(rc); }); } void setId(Utils::Id id) { m_id = id; } void setProducer(const WorkerCreator &producer); void setSupportedRunConfigs(const QList &runConfigs); void addSupportedRunMode(Utils::Id runMode); void addSupportedRunConfig(Utils::Id runConfig); void addSupportedDeviceType(Utils::Id deviceType); void addSupportForLocalRunConfigs(); void cloneProduct(Utils::Id exitstingStepId, Utils::Id overrideId = Utils::Id()); private: friend class RunControl; bool canCreate(Utils::Id runMode, Utils::Id deviceType, const QString &runConfigId) const; RunWorker *create(RunControl *runControl) const; WorkerCreator m_producer; QList m_supportedRunModes; QList m_supportedRunConfigurations; QList m_supportedDeviceTypes; Utils::Id m_id; }; /** * 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(Utils::Id mode); ~RunControl() override; void setTarget(Target *target); void setKit(Kit *kit); void copyDataFromRunConfiguration(RunConfiguration *runConfig); void copyDataFromRunControl(RunControl *runControl); void setAutoDeleteOnStop(bool autoDelete); void setRunRecipe(const Tasking::Group &group); void initiateStart(); void initiateReStart(); void initiateStop(); void forceStop(); bool promptToStop(bool *optionalPrompt = nullptr) const; void setPromptToStop(const std::function &promptToStop); // Note: Works only in the task tree mode void setSupportsReRunning(bool reRunningSupported); bool supportsReRunning() const; QString displayName() const; void setDisplayName(const QString &displayName); bool isRunning() const; bool isStarting() const; bool isStopped() const; void setIcon(const Utils::Icon &icon); Utils::Icon icon() const; Utils::ProcessHandle applicationProcessHandle() const; void setApplicationProcessHandle(const Utils::ProcessHandle &handle); IDeviceConstPtr device() const; // FIXME: Try to cut down to amount of functions. Target *target() const; Project *project() const; Kit *kit() const; const Utils::MacroExpander *macroExpander() const; const Utils::BaseAspect::Data *aspectData(Utils::Id instanceId) const; const Utils::BaseAspect::Data *aspectData(Utils::BaseAspect::Data::ClassId classId) const; template const typename T::Data *aspectData() const { return dynamic_cast(aspectData(&T::staticMetaObject)); } QString buildKey() const; Utils::FilePath buildDirectory() const; Utils::Environment buildEnvironment() const; Utils::Store settingsData(Utils::Id id) const; Utils::FilePath targetFilePath() const; Utils::FilePath projectFilePath() const; void setupFormatter(Utils::OutputFormatter *formatter) const; Utils::Id runMode() const; bool isPrintEnvironmentEnabled() const; const Utils::ProcessRunData &runnable() const; const Utils::CommandLine &commandLine() const; void setCommandLine(const Utils::CommandLine &command); const Utils::FilePath &workingDirectory() const; void setWorkingDirectory(const Utils::FilePath &workingDirectory); const Utils::Environment &environment() const; void setEnvironment(const Utils::Environment &environment); const QVariantHash &extraData() const; void setExtraData(const QVariantHash &extraData); static bool showPromptToStopDialog(const QString &title, const QString &text, const QString &stopButtonText = QString(), const QString &cancelButtonText = QString(), bool *prompt = nullptr); static void provideAskPassEntry(Utils::Environment &env); RunWorker *createWorker(Utils::Id workerId); bool createMainWorker(); static bool canRun(Utils::Id runMode, Utils::Id deviceType, Utils::Id runConfigId); void postMessage(const QString &msg, Utils::OutputFormat format, bool appendNewLine = true); signals: void appendMessage(const QString &msg, Utils::OutputFormat format); void aboutToStart(); void started(); void stopped(); void applicationProcessHandleChanged(QPrivateSignal); private: void setDevice(const IDeviceConstPtr &device); friend class RunWorker; friend class Internal::RunWorkerPrivate; const std::unique_ptr 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); ~SimpleTargetRunner() override; protected: void setStartModifier(const std::function &startModifier); Utils::CommandLine commandLine() const; void setCommandLine(const Utils::CommandLine &commandLine); void setEnvironment(const Utils::Environment &environment); void setWorkingDirectory(const Utils::FilePath &workingDirectory); void setProcessMode(Utils::ProcessMode processMode); Utils::Process *process() const; void suppressDefaultStdOutHandling(); void forceRunOnHost(); void addExtraData(const QString &key, const QVariant &value); private: void start() final; void stop() final; const Utils::ProcessRunData &runnable() const = delete; void setRunnable(const Utils::ProcessRunData &) = delete; const std::unique_ptr d; }; class PROJECTEXPLORER_EXPORT SimpleTargetRunnerFactory : public RunWorkerFactory { public: explicit SimpleTargetRunnerFactory(const QList &runConfig); }; PROJECTEXPLORER_EXPORT void addOutputParserFactory(const std::function &); PROJECTEXPLORER_EXPORT QList createOutputParsers(Target *target); } // namespace ProjectExplorer