runconfiguration.h 13.2 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/qtcassert.h>
34
#include <utils/icon.h>
con's avatar
con committed
35

36
#include <QPointer>
37
#include <QWidget>
con's avatar
con committed
38

39
#include <functional>
40 41
#include <memory>

42
namespace Utils { class OutputFormatter; }
con's avatar
con committed
43

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

hjk's avatar
hjk committed
53 54
namespace Internal { class RunControlPrivate; }

55 56 57 58
// FIXME: This should also contain a handle to an remote device if used.
class PROJECTEXPLORER_EXPORT ProcessHandle
{
public:
59
    explicit ProcessHandle(quint64 pid = 0);
60

61 62 63 64 65 66
    bool isValid() const;
    void setPid(quint64 pid);
    quint64 pid() const;
    QString toString() const;

    bool equals(const ProcessHandle &) const;
67 68 69 70 71

private:
    quint64 m_pid;
};

72 73 74
inline bool operator==(const ProcessHandle &p1, const ProcessHandle &p2) { return p1.equals(p2); }
inline bool operator!=(const ProcessHandle &p1, const ProcessHandle &p2) { return !p1.equals(p2); }

75 76 77 78 79 80 81 82 83 84 85
/**
 * 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
86
    ISettingsAspect() { }
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110

    /// 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
111
class PROJECTEXPLORER_EXPORT IRunConfigurationAspect : public QObject
112
{
hjk's avatar
hjk committed
113 114
    Q_OBJECT

115
public:
116
    explicit IRunConfigurationAspect(RunConfiguration *runConfig);
Tobias Hunger's avatar
Tobias Hunger committed
117
    ~IRunConfigurationAspect() override;
118

119 120
    virtual IRunConfigurationAspect *create(RunConfiguration *runConfig) const = 0;
    virtual IRunConfigurationAspect *clone(RunConfiguration *runConfig) const;
121 122 123 124

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

126
    void setId(Core::Id id) { m_id = id; }
hjk's avatar
hjk committed
127
    void setDisplayName(const QString &displayName) { m_displayName = displayName; }
128 129
    void setProjectSettings(ISettingsAspect *settings);
    void setGlobalSettings(ISettingsAspect *settings);
hjk's avatar
hjk committed
130

131
    QString displayName() const { return m_displayName; }
hjk's avatar
hjk committed
132
    Core::Id id() const { return m_id; }
133 134 135 136 137 138 139 140 141
    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; }

142 143
protected:
    friend class RunConfiguration;
144 145
    virtual void fromMap(const QVariantMap &map);
    virtual void toMap(QVariantMap &data) const;
hjk's avatar
hjk committed
146 147 148

private:
    Core::Id m_id;
149
    QString m_displayName;
150 151 152 153
    bool m_useGlobalSettings = false;
    RunConfiguration *m_runConfiguration = nullptr;
    ISettingsAspect *m_projectSettings = nullptr; // Owned if present.
    ISettingsAspect *m_globalSettings = nullptr;  // Not owned.
154
    RunConfigWidgetCreator m_runConfigWidgetCreator;
155 156
};

157
class PROJECTEXPLORER_EXPORT Runnable
158
{
159 160 161 162 163
    struct Concept
    {
        virtual ~Concept() {}
        virtual Concept *clone() const = 0;
        virtual bool canReUseOutputPane(const std::unique_ptr<Concept> &other) const = 0;
164
        virtual void *typeId() const = 0;
165
    };
166

167 168
    template <class T>
    struct Model : public Concept
169
    {
170
        Model(const T &data) : m_data(data) {}
171

172 173 174 175
        Concept *clone() const override { return new Model(*this); }

        bool canReUseOutputPane(const std::unique_ptr<Concept> &other) const override
        {
176 177
            if (!other.get())
                return false;
178 179 180 181
            if (other->typeId() != typeId())
                return false;
            auto that = static_cast<const Model<T> *>(other.get());
            return m_data == that->m_data;
182 183
        }

184
        void *typeId() const override { return T::staticTypeId; }
185

186 187
        T m_data;
    };
188 189

public:
Tobias Hunger's avatar
Tobias Hunger committed
190 191
    Runnable() = default;
    Runnable(const Runnable &other) : d(other.d->clone()) { }
192 193
    Runnable(Runnable &&other) : d(std::move(other.d)) {}
    template <class T> Runnable(const T &data) : d(new Model<T>(data)) {}
194 195 196 197

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

    template <class T> bool is() const {
198
        return d.get() && (d.get()->typeId() == T::staticTypeId);
199 200 201
    }

    template <class T> const T &as() const {
202
        return static_cast<Model<T> *>(d.get())->m_data;
203 204
    }

205
    bool canReUseOutputPane(const Runnable &other) const;
206

207
private:
208
    std::unique_ptr<Concept> d;
209 210 211 212
};

class PROJECTEXPLORER_EXPORT Connection
{
213 214 215 216
    struct Concept
    {
        virtual ~Concept() {}
        virtual Concept *clone() const = 0;
217
        virtual void *typeId() const = 0;
218 219 220 221 222 223 224
    };

    template <class T>
    struct Model : public Concept
    {
        Model(const T &data) : m_data(data) { }
        Concept *clone() const override { return new Model(*this); }
225
        void *typeId() const override { return T::staticTypeId; }
226 227 228
        T m_data;
    };

229
public:
Tobias Hunger's avatar
Tobias Hunger committed
230 231
    Connection() = default;
    Connection(const Connection &other) : d(other.d->clone()) { }
Tim Jenssen's avatar
Tim Jenssen committed
232
    Connection(Connection &&other) /* MSVC 2013 doesn't want = default */ : d(std::move(other.d)) {}
233
    template <class T> Connection(const T &data) : d(new Model<T>(data)) {}
234 235 236 237

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

    template <class T> bool is() const {
238
        return d.get() && (d.get()->typeId() == T::staticTypeId);
239 240 241
    }

    template <class T> const T &as() const {
242
        return static_cast<Model<T> *>(d.get())->m_data;
243 244 245
    }

private:
246
    std::unique_ptr<Concept> d;
247 248
};

249
// Documentation inside.
250
class PROJECTEXPLORER_EXPORT RunConfiguration : public ProjectConfiguration
con's avatar
con committed
251 252
{
    Q_OBJECT
253

con's avatar
con committed
254
public:
255
    ~RunConfiguration() override;
con's avatar
con committed
256

257
    virtual bool isEnabled() const;
dt_'s avatar
dt_ committed
258
    virtual QString disabledReason() const;
259
    virtual QWidget *createConfigurationWidget() = 0;
260

Tobias Hunger's avatar
Tobias Hunger committed
261
    virtual bool isConfigured() const;
262
    // Pop up configuration dialog in case for example the executable is missing.
263 264
    enum ConfigurationState { Configured, UnConfigured, Waiting };
    // TODO rename function
265
    virtual ConfigurationState ensureConfigured(QString *errorMessage = nullptr);
con's avatar
con committed
266

Tobias Hunger's avatar
Tobias Hunger committed
267
    Target *target() const;
268

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

271 272
    bool fromMap(const QVariantMap &map) override;
    QVariantMap toMap() const override;
273

274
    QList<IRunConfigurationAspect *> extraAspects() const;
275
    IRunConfigurationAspect *extraAspect(Core::Id id) const;
hjk's avatar
hjk committed
276

277 278
    template <typename T> T *extraAspect() const
    {
279
        QTC_ASSERT(m_aspectsInitialized, return nullptr);
hjk's avatar
hjk committed
280 281 282
        foreach (IRunConfigurationAspect *aspect, m_aspects)
            if (T *result = qobject_cast<T *>(aspect))
                return result;
283
        return nullptr;
hjk's avatar
hjk committed
284 285
    }

286
    virtual Runnable runnable() const;
287
    virtual Abi abi() const;
288

289
    void addExtraAspects();
290
    void addExtraAspect(IRunConfigurationAspect *aspect);
291

292
signals:
293
    void enabledChanged();
294
    void requestRunActionsUpdate();
295
    void configurationFinished();
296

297
protected:
298
    RunConfiguration(Target *parent, Core::Id id);
Tobias Hunger's avatar
Tobias Hunger committed
299
    RunConfiguration(Target *parent, RunConfiguration *source);
300

301
    /// convenience function to get current build configuration.
302
    BuildConfiguration *activeBuildConfiguration() const;
303 304

private:
305 306
    void ctor();

307
    QList<IRunConfigurationAspect *> m_aspects;
308
    bool m_aspectsInitialized;
con's avatar
con committed
309 310
};

311
class PROJECTEXPLORER_EXPORT IRunConfigurationFactory : public QObject
con's avatar
con committed
312 313
{
    Q_OBJECT
314

con's avatar
con committed
315
public:
316
    explicit IRunConfigurationFactory(QObject *parent = nullptr);
317

318 319
    enum CreationMode {UserCreate, AutoCreate};
    virtual QList<Core::Id> availableCreationIds(Target *parent, CreationMode mode = UserCreate) const = 0;
320
    virtual QString displayNameForId(Core::Id id) const = 0;
321

322 323
    virtual bool canCreate(Target *parent, Core::Id id) const = 0;
    RunConfiguration *create(Target *parent, Core::Id id);
Tobias Hunger's avatar
Tobias Hunger committed
324
    virtual bool canRestore(Target *parent, const QVariantMap &map) const = 0;
325
    RunConfiguration *restore(Target *parent, const QVariantMap &map);
Tobias Hunger's avatar
Tobias Hunger committed
326 327 328
    virtual bool canClone(Target *parent, RunConfiguration *product) const = 0;
    virtual RunConfiguration *clone(Target *parent, RunConfiguration *product) = 0;

Tobias Hunger's avatar
Tobias Hunger committed
329
    static IRunConfigurationFactory *find(Target *parent, const QVariantMap &map);
330
    static IRunConfigurationFactory *find(Target *parent, RunConfiguration *rc);
Tobias Hunger's avatar
Tobias Hunger committed
331
    static QList<IRunConfigurationFactory *> find(Target *parent);
332 333 334

signals:
    void availableCreationIdsChanged();
335 336

private:
337
    virtual RunConfiguration *doCreate(Target *parent, Core::Id id) = 0;
338
    virtual RunConfiguration *doRestore(Target *parent, const QVariantMap &map) = 0;
con's avatar
con committed
339 340
};

341
class PROJECTEXPLORER_EXPORT IRunControlFactory : public QObject
con's avatar
con committed
342 343 344
{
    Q_OBJECT
public:
345
    explicit IRunControlFactory(QObject *parent = nullptr);
346

347 348
    virtual bool canRun(RunConfiguration *runConfiguration, Core::Id mode) const = 0;
    virtual RunControl *create(RunConfiguration *runConfiguration, Core::Id mode, QString *errorMessage) = 0;
con's avatar
con committed
349

350
    virtual IRunConfigurationAspect *createRunConfigurationAspect(RunConfiguration *rc);
351 352
};

Tobias Hunger's avatar
Tobias Hunger committed
353
class PROJECTEXPLORER_EXPORT RunConfigWidget : public QWidget
354 355 356
{
    Q_OBJECT

Tobias Hunger's avatar
Tobias Hunger committed
357
public:
358 359 360 361
    virtual QString displayName() const = 0;

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

364 365
class PROJECTEXPLORER_EXPORT RunControl : public QObject
{
con's avatar
con committed
366
    Q_OBJECT
Tobias Hunger's avatar
Tobias Hunger committed
367

con's avatar
con committed
368
public:
369 370
    enum StopResult {
        StoppedSynchronously, // Stopped.
371
        AsynchronousStop     // Stop sequence has been started
372 373
    };

374
    RunControl(RunConfiguration *runConfiguration, Core::Id mode);
375
    ~RunControl() override;
con's avatar
con committed
376
    virtual void start() = 0;
377

378
    virtual bool promptToStop(bool *optionalPrompt = nullptr) const;
379
    virtual StopResult stop() = 0;
con's avatar
con committed
380
    virtual bool isRunning() const = 0;
381
    virtual bool supportsReRunning() const { return true; }
382

383 384 385
    virtual QString displayName() const;
    void setDisplayName(const QString &displayName);

386 387
    void setIcon(const Utils::Icon &icon);
    Utils::Icon icon() const;
388

389 390
    ProcessHandle applicationProcessHandle() const;
    void setApplicationProcessHandle(const ProcessHandle &handle);
391
    Abi abi() const;
hjk's avatar
hjk committed
392
    IDevice::ConstPtr device() const;
393

394
    RunConfiguration *runConfiguration() const;
395
    Project *project() const;
396
    bool canReUseOutputPane(const RunControl *other) const;
397

con's avatar
con committed
398
    Utils::OutputFormatter *outputFormatter();
399
    Core::Id runMode() const;
400

hjk's avatar
hjk committed
401
    const Runnable &runnable() const;
402 403
    void setRunnable(const Runnable &runnable);

hjk's avatar
hjk committed
404
    const Connection &connection() const;
405 406
    void setConnection(const Connection &connection);

407 408
    virtual void appendMessage(const QString &msg, Utils::OutputFormat format);

409 410 411
public slots:
    void bringApplicationToForeground(qint64 pid);

con's avatar
con committed
412
signals:
413 414
    void appendMessageRequested(ProjectExplorer::RunControl *runControl,
                                const QString &msg, Utils::OutputFormat format);
con's avatar
con committed
415 416
    void started();
    void finished();
417
    void applicationProcessHandleChanged();
Thorbjørn Lindeijer's avatar
Thorbjørn Lindeijer committed
418

419 420 421 422
protected:
    bool showPromptToStopDialog(const QString &title, const QString &text,
                                const QString &stopButtonText = QString(),
                                const QString &cancelButtonText = QString(),
423
                                bool *prompt = nullptr) const;
424

con's avatar
con committed
425
private:
426
    void bringApplicationToForegroundInternal();
hjk's avatar
hjk committed
427
    Internal::RunControlPrivate *d;
con's avatar
con committed
428 429 430
};

} // namespace ProjectExplorer