diff --git a/src/plugins/debugger/debuggerruncontrolfactory.h b/src/plugins/debugger/debuggerruncontrolfactory.h index 5ef663cbff35973249b0b1566d0cafa93f9b4619..6368da011855d303e6c0020740ecf29150bc1083 100644 --- a/src/plugins/debugger/debuggerruncontrolfactory.h +++ b/src/plugins/debugger/debuggerruncontrolfactory.h @@ -65,7 +65,7 @@ public: private: QString displayName() const; - QWidget *createConfigurationWidget(RunConfiguration *runConfiguration); + ProjectExplorer::RunConfigWidget *createConfigurationWidget(RunConfiguration *runConfiguration); const unsigned m_enabledEngines; }; diff --git a/src/plugins/debugger/debuggerrunner.cpp b/src/plugins/debugger/debuggerrunner.cpp index 02a8626fa367a98d980f5a7d581f1122fbc92f38..62683ceef599ff3908288f345587744c48fb1470 100644 --- a/src/plugins/debugger/debuggerrunner.cpp +++ b/src/plugins/debugger/debuggerrunner.cpp @@ -704,7 +704,7 @@ RunControl *DebuggerRunControlFactory::create return create(sp, runConfiguration); } -QWidget *DebuggerRunControlFactory::createConfigurationWidget +RunConfigWidget *DebuggerRunControlFactory::createConfigurationWidget (RunConfiguration *runConfiguration) { // NBS TODO: Add GDB-specific configuration widget diff --git a/src/plugins/projectexplorer/localapplicationruncontrol.cpp b/src/plugins/projectexplorer/localapplicationruncontrol.cpp index 6bd9ebaafd6a6751e923e66b95431d66ba4057e4..d932a19f7d2778d8f07c1f945b4f86ea7f11a870 100644 --- a/src/plugins/projectexplorer/localapplicationruncontrol.cpp +++ b/src/plugins/projectexplorer/localapplicationruncontrol.cpp @@ -70,10 +70,10 @@ RunControl *LocalApplicationRunControlFactory::create(ProjectExplorer::RunConfig return new LocalApplicationRunControl(qobject_cast<LocalApplicationRunConfiguration *>(runConfiguration), mode); } -QWidget *LocalApplicationRunControlFactory::createConfigurationWidget(RunConfiguration *runConfiguration) +RunConfigWidget *LocalApplicationRunControlFactory::createConfigurationWidget(RunConfiguration *runConfiguration) { Q_UNUSED(runConfiguration) - return new QLabel("TODO add Configuration widget"); + return 0; } // ApplicationRunControl diff --git a/src/plugins/projectexplorer/localapplicationruncontrol.h b/src/plugins/projectexplorer/localapplicationruncontrol.h index 8717bdf5f982f014bee96b5e9ddbd2f08e8bc58c..061f4a317bfb342ca6fa2c9161bd81fccc211489 100644 --- a/src/plugins/projectexplorer/localapplicationruncontrol.h +++ b/src/plugins/projectexplorer/localapplicationruncontrol.h @@ -51,7 +51,7 @@ public: virtual bool canRun(RunConfiguration *runConfiguration, const QString &mode) const; virtual QString displayName() const; virtual RunControl* create(RunConfiguration *runConfiguration, const QString &mode); - virtual QWidget *createConfigurationWidget(RunConfiguration *runConfiguration); + virtual RunConfigWidget *createConfigurationWidget(RunConfiguration *runConfiguration); }; class LocalApplicationRunControl : public RunControl diff --git a/src/plugins/projectexplorer/runconfiguration.cpp b/src/plugins/projectexplorer/runconfiguration.cpp index 0b2a62266eefb0ef0cf92959ad53f8cbf5fd92e2..2790b0ec271b3cc82dcb024c583c5d0ecc82eba3 100644 --- a/src/plugins/projectexplorer/runconfiguration.cpp +++ b/src/plugins/projectexplorer/runconfiguration.cpp @@ -160,6 +160,7 @@ RunConfiguration::RunConfiguration(Target *target, const QString &id) : m_qmlDebugServerPort(Constants::QML_DEFAULT_DEBUG_SERVER_PORT) { Q_ASSERT(target); + addExtraAspects(); } RunConfiguration::RunConfiguration(Target *target, RunConfiguration *source) : @@ -168,10 +169,20 @@ RunConfiguration::RunConfiguration(Target *target, RunConfiguration *source) : m_useQmlDebugger(source->useQmlDebugger()) { Q_ASSERT(target); + addExtraAspects(); } RunConfiguration::~RunConfiguration() { + qDeleteAll(m_aspects); +} + +void RunConfiguration::addExtraAspects() +{ + ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); + foreach (IRunControlFactory *factory, pm->getObjects<IRunControlFactory>()) + if (IRunConfigurationAspect *aspect = factory->createRunConfigurationAspect()) + m_aspects.append(aspect); } bool RunConfiguration::isEnabled(BuildConfiguration *bc) const @@ -239,6 +250,9 @@ QVariantMap RunConfiguration::toMap() const map.insert(QLatin1String(USE_CPP_DEBUGGER_KEY), m_useCppDebugger); map.insert(QLatin1String(USE_QML_DEBUGGER_KEY), m_useQmlDebugger); map.insert(QLatin1String(QML_DEBUG_SERVER_PORT_KEY), m_qmlDebugServerPort); + foreach (IRunConfigurationAspect *aspect, m_aspects) + map.unite(aspect->toMap()); + return map; } @@ -259,9 +273,18 @@ bool RunConfiguration::fromMap(const QVariantMap &map) m_useQmlDebugger = map.value(QLatin1String(USE_QML_DEBUGGER_KEY), false).toBool(); m_qmlDebugServerPort = map.value(QLatin1String(QML_DEBUG_SERVER_PORT_KEY), Constants::QML_DEFAULT_DEBUG_SERVER_PORT).toUInt(); + foreach (IRunConfigurationAspect *aspect, m_aspects) + if (!aspect->fromMap(map)) + return false; + return ProjectConfiguration::fromMap(map); } +QList<IRunConfigurationAspect *> RunConfiguration::extraAspects() const +{ + return m_aspects; +} + ProjectExplorer::OutputFormatter *RunConfiguration::createOutputFormatter() const { return new OutputFormatter(); @@ -303,6 +326,11 @@ IRunControlFactory::~IRunControlFactory() { } +IRunConfigurationAspect *IRunControlFactory::createRunConfigurationAspect() +{ + return 0; +} + RunControl::RunControl(RunConfiguration *runConfiguration, QString mode) : m_runMode(mode), m_runConfiguration(runConfiguration), m_outputFormatter(0) { diff --git a/src/plugins/projectexplorer/runconfiguration.h b/src/plugins/projectexplorer/runconfiguration.h index b5458c36a5ad551dc3fbf3888dc67217c1f52ce8..2574ad9b6384f4665cea5d1fec5a3fced82dbcc3 100644 --- a/src/plugins/projectexplorer/runconfiguration.h +++ b/src/plugins/projectexplorer/runconfiguration.h @@ -41,10 +41,10 @@ #include <QtCore/QMetaType> #include <QtCore/QWeakPointer> +#include <QtGui/QWidget> QT_BEGIN_NAMESPACE class QString; -class QWidget; QT_END_NAMESPACE namespace ProjectExplorer { @@ -54,6 +54,7 @@ class Target; class RunControl; class BuildConfiguration; class OutputFormatter; +class IRunConfigurationAspect; /** * Base class for a run configuration. A run configuration specifies how a @@ -103,6 +104,22 @@ public: virtual QVariantMap toMap() const; + // aspects are a mechanism to add RunControl-specific options to a RunConfiguration without + // subclassing the RunConfiguration for every addition, preventing a combinatorical explosion + // of subclasses or the need to add all options to the base class. + QList<IRunConfigurationAspect *> extraAspects() const; + template <typename T> T *extraAspect() const + { + IRunConfigurationAspect *typeCheck = static_cast<T *>(0); + Q_UNUSED(typeCheck); + T *result = 0; + foreach (IRunConfigurationAspect *a, m_aspects) { + if ((result = dynamic_cast<T *>(a)) != 0) + break; + } + return result; + } + virtual ProjectExplorer::Abi abi() const; signals: @@ -120,9 +137,23 @@ protected: virtual bool fromMap(const QVariantMap &map); private: + void addExtraAspects(); + bool m_useCppDebugger; bool m_useQmlDebugger; uint m_qmlDebugServerPort; + QList<IRunConfigurationAspect *> m_aspects; +}; + +class PROJECTEXPLORER_EXPORT IRunConfigurationAspect +{ +public: + virtual ~IRunConfigurationAspect() {} + virtual QVariantMap toMap() const = 0; + virtual QString displayName() const = 0; +protected: + friend class RunConfiguration; + virtual bool fromMap(const QVariantMap &map) = 0; }; /** @@ -163,6 +194,8 @@ signals: void availableCreationIdsChanged(); }; +class RunConfigWidget; + class PROJECTEXPLORER_EXPORT IRunControlFactory : public QObject { Q_OBJECT @@ -175,8 +208,31 @@ public: virtual QString displayName() const = 0; - /// Returns the widget used to configure this runner. Ownership is transferred to the caller - virtual QWidget *createConfigurationWidget(RunConfiguration *runConfiguration) = 0; + /// Return an IRunConfigurationAspect to carry options for RunControls this factory can create. + /// If no extra options are required it is allowed to return null like the default implementation does. + /// This is intended to be called from the RunConfiguration constructor, so passing a RunConfiguration + /// pointer makes no sense because that object is under construction at the time. + virtual IRunConfigurationAspect *createRunConfigurationAspect(); + + /// Return a widget used to configure this runner. Ownership is transferred to the caller. + /// If @p runConfiguration is not suitable for RunControls from this factory, or no user-accesible + /// configuration is required, return null. + virtual RunConfigWidget *createConfigurationWidget(RunConfiguration *runConfiguration) = 0; +}; + +class PROJECTEXPLORER_EXPORT RunConfigWidget + : public QWidget +{ + Q_OBJECT +public: + RunConfigWidget() + : QWidget(0) + {} + + virtual QString displayName() const = 0; + +signals: + void displayNameChanged(const QString &); }; /** diff --git a/src/plugins/projectexplorer/runsettingspropertiespage.cpp b/src/plugins/projectexplorer/runsettingspropertiespage.cpp index 222931cb83a380bed83f5d5909561f34f095c870..a47e428273504574e71eddbf2809e613da7eb72e 100644 --- a/src/plugins/projectexplorer/runsettingspropertiespage.cpp +++ b/src/plugins/projectexplorer/runsettingspropertiespage.cpp @@ -204,15 +204,6 @@ RunSettingsWidget::RunSettingsWidget(Target *target) connect(m_target, SIGNAL(activeRunConfigurationChanged(ProjectExplorer::RunConfiguration*)), this, SLOT(activeRunConfigurationChanged())); - - // TODO: Add support for custom runner configuration widgets once we have some - /* - QList<IRunControlFactory *> runners = PluginManager::instance()->getObjects<IRunControlFactory>(); - foreach (IRunControlFactory * runner, runners) { - if (runner->canRun(activeRunConfiguration)) - m_ui->layout->addWidget(runner->createConfigurationWidget(activeRunConfiguration)); - } - */ } RunSettingsWidget::~RunSettingsWidget() @@ -419,10 +410,13 @@ void RunSettingsWidget::setConfigurationWidget(RunConfiguration *rc) { delete m_runConfigurationWidget; m_runConfigurationWidget = 0; + removeSubWidgets(); if (!rc) return; - m_runConfigurationWidget = m_target->activeRunConfiguration()->createConfigurationWidget(); + m_runConfigurationWidget = rc->createConfigurationWidget(); m_runLayout->addWidget(m_runConfigurationWidget); + + addRunControlWidgets(); } QString RunSettingsWidget::uniqueDCName(const QString &name) @@ -454,3 +448,47 @@ QString RunSettingsWidget::uniqueRCName(const QString &name) } return result; } + +void RunSettingsWidget::addRunControlWidgets() +{ + ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); + foreach (IRunControlFactory *f, pm->getObjects<IRunControlFactory>()) { + ProjectExplorer::RunConfigWidget *rcw = + f->createConfigurationWidget(m_target->activeRunConfiguration()); + if (rcw) + addSubWidget(rcw); + } +} + +void RunSettingsWidget::addSubWidget(RunConfigWidget *widget) +{ + widget->setContentsMargins(0, 10, 0, 0); + + QLabel *label = new QLabel(this); + label->setText(widget->displayName()); + connect(widget, SIGNAL(displayNameChanged(QString)), + label, SLOT(setText(QString))); + QFont f = label->font(); + f.setBold(true); + f.setPointSizeF(f.pointSizeF() * 1.2); + label->setFont(f); + + label->setContentsMargins(0, 10, 0, 0); + + QGridLayout *l = m_ui->gridLayout; + l->addWidget(label, l->rowCount(), 0, 1, -1); + l->addWidget(widget, l->rowCount(), 0, 1, -1); + + m_subWidgets.append(qMakePair(widget, label)); +} + +void RunSettingsWidget::removeSubWidgets() +{ + // foreach does not like commas in types, it's only a macro after all + typedef QPair<RunConfigWidget *, QLabel *> RunConfigItem; + foreach (const RunConfigItem &item, m_subWidgets) { + delete item.first; + delete item.second; + } + m_subWidgets.clear(); +} diff --git a/src/plugins/projectexplorer/runsettingspropertiespage.h b/src/plugins/projectexplorer/runsettingspropertiespage.h index bfc06ef9041b21622ca153f4d28b6f96c3214f78..3a9f721ca9dfc0c73d7b8e0cee4a5f8dfb622125 100644 --- a/src/plugins/projectexplorer/runsettingspropertiespage.h +++ b/src/plugins/projectexplorer/runsettingspropertiespage.h @@ -52,6 +52,7 @@ class DeployConfigurationWidget; class DeployConfigurationModel; class RunConfiguration; class RunConfigurationModel; +class RunConfigWidget; namespace Internal { @@ -115,6 +116,10 @@ private: void updateDeployConfiguration(DeployConfiguration *); void setConfigurationWidget(RunConfiguration *rc); + void addRunControlWidgets(); + void addSubWidget(RunConfigWidget *subWidget); + void removeSubWidgets(); + Target *m_target; RunConfigurationModel *m_runConfigurationsModel; DeployConfigurationModel *m_deployConfigurationModel; @@ -127,6 +132,7 @@ private: QMenu *m_addRunMenu; QMenu *m_addDeployMenu; bool m_ignoreChange; + QList<QPair<RunConfigWidget *, QLabel *> > m_subWidgets; }; } // namespace Internal diff --git a/src/plugins/qmlprojectmanager/qmlprojectruncontrol.cpp b/src/plugins/qmlprojectmanager/qmlprojectruncontrol.cpp index 52abf6d2513a7dae01146933589efd6be54de559..01620f96e066aed11dc023ece4b21ace2403ad4d 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectruncontrol.cpp +++ b/src/plugins/qmlprojectmanager/qmlprojectruncontrol.cpp @@ -180,10 +180,10 @@ QString QmlRunControlFactory::displayName() const return tr("Run"); } -QWidget *QmlRunControlFactory::createConfigurationWidget(RunConfiguration *runConfiguration) +ProjectExplorer::RunConfigWidget *QmlRunControlFactory::createConfigurationWidget(RunConfiguration *runConfiguration) { Q_UNUSED(runConfiguration) - return new QLabel("TODO add Configuration widget"); + return 0; } RunControl *QmlRunControlFactory::createDebugRunControl(QmlProjectRunConfiguration *runConfig) diff --git a/src/plugins/qmlprojectmanager/qmlprojectruncontrol.h b/src/plugins/qmlprojectmanager/qmlprojectruncontrol.h index 6623990ac8c5917a2c1a2bf1f373d5d28f6e28b5..5def7465962d763e876bbd23423806b7bf00eb70 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectruncontrol.h +++ b/src/plugins/qmlprojectmanager/qmlprojectruncontrol.h @@ -77,7 +77,8 @@ public: virtual bool canRun(ProjectExplorer::RunConfiguration *runConfiguration, const QString &mode) const; virtual ProjectExplorer::RunControl *create(ProjectExplorer::RunConfiguration *runConfiguration, const QString &mode); virtual QString displayName() const; - virtual QWidget *createConfigurationWidget(ProjectExplorer::RunConfiguration *runConfiguration); + virtual ProjectExplorer::RunConfigWidget *createConfigurationWidget(ProjectExplorer::RunConfiguration + *runConfiguration); private: ProjectExplorer::RunControl *createDebugRunControl(QmlProjectRunConfiguration *runConfig); diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemorunfactories.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemorunfactories.cpp index d79ca7623858a49e25b0578dd5a8e4e6853f4e3a..aeff84e654424838c77d6b830cc40c60032ac440 100644 --- a/src/plugins/qt4projectmanager/qt-maemo/maemorunfactories.cpp +++ b/src/plugins/qt4projectmanager/qt-maemo/maemorunfactories.cpp @@ -202,7 +202,7 @@ QString MaemoRunControlFactory::displayName() const return tr("Run on device"); } -QWidget *MaemoRunControlFactory::createConfigurationWidget(RunConfiguration *config) +RunConfigWidget *MaemoRunControlFactory::createConfigurationWidget(RunConfiguration *config) { Q_UNUSED(config) return 0; diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemorunfactories.h b/src/plugins/qt4projectmanager/qt-maemo/maemorunfactories.h index 78aabc82dd87b4072c5cce9a885a6bd1d64e2040..105f08785cfc0ee9e08ff9a8da9fc233bd165425 100644 --- a/src/plugins/qt4projectmanager/qt-maemo/maemorunfactories.h +++ b/src/plugins/qt4projectmanager/qt-maemo/maemorunfactories.h @@ -44,6 +44,7 @@ namespace ProjectExplorer { using ProjectExplorer::IRunConfigurationFactory; using ProjectExplorer::IRunControlFactory; using ProjectExplorer::RunConfiguration; +using ProjectExplorer::RunConfigWidget; using ProjectExplorer::RunControl; using ProjectExplorer::Target; @@ -79,7 +80,7 @@ public: ~MaemoRunControlFactory(); QString displayName() const; - QWidget *createConfigurationWidget(RunConfiguration *runConfiguration); + RunConfigWidget *createConfigurationWidget(RunConfiguration *runConfiguration); bool canRun(RunConfiguration *runConfiguration, const QString &mode) const; RunControl *create(RunConfiguration *runConfiguration, const QString &mode); diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp index 4bd7ea0c60d73c6c4b3de91d4a00aaf1995bfb3b..016e76429c4b3ac251b68d4d50af4b71bb5b8b91 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp @@ -541,7 +541,7 @@ QString S60DeviceDebugRunControlFactory::displayName() const return tr("Debug on Device"); } -QWidget *S60DeviceDebugRunControlFactory::createConfigurationWidget(ProjectExplorer::RunConfiguration * /*runConfiguration */) +ProjectExplorer::RunConfigWidget *S60DeviceDebugRunControlFactory::createConfigurationWidget(RunConfiguration* /*runConfiguration */) { return 0; } diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h index 8536bdd923038b1c04ef19c2f7b8df343485b4a6..9a815dab7d1ba48eeb94363b95d677a19d10103c 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h +++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h @@ -150,7 +150,7 @@ public: ProjectExplorer::RunControl* create(ProjectExplorer::RunConfiguration *runConfiguration, const QString &mode); QString displayName() const; - QWidget *createConfigurationWidget(ProjectExplorer::RunConfiguration * /*runConfiguration */); + ProjectExplorer::RunConfigWidget *createConfigurationWidget(ProjectExplorer::RunConfiguration * /*runConfiguration */); }; } // namespace Internal diff --git a/src/plugins/qt4projectmanager/qt-s60/s60manager.cpp b/src/plugins/qt4projectmanager/qt-s60/s60manager.cpp index e8fad33f7306400cef7879143852d52af2bf2289..25ced39820e05f9fc88780ffb323c8b7027de259 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60manager.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60manager.cpp @@ -95,7 +95,7 @@ public: return m_name; } - QWidget *createConfigurationWidget(ProjectExplorer::RunConfiguration * /*runConfiguration */) { + ProjectExplorer::RunConfigWidget *createConfigurationWidget(ProjectExplorer::RunConfiguration *) { return 0; } diff --git a/src/plugins/qt4projectmanager/qt-s60/s60runcontrolfactory.cpp b/src/plugins/qt4projectmanager/qt-s60/s60runcontrolfactory.cpp index 2bcf7734a8727374eabb61201febab13d974920b..04d74606f6cec1c090ab8659e67ed9e2d2f70124 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60runcontrolfactory.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60runcontrolfactory.cpp @@ -84,7 +84,7 @@ QString S60RunControlFactory::displayName() const return m_name; } -QWidget *S60RunControlFactory::createConfigurationWidget(RunConfiguration * /*S60DeviceRunConfiguration */) +RunConfigWidget *S60RunControlFactory::createConfigurationWidget(RunConfiguration* runConfiguration /*S60DeviceRunConfiguration */) { return 0; } diff --git a/src/plugins/qt4projectmanager/qt-s60/s60runcontrolfactory.h b/src/plugins/qt4projectmanager/qt-s60/s60runcontrolfactory.h index b4e51cd8b58f9b95970e4dcf24e9c51b3e7b19de..c2110563425d0c6ae9abd53efece77811c0771a4 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60runcontrolfactory.h +++ b/src/plugins/qt4projectmanager/qt-s60/s60runcontrolfactory.h @@ -52,7 +52,7 @@ public: QString displayName() const; - QWidget *createConfigurationWidget(ProjectExplorer::RunConfiguration *runConfiguration); + ProjectExplorer::RunConfigWidget *createConfigurationWidget(ProjectExplorer::RunConfiguration *runConfiguration); private: const QString m_mode;