runconfiguration.h 15.9 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
con's avatar
con committed
2
**
3
4
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
con's avatar
con committed
5
**
hjk's avatar
hjk committed
6
** This file is part of Qt Creator.
con's avatar
con committed
7
**
hjk's avatar
hjk committed
8
9
10
11
** 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
12
13
14
** 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.
15
**
16
17
18
19
20
21
22
** 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.
con's avatar
con committed
23
**
hjk's avatar
hjk committed
24
****************************************************************************/
hjk's avatar
hjk committed
25

Tobias Hunger's avatar
Tobias Hunger committed
26
#pragma once
con's avatar
con committed
27

28
#include "projectconfiguration.h"
29
#include "projectexplorerconstants.h"
30
#include "applicationlauncher.h"
hjk's avatar
hjk committed
31
#include "devicesupport/idevice.h"
con's avatar
con committed
32

33
#include <utils/port.h>
34
#include <utils/processhandle.h>
35
#include <utils/qtcassert.h>
36
#include <utils/icon.h>
con's avatar
con committed
37

38
#include <QPointer>
39
#include <QWidget>
con's avatar
con committed
40

41
#include <functional>
42
43
#include <memory>

44
namespace Utils { class OutputFormatter; }
con's avatar
con committed
45

46
47
namespace ProjectExplorer {
class Abi;
48
class BuildConfiguration;
49
class IRunConfigurationAspect;
50
class RunConfiguration;
51
class RunConfigWidget;
52
53
class RunControl;
class Target;
con's avatar
con committed
54

55
56
namespace Internal {
class RunControlPrivate;
57
class RunWorkerPrivate;
58
59
class SimpleRunControlPrivate;
} // Internal
hjk's avatar
hjk committed
60

61
62
63
64
65
66
67
68
69
70
71
/**
 * An interface for a hunk of global or per-project
 * configuration data.
 *
 */

class PROJECTEXPLORER_EXPORT ISettingsAspect : public QObject
{
    Q_OBJECT

public:
Tobias Hunger's avatar
Tobias Hunger committed
72
    ISettingsAspect() { }
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96

    /// Create a configuration widget for this settings aspect.
    virtual QWidget *createConfigWidget(QWidget *parent) = 0;
    /// "Virtual default constructor"
    virtual ISettingsAspect *create() const = 0;
    /// "Virtual copy constructor"
    ISettingsAspect *clone() const;

protected:
    ///
    friend class IRunConfigurationAspect;
    /// Converts current object into map for storage.
    virtual void toMap(QVariantMap &map) const = 0;
    /// Read object state from @p map.
    virtual void fromMap(const QVariantMap &map) = 0;
};


/**
 * An interface to facilitate switching between hunks of
 * global and per-project configuration data.
 *
 */

hjk's avatar
hjk committed
97
class PROJECTEXPLORER_EXPORT IRunConfigurationAspect : public QObject
98
{
hjk's avatar
hjk committed
99
100
    Q_OBJECT

101
public:
102
    explicit IRunConfigurationAspect(RunConfiguration *runConfig);
Tobias Hunger's avatar
Tobias Hunger committed
103
    ~IRunConfigurationAspect() override;
104

105
106
    virtual IRunConfigurationAspect *create(RunConfiguration *runConfig) const = 0;
    virtual IRunConfigurationAspect *clone(RunConfiguration *runConfig) const;
107
108
109
110

    using RunConfigWidgetCreator = std::function<RunConfigWidget *()>;
    void setRunConfigWidgetCreator(const RunConfigWidgetCreator &runConfigWidgetCreator);
    RunConfigWidget *createConfigurationWidget() const;
111

112
    void setId(Core::Id id) { m_id = id; }
hjk's avatar
hjk committed
113
    void setDisplayName(const QString &displayName) { m_displayName = displayName; }
114
115
    void setProjectSettings(ISettingsAspect *settings);
    void setGlobalSettings(ISettingsAspect *settings);
hjk's avatar
hjk committed
116

117
    QString displayName() const { return m_displayName; }
hjk's avatar
hjk committed
118
    Core::Id id() const { return m_id; }
119
120
121
122
123
124
125
126
127
    bool isUsingGlobalSettings() const { return m_useGlobalSettings; }
    void setUsingGlobalSettings(bool value);
    void resetProjectToGlobalSettings();

    ISettingsAspect *projectSettings() const { return m_projectSettings; }
    ISettingsAspect *globalSettings() const { return m_globalSettings; }
    ISettingsAspect *currentSettings() const;
    RunConfiguration *runConfiguration() const { return m_runConfiguration; }

128
129
protected:
    friend class RunConfiguration;
130
131
    virtual void fromMap(const QVariantMap &map);
    virtual void toMap(QVariantMap &data) const;
hjk's avatar
hjk committed
132
133
134

private:
    Core::Id m_id;
135
    QString m_displayName;
136
137
138
139
    bool m_useGlobalSettings = false;
    RunConfiguration *m_runConfiguration = nullptr;
    ISettingsAspect *m_projectSettings = nullptr; // Owned if present.
    ISettingsAspect *m_globalSettings = nullptr;  // Not owned.
140
    RunConfigWidgetCreator m_runConfigWidgetCreator;
141
142
};

143
class PROJECTEXPLORER_EXPORT Runnable
144
{
145
146
147
148
149
    struct Concept
    {
        virtual ~Concept() {}
        virtual Concept *clone() const = 0;
        virtual bool canReUseOutputPane(const std::unique_ptr<Concept> &other) const = 0;
150
        virtual QString displayName() const = 0;
151
        virtual void *typeId() const = 0;
152
    };
153

154
155
    template <class T>
    struct Model : public Concept
156
    {
157
        Model(const T &data) : m_data(data) {}
158

159
160
161
162
        Concept *clone() const override { return new Model(*this); }

        bool canReUseOutputPane(const std::unique_ptr<Concept> &other) const override
        {
163
164
            if (!other.get())
                return false;
165
166
167
168
            if (other->typeId() != typeId())
                return false;
            auto that = static_cast<const Model<T> *>(other.get());
            return m_data == that->m_data;
169
170
        }

171
172
        QString displayName() const override { return m_data.displayName(); }

173
        void *typeId() const override { return T::staticTypeId; }
174

175
176
        T m_data;
    };
177
178

public:
Tobias Hunger's avatar
Tobias Hunger committed
179
    Runnable() = default;
180
    Runnable(const Runnable &other) : d(other.d ? other.d->clone() : nullptr) { }
181
182
    Runnable(Runnable &&other) : d(std::move(other.d)) {}
    template <class T> Runnable(const T &data) : d(new Model<T>(data)) {}
183
184
185
186

    void operator=(Runnable other) { d = std::move(other.d); }

    template <class T> bool is() const {
187
        return d.get() && (d.get()->typeId() == T::staticTypeId);
188
189
190
    }

    template <class T> const T &as() const {
191
        return static_cast<Model<T> *>(d.get())->m_data;
192
193
    }

194
    bool canReUseOutputPane(const Runnable &other) const;
hjk's avatar
hjk committed
195
    QString displayName() const { return d ? d->displayName() : QString(); }
196

197
private:
198
    std::unique_ptr<Concept> d;
199
200
};

201
// Documentation inside.
202
class PROJECTEXPLORER_EXPORT RunConfiguration : public StatefulProjectConfiguration
con's avatar
con committed
203
204
{
    Q_OBJECT
205

con's avatar
con committed
206
public:
207
    ~RunConfiguration() override;
con's avatar
con committed
208

209
210
    QString disabledReason() const override;

211
    virtual QWidget *createConfigurationWidget() = 0;
212

Tobias Hunger's avatar
Tobias Hunger committed
213
    virtual bool isConfigured() const;
214
    // Pop up configuration dialog in case for example the executable is missing.
215
216
    enum ConfigurationState { Configured, UnConfigured, Waiting };
    // TODO rename function
217
    virtual ConfigurationState ensureConfigured(QString *errorMessage = nullptr);
con's avatar
con committed
218

Tobias Hunger's avatar
Tobias Hunger committed
219
    Target *target() const;
220

con's avatar
con committed
221
    virtual Utils::OutputFormatter *createOutputFormatter() const;
dt's avatar
dt committed
222

223
224
    bool fromMap(const QVariantMap &map) override;
    QVariantMap toMap() const override;
225

226
    QList<IRunConfigurationAspect *> extraAspects() const;
227
    IRunConfigurationAspect *extraAspect(Core::Id id) const;
hjk's avatar
hjk committed
228

229
230
    template <typename T> T *extraAspect() const
    {
hjk's avatar
hjk committed
231
232
233
        foreach (IRunConfigurationAspect *aspect, m_aspects)
            if (T *result = qobject_cast<T *>(aspect))
                return result;
234
        return nullptr;
hjk's avatar
hjk committed
235
236
    }

237
    virtual Runnable runnable() const;
238
    virtual Abi abi() const;
239

240
241
242
243
    // Return the name of the build system target that created this run configuration.
    // May return an empty string if no target built the executable!
    virtual QString buildSystemTarget() const { return QString(); }

244
    void addExtraAspect(IRunConfigurationAspect *aspect);
245

246
247
    static RunConfiguration *startupRunConfiguration();

248
249
250
251
252
253
    using AspectFactory = std::function<IRunConfigurationAspect *(RunConfiguration *)>;
    template <class T> static void registerAspect()
    {
        addAspectFactory([](RunConfiguration *rc) { return new T(rc); });
    }

254
signals:
255
    void requestRunActionsUpdate();
256
    void configurationFinished();
257

258
protected:
259
    RunConfiguration(Target *parent, Core::Id id);
Tobias Hunger's avatar
Tobias Hunger committed
260
    RunConfiguration(Target *parent, RunConfiguration *source);
261

262
    /// convenience function to get current build configuration.
263
    BuildConfiguration *activeBuildConfiguration() const;
264

265
266
    virtual void updateEnabledState();

267
private:
268
269
    void ctor();

270
    static void addAspectFactory(const AspectFactory &aspectFactory);
271

272
    QList<IRunConfigurationAspect *> m_aspects;
con's avatar
con committed
273
274
};

275
class PROJECTEXPLORER_EXPORT IRunConfigurationFactory : public QObject
con's avatar
con committed
276
277
{
    Q_OBJECT
278

con's avatar
con committed
279
public:
280
    explicit IRunConfigurationFactory(QObject *parent = nullptr);
281

282
283
    enum CreationMode {UserCreate, AutoCreate};
    virtual QList<Core::Id> availableCreationIds(Target *parent, CreationMode mode = UserCreate) const = 0;
284
    virtual QString displayNameForId(Core::Id id) const = 0;
285

286
287
    virtual bool canCreate(Target *parent, Core::Id id) const = 0;
    RunConfiguration *create(Target *parent, Core::Id id);
Tobias Hunger's avatar
Tobias Hunger committed
288
    virtual bool canRestore(Target *parent, const QVariantMap &map) const = 0;
289
    RunConfiguration *restore(Target *parent, const QVariantMap &map);
Tobias Hunger's avatar
Tobias Hunger committed
290
291
292
    virtual bool canClone(Target *parent, RunConfiguration *product) const = 0;
    virtual RunConfiguration *clone(Target *parent, RunConfiguration *product) = 0;

Tobias Hunger's avatar
Tobias Hunger committed
293
    static IRunConfigurationFactory *find(Target *parent, const QVariantMap &map);
294
    static IRunConfigurationFactory *find(Target *parent, RunConfiguration *rc);
Tobias Hunger's avatar
Tobias Hunger committed
295
    static QList<IRunConfigurationFactory *> find(Target *parent);
296
297
298

signals:
    void availableCreationIdsChanged();
299
300

private:
301
    virtual RunConfiguration *doCreate(Target *parent, Core::Id id) = 0;
302
    virtual RunConfiguration *doRestore(Target *parent, const QVariantMap &map) = 0;
con's avatar
con committed
303
304
};

Tobias Hunger's avatar
Tobias Hunger committed
305
class PROJECTEXPLORER_EXPORT RunConfigWidget : public QWidget
306
307
308
{
    Q_OBJECT

Tobias Hunger's avatar
Tobias Hunger committed
309
public:
310
311
312
313
    virtual QString displayName() const = 0;

signals:
    void displayNameChanged(const QString &);
con's avatar
con committed
314
315
};

316
317
318
319
320
321
322
323
324
325
326
327
class PROJECTEXPLORER_EXPORT RunWorker : public QObject
{
    Q_OBJECT

public:
    explicit RunWorker(RunControl *runControl);
    ~RunWorker() override;

    RunControl *runControl() const;

    void addDependency(RunWorker *dependency);

328
329
    void setDisplayName(const QString &id) { setId(id); } // FIXME: Obsoleted by setId.
    void setId(const QString &id);
330
331
332
333
334

    void setStartTimeout(int ms);
    void setStopTimeout(int ms);

    void recordData(const QString &channel, const QVariant &data);
hjk's avatar
hjk committed
335
    QVariant recordedData(const QString &channel) const;
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350

    // Part of read-only interface of RunControl for convenience.
    void appendMessage(const QString &msg, Utils::OutputFormat format);
    IDevice::ConstPtr device() const;
    const Runnable &runnable() const;
    Core::Id runMode() const;

    // States
    void initiateStart();
    void reportStarted();

    void initiateStop();
    void reportStopped();

    void reportFailure(const QString &msg = QString());
351
352
    void setSupportsReRunning(bool reRunningSupported);
    bool supportsReRunning() const;
353
    bool hasFailed() const;
354
355

    static QString userMessageForProcessError(QProcess::ProcessError, const QString &programName);
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

signals:
    void started();
    void stopped();

protected:
    void virtual start();
    void virtual stop();
    void virtual onFinished() {}

private:
    friend class Internal::RunControlPrivate;
    friend class Internal::RunWorkerPrivate;
    Internal::RunWorkerPrivate *d;
};

372
373
374
375
376
377
378
379
/**
 * 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.
 */

380
381
class PROJECTEXPLORER_EXPORT RunControl : public QObject
{
con's avatar
con committed
382
    Q_OBJECT
Tobias Hunger's avatar
Tobias Hunger committed
383

con's avatar
con committed
384
public:
385
    RunControl(RunConfiguration *runConfiguration, Core::Id mode);
386
    ~RunControl() override;
387

388
    void initiateStart();
389
    void initiateReStart();
390
    void initiateStop();
391
    void initiateFinish();
392

393
394
    bool promptToStop(bool *optionalPrompt = nullptr) const;
    void setPromptToStop(const std::function<bool(bool *)> &promptToStop);
395

396
    bool supportsReRunning() const;
397

398
399
400
    virtual QString displayName() const;
    void setDisplayName(const QString &displayName);

401
    bool isRunning() const;
402
403
    bool isStarting() const;
    bool isStopping() const;
404
    bool isStopped() const;
405

406
407
    void setIcon(const Utils::Icon &icon);
    Utils::Icon icon() const;
408

409
410
    Utils::ProcessHandle applicationProcessHandle() const;
    void setApplicationProcessHandle(const Utils::ProcessHandle &handle);
411
    Abi abi() const;
hjk's avatar
hjk committed
412
    IDevice::ConstPtr device() const;
413

414
    RunConfiguration *runConfiguration() const;
415
    Project *project() const;
416
    bool canReUseOutputPane(const RunControl *other) const;
417

418
    Utils::OutputFormatter *outputFormatter() const;
419
    Core::Id runMode() const;
420

hjk's avatar
hjk committed
421
    const Runnable &runnable() const;
422
423
    void setRunnable(const Runnable &runnable);

424
    virtual void appendMessage(const QString &msg, Utils::OutputFormat format);
425

426
427
428
429
    static bool showPromptToStopDialog(const QString &title, const QString &text,
                                       const QString &stopButtonText = QString(),
                                       const QString &cancelButtonText = QString(),
                                       bool *prompt = nullptr);
430

431
432
    RunWorker *createWorker(Core::Id id);

433
    using WorkerCreator = std::function<RunWorker *(RunControl *)>;
434
435
    using Constraint = std::function<bool(RunConfiguration *)>;

436
437
438
439
440
441
442
    static void registerWorkerCreator(Core::Id id, const WorkerCreator &workerCreator);

    static void registerWorker(Core::Id runMode, const WorkerCreator &producer,
                               const Constraint &constraint = {})
    {
        addWorkerFactory({runMode, constraint, producer});
    }
443
    template <class Worker>
444
    static void registerWorker(Core::Id runMode, const Constraint &constraint, int priority = 0)
445
446
    {
        auto producer = [](RunControl *rc) { return new Worker(rc); };
447
        addWorkerFactory({runMode, constraint, producer, priority});
448
449
    }
    template <class Config, class Worker>
450
    static void registerWorker(Core::Id runMode, int priority = 0)
451
    {
452
        auto constraint = [](RunConfiguration *runConfig) { return qobject_cast<Config *>(runConfig) != nullptr; };
453
        auto producer = [](RunControl *rc) { return new Worker(rc); };
454
        addWorkerFactory({runMode, constraint, producer, priority});
455
456
457
458
459
    }

    struct WorkerFactory {
        Core::Id runMode;
        Constraint constraint;
460
        WorkerCreator producer;
461
        int priority = 0;
462

463
464
465
        WorkerFactory(const Core::Id &mode, Constraint constr, const WorkerCreator &prod,
                      int prio = 0)
            : runMode(mode), constraint(constr), producer(prod), priority(prio) {}
466
        bool canRun(RunConfiguration *runConfiguration, Core::Id runMode) const;
467
468
    };

469
    static WorkerCreator producer(RunConfiguration *runConfiguration, Core::Id runMode);
470

con's avatar
con committed
471
signals:
472
473
    void appendMessageRequested(ProjectExplorer::RunControl *runControl,
                                const QString &msg, Utils::OutputFormat format);
474
    void aboutToStart();
475
    void started();
476
    void stopped();
477
    void finished();
478
    void applicationProcessHandleChanged(QPrivateSignal); // Use setApplicationProcessHandle
Thorbjørn Lindeijer's avatar
Thorbjørn Lindeijer committed
479

con's avatar
con committed
480
private:
481
482
    friend class RunWorker;
    friend class Internal::RunWorkerPrivate;
483

484
    static void addWorkerFactory(const WorkerFactory &workerFactory);
hjk's avatar
hjk committed
485
    Internal::RunControlPrivate *d;
con's avatar
con committed
486
487
};

488

489
490
491
492
493
/**
 * A simple TargetRunner for cases where a plain ApplicationLauncher is
 * sufficient for running purposes.
 */

494
class PROJECTEXPLORER_EXPORT SimpleTargetRunner : public RunWorker
495
496
497
498
{
public:
    explicit SimpleTargetRunner(RunControl *runControl);

hjk's avatar
hjk committed
499
500
    void setRunnable(const Runnable &runnable);

501
protected:
502
503
504
    void start() override;
    void stop() override;

505
private:
506
507
    void onProcessStarted();
    void onProcessFinished(int exitCode, QProcess::ExitStatus status);
hjk's avatar
hjk committed
508
    void onProcessError(QProcess::ProcessError error);
509
510

    ApplicationLauncher m_launcher;
hjk's avatar
hjk committed
511
    Runnable m_runnable;
512
    bool m_stopReported = false;
513
514
};

con's avatar
con committed
515
} // namespace ProjectExplorer