diff options
Diffstat (limited to 'src/plugins/projectexplorer')
71 files changed, 4640 insertions, 1227 deletions
diff --git a/src/plugins/projectexplorer/abstractmsvctoolchain.cpp b/src/plugins/projectexplorer/abstractmsvctoolchain.cpp index 4bb17b044e..0017243a5a 100644 --- a/src/plugins/projectexplorer/abstractmsvctoolchain.cpp +++ b/src/plugins/projectexplorer/abstractmsvctoolchain.cpp @@ -132,14 +132,6 @@ QString AbstractMsvcToolChain::makeCommand() const return QLatin1String("nmake.exe"); } -void AbstractMsvcToolChain::setDebuggerCommand(const Utils::FileName &d) -{ - if (m_debuggerCommand == d) - return; - m_debuggerCommand = d; - toolChainUpdated(); -} - Utils::FileName AbstractMsvcToolChain::compilerCommand() const { Utils::Environment env; @@ -147,12 +139,6 @@ Utils::FileName AbstractMsvcToolChain::compilerCommand() const return Utils::FileName::fromString(env.searchInPath("cl.exe")); } -Utils::FileName AbstractMsvcToolChain::debuggerCommand() const -{ - return m_debuggerCommand; -} - - IOutputParser *AbstractMsvcToolChain::outputParser() const { return new MsvcParser; @@ -296,7 +282,6 @@ bool AbstractMsvcToolChain::operator ==(const ToolChain &other) const const AbstractMsvcToolChain *msvcTc = static_cast<const AbstractMsvcToolChain *>(&other); return targetAbi() == msvcTc->targetAbi() - && m_debuggerCommand == msvcTc->m_debuggerCommand && m_vcvarsBat == msvcTc->m_vcvarsBat; } diff --git a/src/plugins/projectexplorer/abstractmsvctoolchain.h b/src/plugins/projectexplorer/abstractmsvctoolchain.h index 519785880c..ef26aa401c 100644 --- a/src/plugins/projectexplorer/abstractmsvctoolchain.h +++ b/src/plugins/projectexplorer/abstractmsvctoolchain.h @@ -57,10 +57,7 @@ public: void addToEnvironment(Utils::Environment &env) const; QString makeCommand() const; - void setDebuggerCommand(const Utils::FileName &d); - Utils::FileName compilerCommand() const; - Utils::FileName debuggerCommand() const; IOutputParser *outputParser() const; bool canClone() const; diff --git a/src/plugins/projectexplorer/buildconfiguration.cpp b/src/plugins/projectexplorer/buildconfiguration.cpp index df9561db06..e97134952c 100644 --- a/src/plugins/projectexplorer/buildconfiguration.cpp +++ b/src/plugins/projectexplorer/buildconfiguration.cpp @@ -32,16 +32,16 @@ #include "buildconfiguration.h" -#include "toolchain.h" #include "buildmanager.h" #include "buildsteplist.h" #include "projectexplorer.h" #include "projectexplorerconstants.h" +#include "profilemanager.h" #include "target.h" -#include "toolchainmanager.h" #include "project.h" #include <coreplugin/variablemanager.h> +#include <extensionsystem/pluginmanager.h> #include <utils/qtcassert.h> #include <utils/stringutils.h> @@ -52,7 +52,6 @@ static const char BUILD_STEP_LIST_COUNT[] = "ProjectExplorer.BuildConfiguration. static const char BUILD_STEP_LIST_PREFIX[] = "ProjectExplorer.BuildConfiguration.BuildStepList."; static const char CLEAR_SYSTEM_ENVIRONMENT_KEY[] = "ProjectExplorer.BuildConfiguration.ClearSystemEnvironment"; static const char USER_ENVIRONMENT_CHANGES_KEY[] = "ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"; -static const char TOOLCHAIN_KEY[] = "ProjectExplorer.BuildCOnfiguration.ToolChain"; namespace ProjectExplorer { namespace Internal { @@ -83,7 +82,6 @@ bool BuildConfigMacroExpander::resolveMacro(const QString &name, QString *ret) BuildConfiguration::BuildConfiguration(Target *target, const Core::Id id) : ProjectConfiguration(target, id), m_clearSystemEnvironment(false), - m_toolChain(0), m_macroExpander(0) { Q_ASSERT(target); @@ -96,19 +94,14 @@ BuildConfiguration::BuildConfiguration(Target *target, const Core::Id id) : bsl->setDefaultDisplayName(tr("Clean")); m_stepLists.append(bsl); - connect(ToolChainManager::instance(), SIGNAL(toolChainRemoved(ProjectExplorer::ToolChain*)), - this, SLOT(handleToolChainRemovals(ProjectExplorer::ToolChain*))); - connect(ToolChainManager::instance(), SIGNAL(toolChainAdded(ProjectExplorer::ToolChain*)), - this, SLOT(handleToolChainAddition(ProjectExplorer::ToolChain*))); - connect(ToolChainManager::instance(), SIGNAL(toolChainUpdated(ProjectExplorer::ToolChain*)), - this, SLOT(handleToolChainUpdates(ProjectExplorer::ToolChain*))); + connect(ProfileManager::instance(), SIGNAL(profileUpdated(ProjectExplorer::Profile*)), + this, SLOT(handleProfileUpdate(ProjectExplorer::Profile*))); } BuildConfiguration::BuildConfiguration(Target *target, BuildConfiguration *source) : ProjectConfiguration(target, source), m_clearSystemEnvironment(source->m_clearSystemEnvironment), m_userEnvironmentChanges(source->m_userEnvironmentChanges), - m_toolChain(source->m_toolChain), m_macroExpander(0) { Q_ASSERT(target); @@ -116,12 +109,8 @@ BuildConfiguration::BuildConfiguration(Target *target, BuildConfiguration *sourc // otherwise BuildStepFactories might reject to set up a BuildStep for us // since we are not yet the derived class! - connect(ToolChainManager::instance(), SIGNAL(toolChainRemoved(ProjectExplorer::ToolChain*)), - this, SLOT(handleToolChainRemovals(ProjectExplorer::ToolChain*))); - connect(ToolChainManager::instance(), SIGNAL(toolChainAdded(ProjectExplorer::ToolChain*)), - this, SLOT(handleToolChainAddition(ProjectExplorer::ToolChain*))); - connect(ToolChainManager::instance(), SIGNAL(toolChainUpdated(ProjectExplorer::ToolChain*)), - this, SLOT(handleToolChainUpdates(ProjectExplorer::ToolChain*))); + connect(ProfileManager::instance(), SIGNAL(profileUpdated(ProjectExplorer::Profile*)), + this, SLOT(handleProfileUpdate(ProjectExplorer::Profile*))); } BuildConfiguration::~BuildConfiguration() @@ -162,8 +151,6 @@ QVariantMap BuildConfiguration::toMap() const for (int i = 0; i < m_stepLists.count(); ++i) map.insert(QLatin1String(BUILD_STEP_LIST_PREFIX) + QString::number(i), m_stepLists.at(i)->toMap()); - map.insert(QLatin1String(TOOLCHAIN_KEY), m_toolChain ? m_toolChain->id() : QLatin1String("INVALID")); - return map; } @@ -195,10 +182,6 @@ bool BuildConfiguration::fromMap(const QVariantMap &map) m_stepLists.append(list); } - const QString id = map.value(QLatin1String(TOOLCHAIN_KEY)).toString(); - setToolChain(ToolChainManager::instance()->findToolChain(id)); // Do not validate the tool chain as - // the BC is not completely set up yet! - // We currently assume there to be at least a clean and build list! QTC_CHECK(knownStepLists().contains(Core::Id(ProjectExplorer::Constants::BUILDSTEPS_BUILD))); QTC_CHECK(knownStepLists().contains(Core::Id(ProjectExplorer::Constants::BUILDSTEPS_CLEAN))); @@ -206,52 +189,18 @@ bool BuildConfiguration::fromMap(const QVariantMap &map) return ProjectConfiguration::fromMap(map); } -void BuildConfiguration::handleToolChainRemovals(ProjectExplorer::ToolChain *tc) -{ - if (m_toolChain != tc) - return; - setToolChain(target()->preferredToolChain(this)); -} - -void BuildConfiguration::handleToolChainAddition(ProjectExplorer::ToolChain *tc) -{ - Q_UNUSED(tc); - if (m_toolChain != 0) - return; - setToolChain(target()->preferredToolChain(this)); -} - -void BuildConfiguration::handleToolChainUpdates(ProjectExplorer::ToolChain *tc) +void BuildConfiguration::handleProfileUpdate(ProjectExplorer::Profile *p) { - if (tc != m_toolChain) + if (p != target()->profile()) return; - QList<ToolChain *> candidates = target()->possibleToolChains(this); - if (!candidates.contains(m_toolChain)) - setToolChain(target()->preferredToolChain(this)); - else - emit toolChainChanged(); + emit environmentChanged(); } - Target *BuildConfiguration::target() const { return static_cast<Target *>(parent()); } -ProjectExplorer::ToolChain *BuildConfiguration::toolChain() const -{ - return m_toolChain; -} - -void BuildConfiguration::setToolChain(ProjectExplorer::ToolChain *tc) -{ - if (m_toolChain == tc) - return; - m_toolChain = tc; - emit toolChainChanged(); - emit environmentChanged(); -} - Utils::Environment BuildConfiguration::baseEnvironment() const { Utils::Environment result; @@ -333,4 +282,26 @@ IBuildConfigurationFactory::IBuildConfigurationFactory(QObject *parent) : IBuildConfigurationFactory::~IBuildConfigurationFactory() { } +IBuildConfigurationFactory *IBuildConfigurationFactory::find(Target *parent, const QVariantMap &map) +{ + QList<IBuildConfigurationFactory *> factories + = ExtensionSystem::PluginManager::instance()->getObjects<IBuildConfigurationFactory>(); + foreach (IBuildConfigurationFactory *factory, factories) { + if (factory->canRestore(parent, map)) + return factory; + } + return 0; +} + +IBuildConfigurationFactory * IBuildConfigurationFactory::find(Target *parent) +{ + QList<IBuildConfigurationFactory *> factories + = ExtensionSystem::PluginManager::instance()->getObjects<IBuildConfigurationFactory>(); + foreach (IBuildConfigurationFactory *factory, factories) { + if (!factory->availableCreationIds(parent).isEmpty()) + return factory; + } + return 0; +} + } // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/buildconfiguration.h b/src/plugins/projectexplorer/buildconfiguration.h index e2057f4ef4..958692f900 100644 --- a/src/plugins/projectexplorer/buildconfiguration.h +++ b/src/plugins/projectexplorer/buildconfiguration.h @@ -47,9 +47,10 @@ class AbstractMacroExpander; namespace ProjectExplorer { class BuildConfiguration; +class BuildConfigWidget; class BuildStepList; +class Profile; class Target; -class ToolChain; class IOutputParser; class PROJECTEXPLORER_EXPORT BuildConfiguration : public ProjectConfiguration @@ -62,6 +63,8 @@ public: virtual QString buildDirectory() const = 0; + virtual BuildConfigWidget *createConfigWidget() = 0; + // Maybe the BuildConfiguration is not the best place for the environment virtual Utils::Environment baseEnvironment() const; QString baseEnvironmentText() const; @@ -90,9 +93,6 @@ public: Utils::AbstractMacroExpander *macroExpander(); - virtual ProjectExplorer::ToolChain *toolChain() const; - virtual void setToolChain(ProjectExplorer::ToolChain *tc); - enum BuildType { Unknown, Debug, @@ -104,7 +104,10 @@ signals: void environmentChanged(); void buildDirectoryChanged(); void enabledChanged(); - void toolChainChanged(); + /// Emitted whenever the build system needs to be (re-) evaluated + void requestBuildSystemEvaluation(); + /// Emitter whenever the build directory was successfully initialized (configured). + void buildDirectoryInitialized(); protected: BuildConfiguration(Target *target, const Core::Id id); @@ -115,15 +118,12 @@ protected: virtual bool fromMap(const QVariantMap &map); private slots: - void handleToolChainRemovals(ProjectExplorer::ToolChain *tc); - void handleToolChainAddition(ProjectExplorer::ToolChain *tc); - void handleToolChainUpdates(ProjectExplorer::ToolChain*); + void handleProfileUpdate(ProjectExplorer::Profile *p); private: bool m_clearSystemEnvironment; QList<Utils::EnvironmentItem> m_userEnvironmentChanges; QList<BuildStepList *> m_stepLists; - ToolChain *m_toolChain; Utils::AbstractMacroExpander *m_macroExpander; }; @@ -137,18 +137,21 @@ public: virtual ~IBuildConfigurationFactory(); // used to show the list of possible additons to a target, returns a list of types - virtual QList<Core::Id> availableCreationIds(Target *parent) const = 0; + virtual QList<Core::Id> availableCreationIds(const Target *parent) const = 0; // used to translate the types to names to display to the user virtual QString displayNameForId(const Core::Id id) const = 0; - virtual bool canCreate(Target *parent, const Core::Id id) const = 0; - virtual BuildConfiguration *create(Target *parent, const Core::Id id) = 0; + virtual bool canCreate(const Target *parent, const Core::Id id) const = 0; + virtual BuildConfiguration *create(Target *parent, const Core::Id id, const QString &name = QString()) = 0; // used to recreate the runConfigurations when restoring settings - virtual bool canRestore(Target *parent, const QVariantMap &map) const = 0; + virtual bool canRestore(const Target *parent, const QVariantMap &map) const = 0; virtual BuildConfiguration *restore(Target *parent, const QVariantMap &map) = 0; - virtual bool canClone(Target *parent, BuildConfiguration *product) const = 0; + virtual bool canClone(const Target *parent, BuildConfiguration *product) const = 0; virtual BuildConfiguration *clone(Target *parent, BuildConfiguration *product) = 0; + static IBuildConfigurationFactory *find(Target *parent, const QVariantMap &map); + static IBuildConfigurationFactory *find(Target *parent); + signals: void availableCreationIdsChanged(); }; diff --git a/src/plugins/projectexplorer/buildenvironmentwidget.cpp b/src/plugins/projectexplorer/buildenvironmentwidget.cpp index acafb1eb38..6ce515fb6f 100644 --- a/src/plugins/projectexplorer/buildenvironmentwidget.cpp +++ b/src/plugins/projectexplorer/buildenvironmentwidget.cpp @@ -35,6 +35,7 @@ #include "buildconfiguration.h" #include "environmentwidget.h" +#include <projectexplorer/target.h> #include <utils/qtcassert.h> #include <QVBoxLayout> @@ -69,17 +70,13 @@ void BuildEnvironmentWidget::init(BuildConfiguration *bc) Q_ASSERT(bc); if (m_buildConfiguration) { - disconnect(m_buildConfiguration, SIGNAL(environmentChanged()), - this, SLOT(environmentChanged())); - disconnect(m_buildConfiguration, SIGNAL(toolChainChanged()), + disconnect(m_buildConfiguration->target(), SIGNAL(environmentChanged()), this, SLOT(environmentChanged())); } m_buildConfiguration = bc; - connect(m_buildConfiguration, SIGNAL(environmentChanged()), - this, SLOT(environmentChanged())); - connect(m_buildConfiguration, SIGNAL(toolChainChanged()), + connect(m_buildConfiguration->target(), SIGNAL(environmentChanged()), this, SLOT(environmentChanged())); m_clearSystemEnvironmentCheckBox->setChecked(!m_buildConfiguration->useSystemEnvironment()); diff --git a/src/plugins/projectexplorer/buildsettingspropertiespage.cpp b/src/plugins/projectexplorer/buildsettingspropertiespage.cpp index 986f52de15..91a693a561 100644 --- a/src/plugins/projectexplorer/buildsettingspropertiespage.cpp +++ b/src/plugins/projectexplorer/buildsettingspropertiespage.cpp @@ -80,7 +80,7 @@ int BuildSettingsPanelFactory::priority() const bool BuildSettingsPanelFactory::supports(Target *target) { - return target->buildConfigurationFactory(); + return IBuildConfigurationFactory::find(target); } PropertiesPanel *BuildSettingsPanelFactory::createPanel(Target *target) @@ -120,7 +120,7 @@ void BuildSettingsWidget::setupUi() QVBoxLayout *vbox = new QVBoxLayout(this); vbox->setContentsMargins(0, 0, 0, 0); - if (!m_target->buildConfigurationFactory()) { + if (!IBuildConfigurationFactory::find(m_target)) { QLabel *noSettingsLabel = new QLabel(this); noSettingsLabel->setText(tr("No build settings available")); QFont f = noSettingsLabel->font(); @@ -179,9 +179,7 @@ void BuildSettingsWidget::setupUi() connect(m_target, SIGNAL(activeBuildConfigurationChanged(ProjectExplorer::BuildConfiguration*)), this, SLOT(updateActiveConfiguration())); - if (m_target->buildConfigurationFactory()) - connect(m_target->buildConfigurationFactory(), SIGNAL(availableCreationIdsChanged()), - SLOT(updateAddButtonMenu())); + connect(m_target, SIGNAL(profileChanged()), this, SLOT(updateAddButtonMenu())); } void BuildSettingsWidget::addSubWidget(BuildConfigWidget *widget) @@ -227,12 +225,10 @@ void BuildSettingsWidget::updateAddButtonMenu() m_addButtonMenu->addAction(tr("&Clone Selected"), this, SLOT(cloneConfiguration())); } - IBuildConfigurationFactory *factory = m_target->buildConfigurationFactory(); - if (factory) { - foreach (Core::Id id, factory->availableCreationIds(m_target)) { - QAction *action = m_addButtonMenu->addAction(factory->displayNameForId(id), this, SLOT(createConfiguration())); - action->setData(QVariant::fromValue(id)); - } + IBuildConfigurationFactory * factory = IBuildConfigurationFactory::find(m_target); + foreach (Core::Id id, factory->availableCreationIds(m_target)) { + QAction *action = m_addButtonMenu->addAction(factory->displayNameForId(id), this, SLOT(createConfiguration())); + action->setData(QVariant::fromValue(id)); } } } @@ -245,7 +241,7 @@ void BuildSettingsWidget::updateBuildSettings() m_removeButton->setEnabled(m_target->buildConfigurations().size() > 1); // Add pages - BuildConfigWidget *generalConfigWidget = m_target->createConfigWidget(); + BuildConfigWidget *generalConfigWidget = m_buildConfiguration->createConfigWidget(); addSubWidget(generalConfigWidget); addSubWidget(new BuildStepsPage(m_target, Core::Id(Constants::BUILDSTEPS_BUILD))); @@ -285,16 +281,22 @@ void BuildSettingsWidget::updateActiveConfiguration() void BuildSettingsWidget::createConfiguration() { - if (!m_target->buildConfigurationFactory()) - return; - QAction *action = qobject_cast<QAction *>(sender()); Core::Id id = action->data().value<Core::Id>(); - BuildConfiguration *bc = m_target->buildConfigurationFactory()->create(m_target, id); - if (bc) { - m_target->setActiveBuildConfiguration(bc); - updateBuildSettings(); - } + + IBuildConfigurationFactory *factory = IBuildConfigurationFactory::find(m_target); + if (!factory) + return; + + BuildConfiguration *bc = factory->create(m_target, id); + if (!bc) + return; + + m_target->addBuildConfiguration(bc); + + QTC_CHECK(bc->id() == id); + m_target->setActiveBuildConfiguration(bc); + updateBuildSettings(); } void BuildSettingsWidget::cloneConfiguration() @@ -343,8 +345,10 @@ void BuildSettingsWidget::renameConfiguration() void BuildSettingsWidget::cloneConfiguration(BuildConfiguration *sourceConfiguration) { - if (!sourceConfiguration || - !m_target->buildConfigurationFactory()) + if (!sourceConfiguration) + return; + IBuildConfigurationFactory *factory = IBuildConfigurationFactory::find(m_target); + if (!factory) return; //: Title of a the cloned BuildConfiguration window, text of the window @@ -352,7 +356,7 @@ void BuildSettingsWidget::cloneConfiguration(BuildConfiguration *sourceConfigura if (name.isEmpty()) return; - BuildConfiguration * bc(m_target->buildConfigurationFactory()->clone(m_target, sourceConfiguration)); + BuildConfiguration *bc = factory->clone(m_target, sourceConfiguration); if (!bc) return; diff --git a/src/plugins/projectexplorer/buildsteplist.cpp b/src/plugins/projectexplorer/buildsteplist.cpp index 2349035d70..666e148f94 100644 --- a/src/plugins/projectexplorer/buildsteplist.cpp +++ b/src/plugins/projectexplorer/buildsteplist.cpp @@ -159,7 +159,7 @@ bool BuildStepList::fromMap(const QVariantMap &map) qWarning() << "No step data found for" << i << "(continuing)."; continue; } - IBuildStepFactory *factory(findRestoreFactory(this, bsData)); + IBuildStepFactory *factory = findRestoreFactory(this, bsData); if (!factory) { qWarning() << "No factory for step" << i << "found (continuing)."; continue; diff --git a/src/plugins/projectexplorer/buildstepspage.cpp b/src/plugins/projectexplorer/buildstepspage.cpp index 5c292429d9..44e9070487 100644 --- a/src/plugins/projectexplorer/buildstepspage.cpp +++ b/src/plugins/projectexplorer/buildstepspage.cpp @@ -65,7 +65,7 @@ ToolWidget::ToolWidget(QWidget *parent) layout->setMargin(4); layout->setSpacing(4); setLayout(layout); - m_firstWidget = new FadingWidget(this); + m_firstWidget = new Utils::FadingWidget(this); m_firstWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); QHBoxLayout *hbox = new QHBoxLayout(); hbox->setContentsMargins(0, 0, 0, 0); @@ -86,7 +86,7 @@ ToolWidget::ToolWidget(QWidget *parent) hbox->addWidget(m_disableButton); layout->addWidget(m_firstWidget); - m_secondWidget = new FadingWidget(this); + m_secondWidget = new Utils::FadingWidget(this); m_secondWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding); hbox = new QHBoxLayout(); hbox->setMargin(0); @@ -182,39 +182,6 @@ void ToolWidget::setDownVisible(bool b) m_downButton->setVisible(b); } -FadingWidget::FadingWidget(QWidget *parent) : - QWidget(parent), - m_opacityEffect(new QGraphicsOpacityEffect) -{ - m_opacityEffect->setOpacity(0); - setGraphicsEffect(m_opacityEffect); - - // Workaround for issue with QGraphicsEffect. GraphicsEffect - // currently clears with Window color. Remove if flickering - // no longer occurs on fade-in - QPalette pal; - pal.setBrush(QPalette::All, QPalette::Window, Qt::transparent); - setPalette(pal); -} - -void FadingWidget::setOpacity(qreal value) -{ - m_opacityEffect->setOpacity(value); -} - -void FadingWidget::fadeTo(qreal value) -{ - QPropertyAnimation *animation = new QPropertyAnimation(m_opacityEffect, "opacity"); - animation->setDuration(200); - animation->setEndValue(value); - animation->start(QAbstractAnimation::DeleteWhenStopped); -} - -qreal FadingWidget::opacity() -{ - return m_opacityEffect->opacity(); -} - BuildStepsWidgetData::BuildStepsWidgetData(BuildStep *s) : step(s), widget(0), detailsWidget(0) { @@ -395,6 +362,7 @@ void BuildStepListWidget::triggerAddBuildStep() if (QAction *action = qobject_cast<QAction *>(sender())) { QPair<Core::Id, IBuildStepFactory *> pair = m_addBuildStepHash.value(action); BuildStep *newStep = pair.second->create(m_buildStepList, pair.first); + QTC_ASSERT(newStep, return); int pos = m_buildStepList->count(); m_buildStepList->insertStep(pos, newStep); } diff --git a/src/plugins/projectexplorer/buildstepspage.h b/src/plugins/projectexplorer/buildstepspage.h index 32f6520379..10fe1edb08 100644 --- a/src/plugins/projectexplorer/buildstepspage.h +++ b/src/plugins/projectexplorer/buildstepspage.h @@ -57,17 +57,6 @@ class Target; class BuildConfiguration; namespace Internal { -class FadingWidget : public QWidget -{ - Q_OBJECT -public: - FadingWidget(QWidget *parent = 0); - void fadeTo(qreal value); - qreal opacity(); - void setOpacity(qreal value); -protected: - QGraphicsOpacityEffect *m_opacityEffect; -}; class ToolWidget : public Utils::FadingPanel { @@ -97,8 +86,8 @@ private: QToolButton *m_removeButton; bool m_buildStepEnabled; - FadingWidget *m_firstWidget; - FadingWidget *m_secondWidget; + Utils::FadingWidget *m_firstWidget; + Utils::FadingWidget *m_secondWidget; qreal m_targetOpacity; }; diff --git a/src/plugins/projectexplorer/deployconfiguration.cpp b/src/plugins/projectexplorer/deployconfiguration.cpp index f7f0469a41..f5b87e3cd5 100644 --- a/src/plugins/projectexplorer/deployconfiguration.cpp +++ b/src/plugins/projectexplorer/deployconfiguration.cpp @@ -35,10 +35,14 @@ #include "buildmanager.h" #include "buildsteplist.h" #include "buildstepspage.h" +#include "profileinformation.h" +#include "project.h" #include "projectexplorer.h" #include "projectexplorerconstants.h" #include "target.h" +#include <extensionsystem/pluginmanager.h> + #include <QStringList> using namespace ProjectExplorer; @@ -59,7 +63,7 @@ DeployConfiguration::DeployConfiguration(Target *target, const Core::Id id) : //: Display name of the deploy build step list. Used as part of the labels in the project window. m_stepList->setDefaultDisplayName(tr("Deploy")); //: Default DeployConfiguration display name - setDefaultDisplayName(tr("No deployment")); + setDefaultDisplayName(tr("Deploy locally")); } DeployConfiguration::DeployConfiguration(Target *target, DeployConfiguration *source) : @@ -153,14 +157,15 @@ void DeployConfiguration::cloneSteps(DeployConfiguration *source) DeployConfigurationFactory::DeployConfigurationFactory(QObject *parent) : QObject(parent) -{ } +{ setObjectName(QLatin1String("DeployConfigurationFactory")); } DeployConfigurationFactory::~DeployConfigurationFactory() { } QList<Core::Id> DeployConfigurationFactory::availableCreationIds(Target *parent) const { - Q_UNUSED(parent); + if (!canHandle(parent)) + return QList<Core::Id>(); return QList<Core::Id>() << Core::Id(Constants::DEFAULT_DEPLOYCONFIGURATION_ID); } @@ -174,7 +179,8 @@ QString DeployConfigurationFactory::displayNameForId(const Core::Id id) const bool DeployConfigurationFactory::canCreate(Target *parent, const Core::Id id) const { - Q_UNUSED(parent); + if (!canHandle(parent)) + return false; return id == Core::Id(Constants::DEFAULT_DEPLOYCONFIGURATION_ID); } @@ -214,6 +220,35 @@ DeployConfiguration *DeployConfigurationFactory::clone(Target *parent, DeployCon return new DeployConfiguration(parent, product); } +DeployConfigurationFactory *DeployConfigurationFactory::find(Target *parent, const QVariantMap &map) +{ + QList<DeployConfigurationFactory *> factories + = ExtensionSystem::PluginManager::instance()->getObjects<DeployConfigurationFactory>(); + foreach (DeployConfigurationFactory *factory, factories) { + if (factory->canRestore(parent, map)) + return factory; + } + return 0; +} + +DeployConfigurationFactory *DeployConfigurationFactory::find(Target *parent) +{ + QList<DeployConfigurationFactory *> factories + = ExtensionSystem::PluginManager::instance()->getObjects<DeployConfigurationFactory>(); + foreach (DeployConfigurationFactory *factory, factories) { + if (!factory->availableCreationIds(parent).isEmpty()) + return factory; + } + return 0; +} + +bool DeployConfigurationFactory::canHandle(Target *parent) const +{ + if (!parent->project()->supportsProfile(parent->profile())) + return false; + return DeviceTypeProfileInformation::deviceTypeId(parent->profile()) == Core::Id(Constants::DESKTOP_DEVICE_TYPE); +} + /// // DeployConfigurationWidget /// diff --git a/src/plugins/projectexplorer/deployconfiguration.h b/src/plugins/projectexplorer/deployconfiguration.h index 878578aece..af30b665db 100644 --- a/src/plugins/projectexplorer/deployconfiguration.h +++ b/src/plugins/projectexplorer/deployconfiguration.h @@ -70,6 +70,7 @@ public: signals: void enabledChanged(); + void requestBuildSystemEvaluation(); protected: DeployConfiguration(Target *target, const Core::Id id); @@ -77,7 +78,7 @@ protected: void cloneSteps(DeployConfiguration *source); - virtual bool fromMap(const QVariantMap &map); + bool fromMap(const QVariantMap &map); private: friend class DeployConfigurationFactory; @@ -107,8 +108,14 @@ public: virtual bool canClone(Target *parent, DeployConfiguration *product) const; virtual DeployConfiguration *clone(Target *parent, DeployConfiguration *product); + static DeployConfigurationFactory *find(Target *parent, const QVariantMap &map); + static DeployConfigurationFactory *find(Target *parent); + signals: void availableCreationIdsChanged(); + +private: + bool canHandle(Target *parent) const; }; class PROJECTEXPLORER_EXPORT DeployConfigurationWidget : public NamedWidget diff --git a/src/plugins/projectexplorer/devicesupport/devicemanager.cpp b/src/plugins/projectexplorer/devicesupport/devicemanager.cpp index 6a2086f6ab..2e41051be9 100644 --- a/src/plugins/projectexplorer/devicesupport/devicemanager.cpp +++ b/src/plugins/projectexplorer/devicesupport/devicemanager.cpp @@ -139,13 +139,16 @@ void DeviceManager::save() { Utils::PersistentSettingsWriter writer; writer.saveValue(QLatin1String(DeviceManagerKey), toMap()); - writer.save(settingsFilePath(), QLatin1String("QtCreatorDevices"), Core::ICore::mainWindow()); + writer.save(settingsFilePath(QLatin1String("/qtcreator/devices.xml")), + QLatin1String("QtCreatorDevices"), Core::ICore::mainWindow()); } void DeviceManager::load() { Utils::PersistentSettingsReader reader; - if (reader.load(settingsFilePath())) + if (reader.load(settingsFilePath(QLatin1String("/qtcreator/devices.xml")))) + fromMap(reader.restoreValues().value(QLatin1String(DeviceManagerKey)).toMap()); + else if (reader.load(settingsFilePath(QLatin1String("/devices.xml")))) fromMap(reader.restoreValues().value(QLatin1String(DeviceManagerKey)).toMap()); else loadPre2_6(); @@ -220,9 +223,10 @@ QVariantMap DeviceManager::toMap() const return map; } -QString DeviceManager::settingsFilePath() +QString DeviceManager::settingsFilePath(const QString &extension) { - return QFileInfo(ExtensionSystem::PluginManager::settings()->fileName()).absolutePath() + QLatin1String("/devices.xml"); + ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); + return QFileInfo(pm->settings()->fileName()).absolutePath() + extension; } void DeviceManager::addDevice(const IDevice::Ptr &_device) diff --git a/src/plugins/projectexplorer/devicesupport/devicemanager.h b/src/plugins/projectexplorer/devicesupport/devicemanager.h index e9a913ef31..8dc3615816 100644 --- a/src/plugins/projectexplorer/devicesupport/devicemanager.h +++ b/src/plugins/projectexplorer/devicesupport/devicemanager.h @@ -101,7 +101,7 @@ private: IDevice::Ptr fromRawPointer(IDevice *device) const; IDevice::ConstPtr fromRawPointer(const IDevice *device) const; - static QString settingsFilePath(); + static QString settingsFilePath(const QString &extension); static void copy(const DeviceManager *source, DeviceManager *target, bool deep); Internal::DeviceManagerPrivate * const d; diff --git a/src/plugins/projectexplorer/devicesupport/devicemanagermodel.cpp b/src/plugins/projectexplorer/devicesupport/devicemanagermodel.cpp index 352b4d58e6..bee3fb5929 100644 --- a/src/plugins/projectexplorer/devicesupport/devicemanagermodel.cpp +++ b/src/plugins/projectexplorer/devicesupport/devicemanagermodel.cpp @@ -46,6 +46,7 @@ class DeviceManagerModelPrivate public: const DeviceManager *deviceManager; QList<IDevice::ConstPtr> devices; + QList<Core::Id> filter; }; } // namespace Internal @@ -65,6 +66,12 @@ DeviceManagerModel::~DeviceManagerModel() delete d; } +void DeviceManagerModel::setFilter(const QList<Core::Id> filter) +{ + d->filter = filter; + handleDeviceListChanged(); +} + void DeviceManagerModel::updateDevice(Core::Id id) { handleDeviceUpdated(id); @@ -87,6 +94,9 @@ Core::Id DeviceManagerModel::deviceId(int pos) const int DeviceManagerModel::indexOf(IDevice::ConstPtr dev) const { + if (dev.isNull()) + return -1; + for (int i = 0; i < d->devices.count(); ++i) { IDevice::ConstPtr current = d->devices.at(i); if (current->id() == dev->id()) @@ -127,7 +137,7 @@ void DeviceManagerModel::handleDeviceListChanged() for (int i = 0; i < d->deviceManager->deviceCount(); ++i) { IDevice::ConstPtr dev = d->deviceManager->deviceAt(i); - if (dev->id() == Core::Id(Constants::DESKTOP_DEVICE_ID)) + if (d->filter.contains(dev->id())) continue; d->devices << dev; } diff --git a/src/plugins/projectexplorer/devicesupport/devicemanagermodel.h b/src/plugins/projectexplorer/devicesupport/devicemanagermodel.h index bc4eeb827d..32eaa5052d 100644 --- a/src/plugins/projectexplorer/devicesupport/devicemanagermodel.h +++ b/src/plugins/projectexplorer/devicesupport/devicemanagermodel.h @@ -51,7 +51,7 @@ public: explicit DeviceManagerModel(const DeviceManager *deviceManager, QObject *parent = 0); ~DeviceManagerModel(); - void updateDevice(Core::Id id); + void setFilter(const QList<Core::Id> filter); IDevice::ConstPtr device(int pos) const; Core::Id deviceId(int pos) const; @@ -59,6 +59,8 @@ public: int indexForId(Core::Id id) const; int rowCount(const QModelIndex &parent = QModelIndex()) const; + void updateDevice(Core::Id id); + private slots: void handleDeviceAdded(Core::Id id); void handleDeviceRemoved(Core::Id id); diff --git a/src/plugins/projectexplorer/devicesupport/devicesettingswidget.cpp b/src/plugins/projectexplorer/devicesupport/devicesettingswidget.cpp index 4df175bacc..dae2671d36 100644 --- a/src/plugins/projectexplorer/devicesupport/devicesettingswidget.cpp +++ b/src/plugins/projectexplorer/devicesupport/devicesettingswidget.cpp @@ -31,12 +31,14 @@ #include "devicesettingswidget.h" #include "ui_devicesettingswidget.h" +#include "projectexplorerconstants.h" #include "devicefactoryselectiondialog.h" #include "devicemanager.h" #include "devicemanagermodel.h" #include "idevice.h" #include "idevicefactory.h" #include "idevicewidget.h" +#include "projectexplorerconstants.h" #include <coreplugin/icore.h> #include <coreplugin/id.h> @@ -94,7 +96,6 @@ private: const DeviceManager * const m_deviceManager; }; - DeviceSettingsWidget::DeviceSettingsWidget(QWidget *parent) : QWidget(parent), m_ui(new Ui::DeviceSettingsWidget), @@ -105,6 +106,7 @@ DeviceSettingsWidget::DeviceSettingsWidget(QWidget *parent) m_additionalActionsMapper(new QSignalMapper(this)), m_configWidget(0) { + m_deviceManagerModel->setFilter(QList<Core::Id>() << Core::Id(Constants::DESKTOP_DEVICE_ID)); initGui(); connect(m_additionalActionsMapper, SIGNAL(mapped(int)), SLOT(handleAdditionalActionRequest(int))); diff --git a/src/plugins/projectexplorer/gcctoolchain.cpp b/src/plugins/projectexplorer/gcctoolchain.cpp index a6b1d6942e..51fee9020c 100644 --- a/src/plugins/projectexplorer/gcctoolchain.cpp +++ b/src/plugins/projectexplorer/gcctoolchain.cpp @@ -62,7 +62,6 @@ namespace ProjectExplorer { static const char compilerCommandKeyC[] = "ProjectExplorer.GccToolChain.Path"; static const char targetAbiKeyC[] = "ProjectExplorer.GccToolChain.TargetAbi"; static const char supportedAbisKeyC[] = "ProjectExplorer.GccToolChain.SupportedAbis"; -static const char debuggerCommandKeyC[] = "ProjectExplorer.GccToolChain.Debugger"; static QByteArray runGcc(const Utils::FileName &gcc, const QStringList &arguments, const QStringList &env) { @@ -325,7 +324,6 @@ GccToolChain::GccToolChain(const GccToolChain &tc) : ToolChain(tc), m_predefinedMacros(tc.predefinedMacros(QStringList())), m_compilerCommand(tc.compilerCommand()), - m_debuggerCommand(tc.debuggerCommand()), m_targetAbi(tc.m_targetAbi), m_supportedAbis(tc.m_supportedAbis), m_headerPaths(tc.m_headerPaths), @@ -341,15 +339,6 @@ QString GccToolChain::defaultDisplayName() const ProjectExplorer::Abi::toString(m_targetAbi.wordWidth())); } -QString GccToolChain::legacyId() const -{ - QString i = id(); - i = i.left(i.indexOf(QLatin1Char(':'))); - return QString::fromLatin1("%1:%2.%3.%4") - .arg(i).arg(m_compilerCommand.toString()) - .arg(m_targetAbi.toString()).arg(m_debuggerCommand.toString()); -} - QString GccToolChain::type() const { return QLatin1String("gcc"); @@ -428,19 +417,6 @@ void GccToolChain::addToEnvironment(Utils::Environment &env) const } } -void GccToolChain::setDebuggerCommand(const Utils::FileName &d) -{ - if (m_debuggerCommand == d) - return; - m_debuggerCommand = d; - toolChainUpdated(); -} - -Utils::FileName GccToolChain::debuggerCommand() const -{ - return m_debuggerCommand; -} - QList<Utils::FileName> GccToolChain::suggestedMkspecList() const { Abi abi = targetAbi(); @@ -531,7 +507,6 @@ QVariantMap GccToolChain::toMap() const foreach (const ProjectExplorer::Abi &a, m_supportedAbis) abiList.append(a.toString()); data.insert(QLatin1String(supportedAbisKeyC), abiList); - data.insert(QLatin1String(debuggerCommandKeyC), m_debuggerCommand.toString()); return data; } @@ -550,7 +525,6 @@ bool GccToolChain::fromMap(const QVariantMap &data) continue; m_supportedAbis.append(abi); } - m_debuggerCommand = Utils::FileName::fromString(data.value(QLatin1String(debuggerCommandKeyC)).toString()); return true; } @@ -560,8 +534,7 @@ bool GccToolChain::operator ==(const ToolChain &other) const return false; const GccToolChain *gccTc = static_cast<const GccToolChain *>(&other); - return m_compilerCommand == gccTc->m_compilerCommand && m_targetAbi == gccTc->m_targetAbi - && m_debuggerCommand == gccTc->m_debuggerCommand; + return m_compilerCommand == gccTc->m_compilerCommand && m_targetAbi == gccTc->m_targetAbi; } ToolChainConfigWidget *GccToolChain::configurationWidget() @@ -615,16 +588,13 @@ ToolChain *Internal::GccToolChainFactory::create() QList<ToolChain *> Internal::GccToolChainFactory::autoDetect() { - QStringList debuggers; + QList<ToolChain *> tcs; #ifdef Q_OS_MAC - // Fixme Prefer lldb once it is implemented: debuggers.push_back(QLatin1String("lldb")); -#endif - debuggers.push_back(QLatin1String("gdb")); - QList<ToolChain *> tcs = autoDetectToolchains(QLatin1String("g++"), debuggers, Abi::hostAbi()); - // Old mac compilers needed to support macx-gccXY mkspecs: - tcs.append(autoDetectToolchains(QLatin1String("g++-4.0"), debuggers, Abi::hostAbi())); - tcs.append(autoDetectToolchains(QLatin1String("g++-4.2"), debuggers, Abi::hostAbi())); + tcs.append(autoDetectToolchains(QLatin1String("g++-4.0"), Abi::hostAbi())); + tcs.append(autoDetectToolchains(QLatin1String("g++-4.2"), Abi::hostAbi())); +#endif + tcs.append(autoDetectToolchains(QLatin1String("g++"), Abi::hostAbi())); return tcs; } @@ -651,7 +621,6 @@ GccToolChain *Internal::GccToolChainFactory::createToolChain(bool autoDetect) } QList<ToolChain *> Internal::GccToolChainFactory::autoDetectToolchains(const QString &compiler, - const QStringList &debuggers, const Abi &requiredAbi) { QList<ToolChain *> result; @@ -669,22 +638,12 @@ QList<ToolChain *> Internal::GccToolChainFactory::autoDetectToolchains(const QSt return result; } - Utils::FileName debuggerPath = ToolChainManager::instance()->defaultDebugger(requiredAbi); - if (debuggerPath.isEmpty()) { - foreach (const QString &debugger, debuggers) { - debuggerPath = Utils::FileName::fromString(systemEnvironment.searchInPath(debugger)); - if (!debuggerPath.isEmpty()) - break; - } - } - foreach (const Abi &abi, abiList) { QScopedPointer<GccToolChain> tc(createToolChain(true)); if (tc.isNull()) return result; tc->setCompilerCommand(compilerPath); - tc->setDebuggerCommand(debuggerPath); tc->setTargetAbi(abi); tc->setDisplayName(tc->defaultDisplayName()); // reset displayname @@ -715,14 +674,12 @@ Internal::GccToolChainConfigWidget::GccToolChainConfigWidget(GccToolChain *tc) : layout->addRow(tr("&ABI:"), m_abiWidget); m_abiWidget->setEnabled(false); - addDebuggerCommandControls(layout, gnuVersionArgs); - addMkspecControls(layout); addErrorLabel(layout); setFromToolchain(); connect(m_compilerCommand, SIGNAL(changed(QString)), this, SLOT(handleCompilerCommandChange())); - connect(m_abiWidget, SIGNAL(abiChanged()), this, SLOT(handleAbiChange())); + connect(m_abiWidget, SIGNAL(abiChanged()), this, SIGNAL(dirty())); } void Internal::GccToolChainConfigWidget::apply() @@ -736,9 +693,6 @@ void Internal::GccToolChainConfigWidget::apply() tc->setCompilerCommand(m_compilerCommand->fileName()); tc->setTargetAbi(m_abiWidget->currentAbi()); tc->setDisplayName(displayName); // reset display name - tc->setDebuggerCommand(debuggerCommand()); - tc->setMkspecList(mkspecList()); - m_autoDebuggerCommand = Utils::FileName::fromString(QLatin1String("<manually set>")); } void Internal::GccToolChainConfigWidget::setFromToolchain() @@ -750,8 +704,6 @@ void Internal::GccToolChainConfigWidget::setFromToolchain() m_abiWidget->setAbis(tc->supportedAbis(), tc->targetAbi()); if (!m_isReadOnly && !m_compilerCommand->path().isEmpty()) m_abiWidget->setEnabled(true); - setDebuggerCommand(tc->debuggerCommand()); - setMkspecList(tc->mkspecList()); blockSignals(blocked); } @@ -760,9 +712,7 @@ bool Internal::GccToolChainConfigWidget::isDirty() const GccToolChain *tc = static_cast<GccToolChain *>(toolChain()); Q_ASSERT(tc); return m_compilerCommand->fileName() != tc->compilerCommand() - || m_abiWidget->currentAbi() != tc->targetAbi() - || debuggerCommand() != tc->debuggerCommand() - || mkspecList() != tc->mkspecList(); + || m_abiWidget->currentAbi() != tc->targetAbi(); } void Internal::GccToolChainConfigWidget::makeReadOnly() @@ -787,16 +737,6 @@ void Internal::GccToolChainConfigWidget::handleCompilerCommandChange() m_abiWidget->setEnabled(haveCompiler); Abi currentAbi = m_abiWidget->currentAbi(); m_abiWidget->setAbis(abiList, abiList.contains(currentAbi) ? currentAbi : Abi()); - handleAbiChange(); -} - -void Internal::GccToolChainConfigWidget::handleAbiChange() -{ - if (m_autoDebuggerCommand == debuggerCommand()) { - ProjectExplorer::Abi abi = m_abiWidget->currentAbi(); - m_autoDebuggerCommand = ToolChainManager::instance()->defaultDebugger(abi); - setDebuggerCommand(m_autoDebuggerCommand); - } emit dirty(); } @@ -868,7 +808,7 @@ QString Internal::ClangToolChainFactory::id() const QList<ToolChain *> Internal::ClangToolChainFactory::autoDetect() { Abi ha = Abi::hostAbi(); - return autoDetectToolchains(QLatin1String("clang++"), QStringList(), ha); + return autoDetectToolchains(QLatin1String("clang++"), ha); } bool Internal::ClangToolChainFactory::canCreate() @@ -967,18 +907,8 @@ QString Internal::MingwToolChainFactory::id() const QList<ToolChain *> Internal::MingwToolChainFactory::autoDetect() { - // Compatibility to pre-2.2: - // All Mingw toolchains that exist so far are either installed by the SDK itself (in - // which case they most likely have debuggers set up) or were created when updating - // from a previous Qt version. Add debugger in that case. - foreach (ToolChain *tc, ToolChainManager::instance()->toolChains()) { - if (tc->debuggerCommand().isEmpty() && tc->id().startsWith(QLatin1String(Constants::MINGW_TOOLCHAIN_ID))) - static_cast<MingwToolChain *>(tc) - ->setDebuggerCommand(ToolChainManager::instance()->defaultDebugger(tc->targetAbi())); - } - Abi ha = Abi::hostAbi(); - return autoDetectToolchains(QLatin1String("g++"), QStringList(), + return autoDetectToolchains(QLatin1String("g++"), Abi(ha.architecture(), Abi::WindowsOS, Abi::WindowsMSysFlavor, Abi::PEFormat, ha.wordWidth())); } @@ -1062,9 +992,7 @@ QString Internal::LinuxIccToolChainFactory::id() const QList<ToolChain *> Internal::LinuxIccToolChainFactory::autoDetect() { - return autoDetectToolchains(QLatin1String("icpc"), - QStringList(QLatin1String("gdb")), - Abi::hostAbi()); + return autoDetectToolchains(QLatin1String("icpc"), Abi::hostAbi()); } ToolChain *Internal::LinuxIccToolChainFactory::create() diff --git a/src/plugins/projectexplorer/gcctoolchain.h b/src/plugins/projectexplorer/gcctoolchain.h index 4a77843c16..c8faf406b2 100644 --- a/src/plugins/projectexplorer/gcctoolchain.h +++ b/src/plugins/projectexplorer/gcctoolchain.h @@ -54,8 +54,6 @@ class LinuxIccToolChainFactory; class PROJECTEXPLORER_EXPORT GccToolChain : public ToolChain { public: - QString legacyId() const; - QString type() const; QString typeDisplayName() const; Abi targetAbi() const; @@ -71,8 +69,6 @@ public: QList<HeaderPath> systemHeaderPaths() const; void addToEnvironment(Utils::Environment &env) const; QString makeCommand() const; - void setDebuggerCommand(const Utils::FileName &); - Utils::FileName debuggerCommand() const; QList<Utils::FileName> suggestedMkspecList() const; IOutputParser *outputParser() const; @@ -107,7 +103,6 @@ private: void updateSupportedAbis() const; Utils::FileName m_compilerCommand; - Utils::FileName m_debuggerCommand; Abi m_targetAbi; mutable QList<Abi> m_supportedAbis; diff --git a/src/plugins/projectexplorer/gcctoolchainfactories.h b/src/plugins/projectexplorer/gcctoolchainfactories.h index aab545de74..34421d52c2 100644 --- a/src/plugins/projectexplorer/gcctoolchainfactories.h +++ b/src/plugins/projectexplorer/gcctoolchainfactories.h @@ -74,7 +74,6 @@ public: protected: virtual GccToolChain *createToolChain(bool autoDetect); QList<ToolChain *> autoDetectToolchains(const QString &compiler, - const QStringList &debuggers, const Abi &); }; @@ -95,7 +94,6 @@ public: private slots: void handleCompilerCommandChange(); - void handleAbiChange(); private: void setFromToolchain(); diff --git a/src/plugins/projectexplorer/miniprojecttargetselector.cpp b/src/plugins/projectexplorer/miniprojecttargetselector.cpp index 9fdb170f61..8cc1035dde 100644 --- a/src/plugins/projectexplorer/miniprojecttargetselector.cpp +++ b/src/plugins/projectexplorer/miniprojecttargetselector.cpp @@ -47,6 +47,7 @@ #include <projectexplorer/project.h> #include <projectexplorer/buildconfiguration.h> #include <projectexplorer/deployconfiguration.h> +#include <projectexplorer/profilemanager.h> #include <projectexplorer/projectmodels.h> #include <projectexplorer/runconfiguration.h> @@ -590,6 +591,10 @@ MiniProjectTargetSelector::MiniProjectTargetSelector(QAction *targetSelectorActi connect(m_sessionManager, SIGNAL(projectDisplayNameChanged(ProjectExplorer::Project*)), this, SLOT(updateActionAndSummary())); + // for icon changes: + connect(ProjectExplorer::ProfileManager::instance(), SIGNAL(profileUpdated(ProjectExplorer::Profile*)), + this, SLOT(profileChanged(ProjectExplorer::Profile*))); + connect(m_listWidgets[TARGET], SIGNAL(changeActiveProjectConfiguration(ProjectExplorer::ProjectConfiguration*)), this, SLOT(setActiveTarget(ProjectExplorer::ProjectConfiguration*))); connect(m_listWidgets[BUILD], SIGNAL(changeActiveProjectConfiguration(ProjectExplorer::ProjectConfiguration*)), @@ -869,6 +874,8 @@ void MiniProjectTargetSelector::activeTargetChanged(ProjectExplorer::Target *tar this, SLOT(updateActionAndSummary())); disconnect(m_target, SIGNAL(toolTipChanged()), this, SLOT(updateActionAndSummary())); + disconnect(m_target, SIGNAL(iconChanged()), + this, SLOT(updateActionAndSummary())); disconnect(m_target, SIGNAL(activeBuildConfigurationChanged(ProjectExplorer::BuildConfiguration*)), this, SLOT(activeBuildConfigurationChanged(ProjectExplorer::BuildConfiguration*))); disconnect(m_target, SIGNAL(activeDeployConfigurationChanged(ProjectExplorer::DeployConfiguration*)), @@ -925,6 +932,8 @@ void MiniProjectTargetSelector::activeTargetChanged(ProjectExplorer::Target *tar this, SLOT(updateActionAndSummary())); connect(m_target, SIGNAL(toolTipChanged()), this, SLOT(updateActionAndSummary())); + connect(m_target, SIGNAL(iconChanged()), + this, SLOT(updateActionAndSummary())); connect(m_target, SIGNAL(activeBuildConfigurationChanged(ProjectExplorer::BuildConfiguration*)), this, SLOT(activeBuildConfigurationChanged(ProjectExplorer::BuildConfiguration*))); connect(m_target, SIGNAL(activeDeployConfigurationChanged(ProjectExplorer::DeployConfiguration*)), @@ -942,6 +951,12 @@ void MiniProjectTargetSelector::activeTargetChanged(ProjectExplorer::Target *tar updateActionAndSummary(); } +void MiniProjectTargetSelector::profileChanged(Profile *profile) +{ + if (m_target && m_target->profile() == profile) + updateActionAndSummary(); +} + void MiniProjectTargetSelector::activeBuildConfigurationChanged(ProjectExplorer::BuildConfiguration *bc) { if (m_buildConfiguration) diff --git a/src/plugins/projectexplorer/miniprojecttargetselector.h b/src/plugins/projectexplorer/miniprojecttargetselector.h index 51f14622c5..f356610608 100644 --- a/src/plugins/projectexplorer/miniprojecttargetselector.h +++ b/src/plugins/projectexplorer/miniprojecttargetselector.h @@ -43,6 +43,7 @@ class QStackedWidget; QT_END_NAMESPACE namespace ProjectExplorer { +class Profile; class Project; class Target; class BuildConfiguration; @@ -134,6 +135,7 @@ private slots: void changeStartupProject(ProjectExplorer::Project *project); void activeTargetChanged(ProjectExplorer::Target *target); + void profileChanged(ProjectExplorer::Profile *profile); void activeBuildConfigurationChanged(ProjectExplorer::BuildConfiguration *bc); void activeDeployConfigurationChanged(ProjectExplorer::DeployConfiguration *dc); void activeRunConfigurationChanged(ProjectExplorer::RunConfiguration *rc); diff --git a/src/plugins/projectexplorer/msvctoolchain.cpp b/src/plugins/projectexplorer/msvctoolchain.cpp index 74e0f1ffae..8e5fa77871 100644 --- a/src/plugins/projectexplorer/msvctoolchain.cpp +++ b/src/plugins/projectexplorer/msvctoolchain.cpp @@ -53,7 +53,6 @@ #include <QDesktopServices> #define KEY_ROOT "ProjectExplorer.MsvcToolChain." -static const char debuggerCommandKeyC[] = KEY_ROOT"Debugger"; static const char varsBatKeyC[] = KEY_ROOT"VarsBat"; static const char varsBatArgKeyC[] = KEY_ROOT"VarsBatArg"; static const char supportedAbiKeyC[] = KEY_ROOT"SupportedAbi"; @@ -332,19 +331,6 @@ MsvcToolChain *MsvcToolChain::readFromMap(const QVariantMap &data) return 0; } -QString MsvcToolChain::legacyId() const -{ - const QChar colon = QLatin1Char(':'); - QString id = QLatin1String(Constants::MSVC_TOOLCHAIN_ID); - id += colon; - id += m_vcvarsBat; - id += colon; - id += m_varsBatArg; - id += colon; - id += m_debuggerCommand.toString(); - return id; -} - QString MsvcToolChain::type() const { return QLatin1String("msvc"); @@ -369,8 +355,6 @@ QList<Utils::FileName> MsvcToolChain::suggestedMkspecList() const QVariantMap MsvcToolChain::toMap() const { QVariantMap data = ToolChain::toMap(); - if (!m_debuggerCommand.isEmpty()) - data.insert(QLatin1String(debuggerCommandKeyC), m_debuggerCommand.toString()); data.insert(QLatin1String(varsBatKeyC), m_vcvarsBat); if (!m_varsBatArg.isEmpty()) data.insert(QLatin1String(varsBatArgKeyC), m_varsBatArg); @@ -384,7 +368,6 @@ bool MsvcToolChain::fromMap(const QVariantMap &data) return false; m_vcvarsBat = data.value(QLatin1String(varsBatKeyC)).toString(); m_varsBatArg = data.value(QLatin1String(varsBatArgKeyC)).toString(); - m_debuggerCommand = Utils::FileName::fromString(data.value(QLatin1String(debuggerCommandKeyC)).toString()); const QString abiString = data.value(QLatin1String(supportedAbiKeyC)).toString(); m_abi = Abi(abiString); @@ -403,42 +386,6 @@ ToolChain *MsvcToolChain::clone() const } // -------------------------------------------------------------------------- -// MsvcDebuggerConfigLabel -// -------------------------------------------------------------------------- - -static const char dgbToolsDownloadLink32C[] = "http://www.microsoft.com/whdc/devtools/debugging/installx86.Mspx"; -static const char dgbToolsDownloadLink64C[] = "http://www.microsoft.com/whdc/devtools/debugging/install64bit.Mspx"; - -QString MsvcDebuggerConfigLabel::labelText() -{ -#ifdef Q_OS_WIN - const bool is64bit = Utils::winIs64BitSystem(); -#else - const bool is64bit = false; -#endif - const QString link = is64bit ? QLatin1String(dgbToolsDownloadLink64C) : QLatin1String(dgbToolsDownloadLink32C); - //: Label text for path configuration. %2 is "x-bit version". - return tr( - "<html><body><p>Specify the path to the " - "<a href=\"%1\">Windows Console Debugger executable</a>" - " (%2) here.</p>" - "</body></html>").arg(link, (is64bit ? tr("64-bit version") - : tr("32-bit version"))); -} - -MsvcDebuggerConfigLabel::MsvcDebuggerConfigLabel(QWidget *parent) : - QLabel(labelText(), parent) -{ - connect(this, SIGNAL(linkActivated(QString)), this, SLOT(slotLinkActivated(QString))); - setTextInteractionFlags(Qt::TextBrowserInteraction); -} - -void MsvcDebuggerConfigLabel::slotLinkActivated(const QString &link) -{ - QDesktopServices::openUrl(QUrl(link)); -} - -// -------------------------------------------------------------------------- // MsvcToolChainConfigWidget // -------------------------------------------------------------------------- @@ -450,21 +397,12 @@ MsvcToolChainConfigWidget::MsvcToolChainConfigWidget(ToolChain *tc) : formLayout->addRow(new QLabel(tc->displayName())); m_varsBatDisplayLabel->setTextInteractionFlags(Qt::TextBrowserInteraction); formLayout->addRow(tr("Initialization:"), m_varsBatDisplayLabel); - formLayout->addRow(new MsvcDebuggerConfigLabel); - addDebuggerCommandControls(formLayout, QStringList(QLatin1String("-version"))); - addDebuggerAutoDetection(this, SLOT(autoDetectDebugger())); - addMkspecControls(formLayout); addErrorLabel(formLayout); setFromToolChain(); } void MsvcToolChainConfigWidget::apply() -{ - MsvcToolChain *tc = static_cast<MsvcToolChain *>(toolChain()); - QTC_ASSERT(tc, return; ); - tc->setDebuggerCommand(debuggerCommand()); - tc->setMkspecList(mkspecList()); -} +{ } void MsvcToolChainConfigWidget::setFromToolChain() { @@ -476,45 +414,11 @@ void MsvcToolChainConfigWidget::setFromToolChain() varsBatDisplay += tc->varsBatArg(); } m_varsBatDisplayLabel->setText(varsBatDisplay); - setDebuggerCommand(tc->debuggerCommand()); - setMkspecList(tc->mkspecList()); } bool MsvcToolChainConfigWidget::isDirty() const { - MsvcToolChain *tc = static_cast<MsvcToolChain *>(toolChain()); - QTC_ASSERT(tc, return false); - return debuggerCommand() != tc->debuggerCommand() - || mkspecList() != tc->mkspecList(); -} - -void MsvcToolChainConfigWidget::autoDetectDebugger() -{ - clearErrorMessage(); - - MsvcToolChain *tc = static_cast<MsvcToolChain *>(toolChain()); - QTC_ASSERT(tc, return); - ProjectExplorer::Abi abi = tc->targetAbi(); - - const QPair<Utils::FileName, Utils::FileName> cdbExecutables = MsvcToolChain::autoDetectCdbDebugger(); - Utils::FileName debugger; - if (abi.wordWidth() == 32) { - if (cdbExecutables.first.isEmpty()) { - setErrorMessage(tr("No CDB debugger detected (neither 32bit nor 64bit).")); - return; - } - debugger = cdbExecutables.first; - } else if (abi.wordWidth() == 64) { - if (cdbExecutables.second.isEmpty()) { - setErrorMessage(tr("No 64bit CDB debugger detected.")); - return; - } - debugger = cdbExecutables.second; - } - if (debugger != debuggerCommand()) { - setDebuggerCommand(debugger); - emitDirty(); - } + return false; } // -------------------------------------------------------------------------- @@ -638,79 +542,10 @@ QList<ToolChain *> MsvcToolChainFactory::autoDetect() vcvarsIA64bat, QString(), true)); } } - if (!results.isEmpty()) { // Detect debugger - const QPair<Utils::FileName, Utils::FileName> cdbDebugger = MsvcToolChain::autoDetectCdbDebugger(); - foreach (ToolChain *tc, results) - static_cast<MsvcToolChain *>(tc)->setDebuggerCommand(tc->targetAbi().wordWidth() == 32 ? cdbDebugger.first : cdbDebugger.second); - } return results; } -// Detect CDB, return a pair of <32bit, 64bit> executables. -QPair<Utils::FileName, Utils::FileName> MsvcToolChain::autoDetectCdbDebugger() -{ - QPair<Utils::FileName, Utils::FileName> result; - QList<Utils::FileName> cdbs; - - QStringList programDirs; - programDirs.append(QString::fromLocal8Bit(qgetenv("ProgramFiles"))); - programDirs.append(QString::fromLocal8Bit(qgetenv("ProgramFiles(x86)"))); - programDirs.append(QString::fromLocal8Bit(qgetenv("ProgramW6432"))); - - foreach (const QString &dirName, programDirs) { - if (dirName.isEmpty()) - continue; - QDir dir(dirName); - // Windows SDK's starting from version 8 live in - // "ProgramDir\Windows Kits\<version>" - const QString windowsKitsFolderName = QLatin1String("Windows Kits"); - if (dir.exists(windowsKitsFolderName)) { - QDir windowKitsFolder = dir; - if (windowKitsFolder.cd(windowsKitsFolderName)) { - // Check in reverse order (latest first) - const QFileInfoList kitFolders = - windowKitsFolder.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot, - QDir::Time|QDir::Reversed); - foreach (const QFileInfo &kitFolderFi, kitFolders) { - const QString path = kitFolderFi.absoluteFilePath(); - const QFileInfo cdb32(path + QLatin1String("/Debuggers/x86/cdb.exe")); - if (cdb32.isExecutable()) - cdbs.push_back(Utils::FileName::fromString(cdb32.absoluteFilePath())); - const QFileInfo cdb64(path + QLatin1String("/Debuggers/x64/cdb.exe")); - if (cdb64.isExecutable()) - cdbs.push_back(Utils::FileName::fromString(cdb64.absoluteFilePath())); - } // for Kits - } // can cd to "Windows Kits" - } // "Windows Kits" exists - - // Pre Windows SDK 8: Check 'Debugging Tools for Windows' - foreach (const QFileInfo &fi, dir.entryInfoList(QStringList(QLatin1String("Debugging Tools for Windows*")), - QDir::Dirs | QDir::NoDotAndDotDot)) { - Utils::FileName filePath(fi); - filePath.appendPath(QLatin1String("cdb.exe")); - if (!cdbs.contains(filePath)) - cdbs.append(filePath); - } - } - - foreach (const Utils::FileName &cdb, cdbs) { - QList<ProjectExplorer::Abi> abis = ProjectExplorer::Abi::abisOfBinary(cdb); - if (abis.isEmpty()) - continue; - if (abis.first().wordWidth() == 32) - result.first = cdb; - else if (abis.first().wordWidth() == 64) - result.second = cdb; - } - - // prefer 64bit debugger, even for 32bit binaries: - if (!result.second.isEmpty()) - result.first = result.second; - - return result; -} - bool MsvcToolChain::operator ==(const ToolChain &other) const { if (!AbstractMsvcToolChain::operator ==(other)) diff --git a/src/plugins/projectexplorer/msvctoolchain.h b/src/plugins/projectexplorer/msvctoolchain.h index d7151e1ba4..ed08140641 100644 --- a/src/plugins/projectexplorer/msvctoolchain.h +++ b/src/plugins/projectexplorer/msvctoolchain.h @@ -56,7 +56,6 @@ public: MsvcToolChain(const QString &name, const Abi &abi, const QString &varsBat, const QString &varsBatArg, bool autodetect = false); - QString legacyId() const; QList<Utils::FileName> suggestedMkspecList() const; static MsvcToolChain *readFromMap(const QVariantMap &data); @@ -73,8 +72,6 @@ public: QString varsBatArg() const { return m_varsBatArg; } - static QPair<Utils::FileName, Utils::FileName> autoDetectCdbDebugger(); - bool operator == (const ToolChain &) const; protected: @@ -110,23 +107,6 @@ public: }; // -------------------------------------------------------------------------- -// MsvcDebuggerConfigLabel: Label displaying debugging tools download info. -// -------------------------------------------------------------------------- - -class MsvcDebuggerConfigLabel : public QLabel -{ - Q_OBJECT -public: - explicit MsvcDebuggerConfigLabel(QWidget *parent = 0); - -private slots: - void slotLinkActivated(const QString &l); - -private: - static QString labelText(); -}; - -// -------------------------------------------------------------------------- // MsvcToolChainConfigWidget // -------------------------------------------------------------------------- @@ -141,9 +121,6 @@ public: void discard() { setFromToolChain(); } bool isDirty() const; -private slots: - void autoDetectDebugger(); - private: void setFromToolChain(); diff --git a/src/plugins/projectexplorer/profile.cpp b/src/plugins/projectexplorer/profile.cpp new file mode 100644 index 0000000000..a183e13d16 --- /dev/null +++ b/src/plugins/projectexplorer/profile.cpp @@ -0,0 +1,307 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#include "profile.h" + +#include "devicesupport/devicemanager.h" +#include "profileinformation.h" +#include "profilemanager.h" +#include "toolchainmanager.h" + +#include <QApplication> +#include <QIcon> +#include <QStyle> +#include <QTextStream> +#include <QUuid> + +namespace { + +const char ID_KEY[] = "PE.Profile.Id"; +const char DISPLAYNAME_KEY[] = "PE.Profile.Name"; +const char AUTODETECTED_KEY[] = "PE.Profile.AutoDetected"; +const char DATA_KEY[] = "PE.Profile.Data"; +const char ICON_KEY[] = "PE.Profile.Icon"; + +} // namespace + +namespace ProjectExplorer { + +// ------------------------------------------------------------------------- +// ProfilePrivate +// ------------------------------------------------------------------------- + +namespace Internal { + +class ProfilePrivate +{ +public: + ProfilePrivate() : + m_id(QUuid::createUuid().toString().toLatin1().constData()), + m_autodetected(false), + m_isValid(true) + { } + + QString m_displayName; + Core::Id m_id; + bool m_autodetected; + bool m_isValid; + QIcon m_icon; + QString m_iconPath; + + QHash<Core::Id, QVariant> m_data; +}; + +} // namespace Internal + +// ------------------------------------------------------------------------- +// Profile: +// ------------------------------------------------------------------------- + +Profile::Profile() : + d(new Internal::ProfilePrivate) +{ + ProfileManager *stm = ProfileManager::instance(); + foreach (ProfileInformation *sti, stm->profileInformation()) + d->m_data.insert(sti->dataId(), sti->defaultValue(this)); + + setDisplayName(QCoreApplication::translate("ProjectExplorer::Profile", "Unnamed")); + setIconPath(QLatin1String(":///DESKTOP///")); +} + +Profile::Profile(const Profile &other) : + d(new Internal::ProfilePrivate) +{ + d->m_displayName = QCoreApplication::translate("ProjectExplorer::Profile", "Clone of %1").arg(other.d->m_displayName); + d->m_autodetected = false; + d->m_data = other.d->m_data; + d->m_isValid = other.d->m_isValid; + d->m_icon = other.d->m_icon; + d->m_iconPath = other.d->m_iconPath; +} + +Profile::~Profile() +{ + delete d; +} + +bool Profile::isValid() const +{ + return d->m_id.isValid() && d->m_isValid; +} + +QList<Task> Profile::validate() +{ + QList<Task> result; + QList<ProfileInformation *> infoList = ProfileManager::instance()->profileInformation(); + foreach (ProfileInformation *i, infoList) + result.append(i->validate(this)); + return result; +} + +QString Profile::displayName() const +{ + return d->m_displayName; +} + +void Profile::setDisplayName(const QString &name) +{ + if (d->m_displayName == name) + return; + d->m_displayName = name; + profileUpdated(); +} + +bool Profile::isAutoDetected() const +{ + return d->m_autodetected; +} + +Core::Id Profile::id() const +{ + return d->m_id; +} + +QIcon Profile::icon() const +{ + return d->m_icon; +} + +QString Profile::iconPath() const +{ + return d->m_iconPath; +} + +void Profile::setIconPath(const QString &path) +{ + if (d->m_iconPath == path) + return; + d->m_iconPath = path; + if (path.isNull()) + d->m_icon = QIcon(); + else if (path == QLatin1String(":///DESKTOP///")) + d->m_icon = qApp->style()->standardIcon(QStyle::SP_ComputerIcon); + else + d->m_icon = QIcon(path); + profileUpdated(); +} + +QVariant Profile::value(const Core::Id &key, const QVariant &unset) const +{ + return d->m_data.value(key, unset); +} + +bool Profile::hasValue(const Core::Id &key) const +{ + return d->m_data.contains(key); +} + +void Profile::setValue(const Core::Id &key, const QVariant &value) +{ + if (d->m_data.value(key) == value) + return; + d->m_data.insert(key, value); + profileUpdated(); +} + +void Profile::removeKey(const Core::Id &key) +{ + if (!d->m_data.contains(key)) + return; + d->m_data.remove(key); + profileUpdated(); +} + +QVariantMap Profile::toMap() const +{ + QVariantMap data; + data.insert(QLatin1String(ID_KEY), QString::fromLatin1(d->m_id.name())); + data.insert(QLatin1String(DISPLAYNAME_KEY), d->m_displayName); + data.insert(QLatin1String(AUTODETECTED_KEY), d->m_autodetected); + data.insert(QLatin1String(ICON_KEY), d->m_iconPath); + + QVariantMap extra; + foreach (const Core::Id &key, d->m_data.keys()) + extra.insert(QString::fromLatin1(key.name().constData()), d->m_data.value(key)); + data.insert(QLatin1String(DATA_KEY), extra); + + return data; +} + +bool Profile::operator==(const Profile &other) const +{ + return d->m_data == other.d->m_data; +} + +void Profile::addToEnvironment(Utils::Environment &env) const +{ + QList<ProfileInformation *> infoList = ProfileManager::instance()->profileInformation(); + foreach (ProfileInformation *si, infoList) + si->addToEnvironment(this, env); +} + +QString Profile::toHtml() +{ + QString rc; + QTextStream str(&rc); + str << "<html><body>"; + str << "<h3>" << displayName() << "</h3>"; + str << "<table>"; + + if (!isValid()) { + QList<Task> issues = validate(); + str << "<p>"; + foreach (const Task &t, issues) { + str << "<b>"; + switch (t.type) { + case Task::Error: + QCoreApplication::translate("ProjectExplorer::Profile", "Error:"); + break; + case Task::Warning: + QCoreApplication::translate("ProjectExplorer::Profile", "Warning:"); + break; + case Task::Unknown: + default: + break; + } + str << "</b>" << t.description << "<br>"; + } + str << "</p>"; + } + + QList<ProfileInformation *> infoList = ProfileManager::instance()->profileInformation(); + foreach (ProfileInformation *i, infoList) { + ProfileInformation::ItemList list = i->toUserOutput(this); + foreach (const ProfileInformation::Item &j, list) + str << "<tr><td><b>" << j.first << ":</b></td><td>" << j.second << "</td></tr>"; + } + str << "</table></body></html>"; + return rc; +} + +bool Profile::fromMap(const QVariantMap &data) +{ + const QString id = data.value(QLatin1String(ID_KEY)).toString(); + if (id.isEmpty()) + return false; + d->m_id = Core::Id(id); + d->m_displayName = data.value(QLatin1String(DISPLAYNAME_KEY)).toString(); + d->m_autodetected = data.value(QLatin1String(AUTODETECTED_KEY)).toBool(); + setIconPath(data.value(QLatin1String(ICON_KEY)).toString()); + + QVariantMap extra = data.value(QLatin1String(DATA_KEY)).toMap(); + foreach (const QString &key, extra.keys()) + d->m_data.insert(Core::Id(key), extra.value(key)); + + return true; +} + +void Profile::setAutoDetected(bool detected) +{ + d->m_autodetected = detected; +} + +void Profile::setId(const Core::Id &id) +{ + d->m_id = id; +} + +void Profile::setValid(bool valid) +{ + d->m_isValid = valid; +} + +void Profile::profileUpdated() +{ + ProfileManager::instance()->notifyAboutUpdate(this); +} + +} // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/profile.h b/src/plugins/projectexplorer/profile.h new file mode 100644 index 0000000000..775100f522 --- /dev/null +++ b/src/plugins/projectexplorer/profile.h @@ -0,0 +1,109 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#ifndef PROFILE_H +#define PROFILE_H + +#include "projectexplorer_export.h" +#include "task.h" + +#include <coreplugin/id.h> + +#include <QVariant> + +namespace Utils { class Environment; } + +namespace ProjectExplorer { + +namespace Internal { +class ProfileManagerPrivate; +class ProfilePrivate; +} // namespace Internal + +/** + * @brief The Profile class + * + * The profile holds a set of values defining a system targeted by the software + * under development. + */ +class PROJECTEXPLORER_EXPORT Profile +{ +public: + Profile(); + Profile(const Profile &other); + ~Profile(); + + bool isValid() const; + QList<Task> validate(); + + QString displayName() const; + void setDisplayName(const QString &name); + + bool isAutoDetected() const; + Core::Id id() const; + + QIcon icon() const; + QString iconPath() const; + void setIconPath(const QString &path); + + QVariant value(const Core::Id &key, const QVariant &unset = QVariant()) const; + bool hasValue(const Core::Id &key) const; + void setValue(const Core::Id &key, const QVariant &value); + void removeKey(const Core::Id &key); + + bool operator==(const Profile &other) const; + + void addToEnvironment(Utils::Environment &env) const; + + QString toHtml(); + +private: + void setAutoDetected(bool detected); + void setId(const Core::Id &id); + void setValid(bool valid); + + void profileUpdated(); + + QVariantMap toMap() const; + bool fromMap(const QVariantMap &value); + + Internal::ProfilePrivate *d; + + friend class ProfileManager; + friend class Internal::ProfileManagerPrivate; +}; + +} // namespace ProjectExplorer + +Q_DECLARE_METATYPE(ProjectExplorer::Profile *) + +#endif // PROFILE_H diff --git a/src/plugins/projectexplorer/profileconfigwidget.h b/src/plugins/projectexplorer/profileconfigwidget.h new file mode 100644 index 0000000000..c98f5cfbc0 --- /dev/null +++ b/src/plugins/projectexplorer/profileconfigwidget.h @@ -0,0 +1,67 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#ifndef PROFILECONFIGWIDGET_H +#define PROFILECONFIGWIDGET_H + +#include "projectexplorer_export.h" + +#include <QWidget> + +namespace ProjectExplorer { + +// -------------------------------------------------------------------------- +// ProfileConfigWidget +// -------------------------------------------------------------------------- + +class PROJECTEXPLORER_EXPORT ProfileConfigWidget : public QWidget +{ + Q_OBJECT + +public: + ProfileConfigWidget(QWidget *parent = 0) : QWidget(parent) + { } + + virtual QString displayName() const = 0; + virtual void makeReadOnly() = 0; + + virtual void apply() = 0; + virtual void discard() = 0; + virtual bool isDirty() const = 0; + +signals: + void dirty(); +}; + +} // namespace ProjectExplorer + +#endif // PROFILECONFIGWIDGET_H diff --git a/src/plugins/projectexplorer/profileinformation.cpp b/src/plugins/projectexplorer/profileinformation.cpp new file mode 100644 index 0000000000..0dd63e56d3 --- /dev/null +++ b/src/plugins/projectexplorer/profileinformation.cpp @@ -0,0 +1,355 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#include "profileinformation.h" + +#include "devicesupport/desktopdevice.h" +#include "devicesupport/devicemanager.h" +#include "projectexplorerconstants.h" +#include "profile.h" +#include "profileinformationconfigwidget.h" +#include "toolchain.h" +#include "toolchainmanager.h" + +#include <extensionsystem/pluginmanager.h> +#include <projectexplorer/abi.h> +#include <utils/pathchooser.h> + +#include <QComboBox> +#include <QHBoxLayout> +#include <QLabel> +#include <QPushButton> + +namespace ProjectExplorer { + +// -------------------------------------------------------------------------- +// SysRootInformation: +// -------------------------------------------------------------------------- + +static const char SYSROOT_INFORMATION[] = "PE.Profile.SysRoot"; + +SysRootProfileInformation::SysRootProfileInformation() +{ + setObjectName(QLatin1String("SysRootInformation")); +} + +Core::Id SysRootProfileInformation::dataId() const +{ + static const Core::Id id(SYSROOT_INFORMATION); + return id; +} + +unsigned int SysRootProfileInformation::priority() const +{ + return 32000; +} + +QVariant SysRootProfileInformation::defaultValue(Profile *p) const +{ + Q_UNUSED(p) + return QString(); +} + +QList<Task> SysRootProfileInformation::validate(Profile *p) const +{ + QList<Task> result; + const Utils::FileName dir = SysRootProfileInformation::sysRoot(p); + if (!dir.toFileInfo().isDir() && SysRootProfileInformation::hasSysRoot(p)) + result << Task(Task::Error, QObject::tr("Sys Root \"%1\" is not a directory.").arg(dir.toUserOutput()), + Utils::FileName(), -1, Core::Id(Constants::TASK_CATEGORY_BUILDSYSTEM)); + return result; +} + +ProfileConfigWidget *SysRootProfileInformation::createConfigWidget(Profile *p) const +{ + Q_ASSERT(p); + return new Internal::SysRootInformationConfigWidget(p); +} + +ProfileInformation::ItemList SysRootProfileInformation::toUserOutput(Profile *p) const +{ + return ItemList() << qMakePair(tr("Sys Root"), sysRoot(p).toUserOutput()); +} + +bool SysRootProfileInformation::hasSysRoot(const Profile *p) +{ + return !p->value(Core::Id(SYSROOT_INFORMATION)).isNull(); +} + +Utils::FileName SysRootProfileInformation::sysRoot(const Profile *p) +{ + if (!p) + return Utils::FileName(); + return Utils::FileName::fromString(p->value(Core::Id(SYSROOT_INFORMATION)).toString()); +} + +void SysRootProfileInformation::setSysRoot(Profile *p, const Utils::FileName &v) +{ + p->setValue(Core::Id(SYSROOT_INFORMATION), v.toString()); +} + +// -------------------------------------------------------------------------- +// ToolChainInformation: +// -------------------------------------------------------------------------- + +static const char TOOLCHAIN_INFORMATION[] = "PE.Profile.ToolChain"; + +ToolChainProfileInformation::ToolChainProfileInformation() +{ + setObjectName(QLatin1String("ToolChainInformation")); + connect(ToolChainManager::instance(), SIGNAL(toolChainRemoved(ProjectExplorer::ToolChain*)), + this, SIGNAL(validationNeeded())); + connect(ToolChainManager::instance(), SIGNAL(toolChainUpdated(ProjectExplorer::ToolChain*)), + this, SIGNAL(validationNeeded())); +} + +Core::Id ToolChainProfileInformation::dataId() const +{ + static const Core::Id id(TOOLCHAIN_INFORMATION); + return id; +} + +unsigned int ToolChainProfileInformation::priority() const +{ + return 30000; +} + +QVariant ToolChainProfileInformation::defaultValue(Profile *p) const +{ + Q_UNUSED(p); + QList<ToolChain *> tcList = ToolChainManager::instance()->toolChains(); + if (tcList.isEmpty()) + return QString(); + + ProjectExplorer::Abi abi = ProjectExplorer::Abi::hostAbi(); + + foreach (ToolChain *tc, tcList) { + if (tc->targetAbi() == abi) + return tc->id(); + } + + return tcList.at(0)->id(); +} + +QList<Task> ToolChainProfileInformation::validate(Profile *p) const +{ + QList<Task> result; + if (!toolChain(p)) { + setToolChain(p, 0); // make sure to clear out no longer known tool chains + result << Task(Task::Error, QObject::tr("No tool chain set up."), + Utils::FileName(), -1, Core::Id(Constants::TASK_CATEGORY_BUILDSYSTEM)); + } + return result; +} + +ProfileConfigWidget *ToolChainProfileInformation::createConfigWidget(Profile *p) const +{ + Q_ASSERT(p); + return new Internal::ToolChainInformationConfigWidget(p); +} + +ProfileInformation::ItemList ToolChainProfileInformation::toUserOutput(Profile *p) const +{ + ToolChain *tc = toolChain(p); + return ItemList() << qMakePair(tr("Tool chain"), tc ? tc->displayName() : tr("None")); +} + +void ToolChainProfileInformation::addToEnvironment(const Profile *p, Utils::Environment &env) const +{ + ToolChain *tc = toolChain(p); + if (tc) + tc->addToEnvironment(env); +} + +ToolChain *ToolChainProfileInformation::toolChain(const Profile *p) +{ + if (!p) + return 0; + const QString id = p->value(Core::Id(TOOLCHAIN_INFORMATION)).toString(); + return ToolChainManager::instance()->findToolChain(id); +} + +void ToolChainProfileInformation::setToolChain(Profile *p, ToolChain *tc) +{ + p->setValue(Core::Id(TOOLCHAIN_INFORMATION), tc ? tc->id() : QString()); +} + +// -------------------------------------------------------------------------- +// DeviceTypeInformation: +// -------------------------------------------------------------------------- + +static const char DEVICETYPE_INFORMATION[] = "PE.Profile.DeviceType"; + +DeviceTypeProfileInformation::DeviceTypeProfileInformation() +{ + setObjectName(QLatin1String("DeviceTypeInformation")); +} + +Core::Id DeviceTypeProfileInformation::dataId() const +{ + static const Core::Id id(DEVICETYPE_INFORMATION); + return id; +} + +unsigned int DeviceTypeProfileInformation::priority() const +{ + return 33000; +} + +QVariant DeviceTypeProfileInformation::defaultValue(Profile *p) const +{ + Q_UNUSED(p); + return QByteArray(Constants::DESKTOP_DEVICE_TYPE); +} + +QList<Task> DeviceTypeProfileInformation::validate(Profile *p) const +{ + IDevice::ConstPtr dev = DeviceProfileInformation::device(p); + QList<Task> result; + if (!dev.isNull() && dev->type() != DeviceTypeProfileInformation::deviceTypeId(p)) + result.append(Task(Task::Error, QObject::tr("Device does not match device type."), + Utils::FileName(), -1, Core::Id(Constants::TASK_CATEGORY_BUILDSYSTEM))); + return result; +} + +ProfileConfigWidget *DeviceTypeProfileInformation::createConfigWidget(Profile *p) const +{ + Q_ASSERT(p); + return new Internal::DeviceTypeInformationConfigWidget(p); +} + +ProfileInformation::ItemList DeviceTypeProfileInformation::toUserOutput(Profile *p) const +{ + Core::Id type = deviceTypeId(p); + QString typeDisplayName = tr("Unknown device type"); + if (type.isValid()) { + QList<IDeviceFactory *> factories + = ExtensionSystem::PluginManager::instance()->getObjects<IDeviceFactory>(); + foreach (IDeviceFactory *factory, factories) { + if (factory->availableCreationIds().contains(type)) { + typeDisplayName = factory->displayNameForId(type); + break; + } + } + } + return ItemList() << qMakePair(tr("Device type"), typeDisplayName); +} + +const Core::Id DeviceTypeProfileInformation::deviceTypeId(const Profile *p) +{ + if (!p) + return Core::Id(); + return Core::Id(p->value(Core::Id(DEVICETYPE_INFORMATION)).toByteArray().constData()); +} + +void DeviceTypeProfileInformation::setDeviceTypeId(Profile *p, Core::Id type) +{ + p->setValue(Core::Id(DEVICETYPE_INFORMATION), type.name()); +} + +// -------------------------------------------------------------------------- +// DeviceInformation: +// -------------------------------------------------------------------------- + +static const char DEVICE_INFORMATION[] = "PE.Profile.Device"; + +DeviceProfileInformation::DeviceProfileInformation() +{ + setObjectName(QLatin1String("DeviceInformation")); + connect(DeviceManager::instance(), SIGNAL(deviceRemoved(Core::Id)), + this, SIGNAL(validationNeeded())); + connect(DeviceManager::instance(), SIGNAL(deviceUpdated(Core::Id)), + this, SIGNAL(validationNeeded())); +} + +Core::Id DeviceProfileInformation::dataId() const +{ + static const Core::Id id(DEVICE_INFORMATION); + return id; +} + +unsigned int DeviceProfileInformation::priority() const +{ + return 32000; +} + +QVariant DeviceProfileInformation::defaultValue(Profile *p) const +{ + Q_UNUSED(p); + return QByteArray(Constants::DESKTOP_DEVICE_ID); +} + +QList<Task> DeviceProfileInformation::validate(Profile *p) const +{ + Q_UNUSED(p); + QList<Task> result; + return result; +} + +ProfileConfigWidget *DeviceProfileInformation::createConfigWidget(Profile *p) const +{ + Q_ASSERT(p); + return new Internal::DeviceInformationConfigWidget(p); +} + +ProfileInformation::ItemList DeviceProfileInformation::toUserOutput(Profile *p) const +{ + IDevice::ConstPtr dev = device(p); + return ItemList() << qMakePair(tr("Device"), dev.isNull() ? tr("Unconfigured") : dev->displayName()); +} + +IDevice::ConstPtr DeviceProfileInformation::device(const Profile *p) +{ + DeviceManager *dm = DeviceManager::instance(); + return dm ? dm->find(deviceId(p)) : IDevice::ConstPtr(); +} + +Core::Id DeviceProfileInformation::deviceId(const Profile *p) +{ + if (p) { + QByteArray idname = p->value(Core::Id(DEVICE_INFORMATION)).toByteArray(); + return idname.isEmpty() ? IDevice::invalidId() : Core::Id(idname.constData()); + } + return IDevice::invalidId(); +} + +void DeviceProfileInformation::setDevice(Profile *p, IDevice::ConstPtr dev) +{ + setDeviceId(p, dev ? dev->id() : IDevice::invalidId()); +} + +void DeviceProfileInformation::setDeviceId(Profile *p, const Core::Id id) +{ + p->setValue(Core::Id(DEVICE_INFORMATION), id.name()); +} + +} // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/profileinformation.h b/src/plugins/projectexplorer/profileinformation.h new file mode 100644 index 0000000000..44fd0793fc --- /dev/null +++ b/src/plugins/projectexplorer/profileinformation.h @@ -0,0 +1,224 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#ifndef PROFILEINFORMATION_H +#define PROFILEINFORMATION_H + +#include "profilemanager.h" +#include "profile.h" + +#include "devicesupport/idevice.h" +#include "toolchain.h" + +#include <utils/fileutils.h> + +#include <QVariant> + +namespace ProjectExplorer { + +class ProfileConfigWidget; + +// -------------------------------------------------------------------------- +// SysRootInformation: +// -------------------------------------------------------------------------- + +class PROJECTEXPLORER_EXPORT SysRootProfileInformation : public ProfileInformation +{ + Q_OBJECT + +public: + SysRootProfileInformation(); + + Core::Id dataId() const; + unsigned int priority() const; + + QVariant defaultValue(Profile *p) const; + + QList<Task> validate(Profile *p) const; + + ProfileConfigWidget *createConfigWidget(Profile *p) const; + + ItemList toUserOutput(Profile *p) const; + + static bool hasSysRoot(const Profile *p); + static Utils::FileName sysRoot(const Profile *p); + static void setSysRoot(Profile *p, const Utils::FileName &v); +}; + +class PROJECTEXPLORER_EXPORT SysRootMatcher : public ProfileMatcher +{ +public: + SysRootMatcher(const Utils::FileName &fn) : m_sysroot(fn) + { } + + bool matches(const Profile *p) const + { + return SysRootProfileInformation::sysRoot(p) == m_sysroot; + } + +private: + Utils::FileName m_sysroot; +}; + +// -------------------------------------------------------------------------- +// ToolChainInformation: +// -------------------------------------------------------------------------- + +class PROJECTEXPLORER_EXPORT ToolChainProfileInformation : public ProfileInformation +{ + Q_OBJECT + +public: + ToolChainProfileInformation(); + + Core::Id dataId() const; + unsigned int priority() const; + + QVariant defaultValue(Profile *p) const; + + QList<Task> validate(Profile *p) const; + + ProfileConfigWidget *createConfigWidget(Profile *p) const; + + ItemList toUserOutput(Profile *p) const; + + void addToEnvironment(const Profile *p, Utils::Environment &env) const; + + static ToolChain *toolChain(const Profile *p); + static void setToolChain(Profile *p, ToolChain *tc); +}; + +class PROJECTEXPLORER_EXPORT ToolChainMatcher : public ProfileMatcher +{ +public: + ToolChainMatcher(const ToolChain *tc) : m_tc(tc) + { } + + bool matches(const Profile *p) const + { + return ToolChainProfileInformation::toolChain(p) == m_tc; + } + +private: + const ToolChain *m_tc; +}; + +// -------------------------------------------------------------------------- +// DeviceTypeInformation: +// -------------------------------------------------------------------------- + +class PROJECTEXPLORER_EXPORT DeviceTypeProfileInformation : public ProfileInformation +{ + Q_OBJECT + +public: + DeviceTypeProfileInformation(); + + Core::Id dataId() const; + unsigned int priority() const; + + QVariant defaultValue(Profile *p) const; + + QList<Task> validate(Profile *p) const; + + ProfileConfigWidget *createConfigWidget(Profile *p) const; + + ItemList toUserOutput(Profile *p) const; + + static const Core::Id deviceTypeId(const Profile *p); + static void setDeviceTypeId(Profile *p, Core::Id type); +}; + +class PROJECTEXPLORER_EXPORT DeviceTypeMatcher : public ProfileMatcher +{ +public: + DeviceTypeMatcher(const Core::Id t) : m_type(t) + { } + + bool matches(const Profile *p) const + { + Core::Id deviceType = DeviceTypeProfileInformation::deviceTypeId(p); + if (!deviceType.isValid()) + return false; + return deviceType == m_type; + } + +private: + const Core::Id m_type; +}; + +// -------------------------------------------------------------------------- +// DeviceInformation: +// -------------------------------------------------------------------------- + +class PROJECTEXPLORER_EXPORT DeviceProfileInformation : public ProfileInformation +{ + Q_OBJECT + +public: + DeviceProfileInformation(); + + Core::Id dataId() const; + unsigned int priority() const; + + QVariant defaultValue(Profile *p) const; + + QList<Task> validate(Profile *p) const; + + ProfileConfigWidget *createConfigWidget(Profile *p) const; + + ItemList toUserOutput(Profile *p) const; + + static IDevice::ConstPtr device(const Profile *p); + static Core::Id deviceId(const Profile *p); + static void setDevice(Profile *p, IDevice::ConstPtr dev); + static void setDeviceId(Profile *p, const Core::Id id); +}; + +class PROJECTEXPLORER_EXPORT DeviceMatcher : public ProfileMatcher +{ +public: + DeviceMatcher(Core::Id id) : m_devId(id) + { } + + bool matches(const Profile *p) const + { + return DeviceProfileInformation::deviceId(p) == m_devId; + } + +private: + Core::Id m_devId; +}; + +} // namespace ProjectExplorer + +#endif // PROFILEINFORMATION_H diff --git a/src/plugins/projectexplorer/profileinformationconfigwidget.cpp b/src/plugins/projectexplorer/profileinformationconfigwidget.cpp new file mode 100644 index 0000000000..457bb8369c --- /dev/null +++ b/src/plugins/projectexplorer/profileinformationconfigwidget.cpp @@ -0,0 +1,353 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#include "profileinformationconfigwidget.h" + +#include "devicesupport/devicemanager.h" +#include "devicesupport/devicemanagermodel.h" +#include "devicesupport/idevicefactory.h" +#include "projectexplorerconstants.h" +#include "profile.h" +#include "profileinformation.h" +#include "toolchain.h" +#include "toolchainmanager.h" + +#include <coreplugin/icore.h> +#include <extensionsystem/pluginmanager.h> +#include <utils/pathchooser.h> + +#include <QComboBox> +#include <QHBoxLayout> +#include <QLabel> +#include <QPushButton> + +namespace ProjectExplorer { +namespace Internal { + +// -------------------------------------------------------------------------- +// SysRootInformationConfigWidget: +// -------------------------------------------------------------------------- + +SysRootInformationConfigWidget::SysRootInformationConfigWidget(Profile *p, QWidget *parent) : + ProfileConfigWidget(parent), + m_profile(p) +{ + QHBoxLayout *layout = new QHBoxLayout(this); + layout->setMargin(0); + m_chooser = new Utils::PathChooser; + m_chooser->setContentsMargins(0, 0, 0, 0); + layout->addWidget(m_chooser); + m_chooser->setExpectedKind(Utils::PathChooser::ExistingDirectory); + + m_chooser->setFileName(SysRootProfileInformation::sysRoot(p)); + + connect(m_chooser, SIGNAL(changed(QString)), this, SIGNAL(dirty())); +} + +QString SysRootInformationConfigWidget::displayName() const +{ + return tr("Sysroot:"); +} + +void SysRootInformationConfigWidget::apply() +{ + SysRootProfileInformation::setSysRoot(m_profile, m_chooser->fileName()); +} + +void SysRootInformationConfigWidget::discard() +{ + m_chooser->setFileName(SysRootProfileInformation::sysRoot(m_profile)); +} + +bool SysRootInformationConfigWidget::isDirty() const +{ + return SysRootProfileInformation::sysRoot(m_profile) != m_chooser->fileName(); +} + +void SysRootInformationConfigWidget::makeReadOnly() +{ + m_chooser->setEnabled(false); +} + +// -------------------------------------------------------------------------- +// ToolChainInformationConfigWidget: +// -------------------------------------------------------------------------- + +ToolChainInformationConfigWidget::ToolChainInformationConfigWidget(Profile *p, QWidget *parent) : + ProfileConfigWidget(parent), + m_isReadOnly(false), m_profile(p), + m_comboBox(new QComboBox), m_manageButton(new QPushButton) +{ + ToolChainManager *tcm = ToolChainManager::instance(); + + QHBoxLayout *layout = new QHBoxLayout(this); + layout->setMargin(0); + m_comboBox->setContentsMargins(0, 0, 0, 0); + m_comboBox->setEnabled(false); + m_comboBox->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); + layout->addWidget(m_comboBox); + + foreach (ToolChain *tc, tcm->toolChains()) + toolChainAdded(tc); + + updateComboBox(); + + discard(); + connect(m_comboBox, SIGNAL(currentIndexChanged(int)), this, SIGNAL(dirty())); + + m_manageButton->setContentsMargins(0, 0, 0, 0); + m_manageButton->setText(tr("Manage...")); + layout->addWidget(m_manageButton); + connect(m_manageButton, SIGNAL(clicked()), this, SLOT(manageToolChains())); + + connect(tcm, SIGNAL(toolChainAdded(ProjectExplorer::ToolChain*)), + this, SLOT(toolChainAdded(ProjectExplorer::ToolChain*))); + connect(tcm, SIGNAL(toolChainRemoved(ProjectExplorer::ToolChain*)), + this, SLOT(toolChainRemoved(ProjectExplorer::ToolChain*))); + connect(tcm, SIGNAL(toolChainUpdated(ProjectExplorer::ToolChain*)), + this, SLOT(toolChainUpdated(ProjectExplorer::ToolChain*))); +} + +QString ToolChainInformationConfigWidget::displayName() const +{ + return tr("Tool chain:"); +} + +void ToolChainInformationConfigWidget::apply() +{ + const QString id = m_comboBox->itemData(m_comboBox->currentIndex()).toString(); + ToolChain *tc = ToolChainManager::instance()->findToolChain(id); + ToolChainProfileInformation::setToolChain(m_profile, tc); +} + +void ToolChainInformationConfigWidget::discard() +{ + m_comboBox->setCurrentIndex(indexOf(ToolChainProfileInformation::toolChain(m_profile))); +} + +bool ToolChainInformationConfigWidget::isDirty() const +{ + ToolChain *tc = ToolChainProfileInformation::toolChain(m_profile); + return (m_comboBox->itemData(m_comboBox->currentIndex()).toString()) + == (tc ? tc->id() : QString()); +} + +void ToolChainInformationConfigWidget::makeReadOnly() +{ + m_comboBox->setEnabled(false); +} + +void ToolChainInformationConfigWidget::toolChainAdded(ProjectExplorer::ToolChain *tc) +{ + m_comboBox->addItem(tc->displayName(), tc->id()); + updateComboBox(); +} + +void ToolChainInformationConfigWidget::toolChainRemoved(ProjectExplorer::ToolChain *tc) +{ + const int pos = indexOf(tc); + if (pos < 0) + return; + m_comboBox->removeItem(pos); + updateComboBox(); +} +void ToolChainInformationConfigWidget::toolChainUpdated(ProjectExplorer::ToolChain *tc) +{ + const int pos = indexOf(tc); + if (pos < 0) + return; + m_comboBox->setItemText(pos, tc->displayName()); +} + +void ToolChainInformationConfigWidget::manageToolChains() +{ + Core::ICore::showOptionsDialog(QLatin1String(ProjectExplorer::Constants::PROJECTEXPLORER_SETTINGS_CATEGORY), + QLatin1String(ProjectExplorer::Constants::TOOLCHAIN_SETTINGS_PAGE_ID)); +} + +void ToolChainInformationConfigWidget::updateComboBox() +{ + // remove unavailable tool chain: + int pos = indexOf(0); + if (pos >= 0) + m_comboBox->removeItem(pos); + + if (m_comboBox->count() == 0) { + m_comboBox->addItem(tr("<No tool chain available>"), QString()); + m_comboBox->setEnabled(false); + } else { + m_comboBox->setEnabled(!m_isReadOnly); + } +} + +int ToolChainInformationConfigWidget::indexOf(const ToolChain *tc) +{ + const QString id = tc ? tc->id() : QString(); + for (int i = 0; i < m_comboBox->count(); ++i) { + if (id == m_comboBox->itemData(i).toString()) + return i; + } + return -1; +} + +// -------------------------------------------------------------------------- +// DeviceTypeInformationConfigWidget: +// -------------------------------------------------------------------------- + +DeviceTypeInformationConfigWidget::DeviceTypeInformationConfigWidget(Profile *p, QWidget *parent) : + ProfileConfigWidget(parent), + m_isReadOnly(false), m_profile(p), + m_comboBox(new QComboBox) +{ + QHBoxLayout *layout = new QHBoxLayout(this); + layout->setMargin(0); + m_comboBox->setContentsMargins(0, 0, 0, 0); + m_comboBox->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); + layout->addWidget(m_comboBox); + + QList<IDeviceFactory *> factories + = ExtensionSystem::PluginManager::instance()->getObjects<IDeviceFactory>(); + foreach (IDeviceFactory *factory, factories) { + foreach (Core::Id id, factory->availableCreationIds()) { + m_comboBox->addItem(factory->displayNameForId(id), QVariant::fromValue(id)); + } + } + + discard(); + connect(m_comboBox, SIGNAL(currentIndexChanged(int)), this, SIGNAL(dirty())); +} + +QString DeviceTypeInformationConfigWidget::displayName() const +{ + return tr("Device Type:"); +} + +void DeviceTypeInformationConfigWidget::apply() +{ + Core::Id devType; + if (m_comboBox->currentIndex() >= 0) + devType = m_comboBox->itemData(m_comboBox->currentIndex()).value<Core::Id>(); + DeviceTypeProfileInformation::setDeviceTypeId(m_profile, devType); +} + +void DeviceTypeInformationConfigWidget::discard() +{ + Core::Id devType = DeviceTypeProfileInformation::deviceTypeId(m_profile); + if (!devType.isValid()) + m_comboBox->setCurrentIndex(-1); + for (int i = 0; i < m_comboBox->count(); ++i) { + if (m_comboBox->itemData(i).value<Core::Id>() == devType) { + m_comboBox->setCurrentIndex(i); + break; + } + } +} + +bool DeviceTypeInformationConfigWidget::isDirty() const +{ + Core::Id devType; + if (m_comboBox->currentIndex() >= 0) + devType = m_comboBox->itemData(m_comboBox->currentIndex()).value<Core::Id>(); + return DeviceTypeProfileInformation::deviceTypeId(m_profile) != devType; +} + +void DeviceTypeInformationConfigWidget::makeReadOnly() +{ + m_comboBox->setEnabled(false); +} + +// -------------------------------------------------------------------------- +// DeviceInformationConfigWidget: +// -------------------------------------------------------------------------- + +DeviceInformationConfigWidget::DeviceInformationConfigWidget(Profile *p, QWidget *parent) : + ProfileConfigWidget(parent), + m_isReadOnly(false), m_profile(p), + m_comboBox(new QComboBox), m_manageButton(new QPushButton), + m_model(new DeviceManagerModel(DeviceManager::instance())) +{ + QHBoxLayout *layout = new QHBoxLayout(this); + layout->setMargin(0); + m_comboBox->setContentsMargins(0, 0, 0, 0); + m_comboBox->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); + layout->addWidget(m_comboBox); + + m_comboBox->setModel(m_model); + + m_manageButton->setContentsMargins(0, 0, 0, 0); + m_manageButton->setText(tr("Manage...")); + layout->addWidget(m_manageButton); + + discard(); + connect(m_comboBox, SIGNAL(currentIndexChanged(int)), this, SIGNAL(dirty())); + + connect(m_manageButton, SIGNAL(clicked()), this, SLOT(manageDevices())); +} + +QString DeviceInformationConfigWidget::displayName() const +{ + return tr("Device:"); +} + +void DeviceInformationConfigWidget::apply() +{ + int idx = m_comboBox->currentIndex(); + if (idx >= 0) + DeviceProfileInformation::setDeviceId(m_profile, m_model->deviceId(idx)); + else + DeviceProfileInformation::setDeviceId(m_profile, IDevice::invalidId()); +} + +void DeviceInformationConfigWidget::discard() +{ + m_comboBox->setCurrentIndex(m_model->indexOf(DeviceProfileInformation::device(m_profile))); +} + +bool DeviceInformationConfigWidget::isDirty() const +{ + Core::Id devId = DeviceProfileInformation::deviceId(m_profile); + return devId != m_model->deviceId(m_comboBox->currentIndex()); +} + +void DeviceInformationConfigWidget::makeReadOnly() +{ + m_comboBox->setEnabled(false); +} + +void DeviceInformationConfigWidget::manageDevices() +{ + Core::ICore::showOptionsDialog(QLatin1String(ProjectExplorer::Constants::DEVICE_SETTINGS_CATEGORY), + QLatin1String(ProjectExplorer::Constants::DEVICE_SETTINGS_PAGE_ID)); +} + +} // namespace Internal +} // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/profileinformationconfigwidget.h b/src/plugins/projectexplorer/profileinformationconfigwidget.h new file mode 100644 index 0000000000..59eafd2a4b --- /dev/null +++ b/src/plugins/projectexplorer/profileinformationconfigwidget.h @@ -0,0 +1,160 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#ifndef PROFILEINFORMATIONCONFIGWIDGET_H +#define PROFILEINFORMATIONCONFIGWIDGET_H + +#include "profileconfigwidget.h" + +QT_FORWARD_DECLARE_CLASS(QComboBox) +QT_FORWARD_DECLARE_CLASS(QPushButton) + +namespace Utils { class PathChooser; } + +namespace ProjectExplorer { + +class DeviceManagerModel; +class Profile; +class ToolChain; + +namespace Internal { + +// -------------------------------------------------------------------------- +// SysRootInformationConfigWidget: +// -------------------------------------------------------------------------- + +class SysRootInformationConfigWidget : public ProfileConfigWidget +{ + Q_OBJECT + +public: + explicit SysRootInformationConfigWidget(Profile *p, QWidget *parent = 0); + + QString displayName() const; + void apply(); + void discard(); + bool isDirty() const; + void makeReadOnly(); + +private: + Profile *m_profile; + Utils::PathChooser *m_chooser; +}; + +// -------------------------------------------------------------------------- +// ToolChainInformationConfigWidget: +// -------------------------------------------------------------------------- + +class ToolChainInformationConfigWidget : public ProfileConfigWidget +{ + Q_OBJECT + +public: + explicit ToolChainInformationConfigWidget(Profile *p, QWidget *parent = 0); + + QString displayName() const; + void apply(); + void discard(); + bool isDirty() const; + void makeReadOnly(); + +private slots: + void toolChainAdded(ProjectExplorer::ToolChain *tc); + void toolChainRemoved(ProjectExplorer::ToolChain *tc); + void toolChainUpdated(ProjectExplorer::ToolChain *tc); + void manageToolChains(); + +private: + void updateComboBox(); + int indexOf(const ToolChain *tc); + + bool m_isReadOnly; + Profile *m_profile; + QComboBox *m_comboBox; + QPushButton *m_manageButton; +}; + +// -------------------------------------------------------------------------- +// DeviceTypeInformationConfigWidget: +// -------------------------------------------------------------------------- + +class DeviceTypeInformationConfigWidget : public ProfileConfigWidget +{ + Q_OBJECT + +public: + explicit DeviceTypeInformationConfigWidget(Profile *p, QWidget *parent = 0); + + QString displayName() const; + void apply(); + void discard(); + bool isDirty() const; + void makeReadOnly(); + +private: + bool m_isReadOnly; + Profile *m_profile; + QComboBox *m_comboBox; +}; + +// -------------------------------------------------------------------------- +// DeviceInformationConfigWidget: +// -------------------------------------------------------------------------- + +class DeviceInformationConfigWidget : public ProfileConfigWidget +{ + Q_OBJECT + +public: + explicit DeviceInformationConfigWidget(Profile *p, QWidget *parent = 0); + + QString displayName() const; + void apply(); + void discard(); + bool isDirty() const; + void makeReadOnly(); + +private slots: + void manageDevices(); + +private: + bool m_isReadOnly; + Profile *m_profile; + QComboBox *m_comboBox; + QPushButton *m_manageButton; + DeviceManagerModel *m_model; +}; + +} // namespace Internal +} // namespace ProjectExplorer + +#endif // PROFILEINFORMATIONCONFIGWIDGET_H diff --git a/src/plugins/projectexplorer/profilemanager.cpp b/src/plugins/projectexplorer/profilemanager.cpp new file mode 100644 index 0000000000..add233b20f --- /dev/null +++ b/src/plugins/projectexplorer/profilemanager.cpp @@ -0,0 +1,471 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#include "profilemanager.h" + +#include "profile.h" +#include "profileconfigwidget.h" +#include "profilemanagerconfigwidget.h" +#include "project.h" + +#include <coreplugin/icore.h> + +#include <extensionsystem/pluginmanager.h> + +#include <utils/persistentsettings.h> +#include <utils/environment.h> + +#include <QCoreApplication> +#include <QDir> +#include <QSettings> + +#include <QFormLayout> +#include <QLabel> +#include <QMainWindow> + +static const char PROFILE_DATA_KEY[] = "Profile."; +static const char PROFILE_COUNT_KEY[] = "Profile.Count"; +static const char PROFILE_FILE_VERSION_KEY[] = "Version"; +static const char PROFILE_DEFAULT_KEY[] = "Profile.Default"; +static const char PROFILE_FILENAME[] = "/qtcreator/profiles.xml"; + +using Utils::PersistentSettingsWriter; +using Utils::PersistentSettingsReader; + +static QString settingsFileName() +{ + ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); + QFileInfo settingsLocation(pm->settings()->fileName()); + return settingsLocation.absolutePath() + QLatin1String(PROFILE_FILENAME); +} + +namespace ProjectExplorer { + +ProfileManager *ProfileManager::m_instance = 0; + +namespace Internal { + +// -------------------------------------------------------------------------- +// ProfileManagerPrivate: +// -------------------------------------------------------------------------- + +class ProfileManagerPrivate +{ +public: + ProfileManagerPrivate(); + ~ProfileManagerPrivate(); + QList<Task> validateProfile(Profile *p) const; + + Profile *m_defaultProfile; + bool m_initialized; + QList<ProfileInformation *> m_informationList; + QList<Profile *> m_profileList; +}; + +ProfileManagerPrivate::ProfileManagerPrivate() + : m_defaultProfile(0), m_initialized(false) +{ } + +ProfileManagerPrivate::~ProfileManagerPrivate() +{ +} + +QList<Task> ProfileManagerPrivate::validateProfile(Profile *p) const +{ + Q_ASSERT(p); + QList<Task> result; + bool hasError = false; + foreach (ProfileInformation *pi, m_informationList) { + QList<Task> tmp = pi->validate(p); + foreach (const Task &t, tmp) + if (t.type == Task::Error) + hasError = true; + result << tmp; + } + p->setValid(!hasError); + return result; +} + +} // namespace Internal + +// -------------------------------------------------------------------------- +// ProfileManager: +// -------------------------------------------------------------------------- + +ProfileManager *ProfileManager::instance() +{ + return m_instance; +} + +ProfileManager::ProfileManager(QObject *parent) : + QObject(parent), + d(new Internal::ProfileManagerPrivate()) +{ + Q_ASSERT(!m_instance); + m_instance = this; + + connect(Core::ICore::instance(), SIGNAL(saveSettingsRequested()), + this, SLOT(saveProfiles())); + + connect(this, SIGNAL(profileAdded(ProjectExplorer::Profile*)), + this, SIGNAL(profilesChanged())); + connect(this, SIGNAL(profileRemoved(ProjectExplorer::Profile*)), + this, SIGNAL(profilesChanged())); + connect(this, SIGNAL(profileUpdated(ProjectExplorer::Profile*)), + this, SIGNAL(profilesChanged())); +} + +void ProfileManager::restoreProfiles() +{ + QList<Profile *> stsToRegister; + QList<Profile *> stsToCheck; + + // read all profiles from SDK + QFileInfo systemSettingsFile(Core::ICore::settings(QSettings::SystemScope)->fileName()); + ProfileList system = restoreProfiles(systemSettingsFile.absolutePath() + QLatin1String(PROFILE_FILENAME)); + QList<Profile *> readSts = system.profiles; + // make sure we mark these as autodetected! + foreach (Profile *p, readSts) + p->setAutoDetected(true); + + stsToRegister = readSts; // SDK profiles are always considered to be up-to-date, so no need to + // recheck them. + + // read all profile chains from user file + ProfileList userProfiles = restoreProfiles(settingsFileName()); + readSts = userProfiles.profiles; + + foreach (Profile *p, readSts) { + if (p->isAutoDetected()) + stsToCheck.append(p); + else + stsToRegister.append(p); + } + readSts.clear(); + + // Then auto create profiles: + QList<Profile *> detectedSts; + Profile *defaultProfile = new Profile; // One profile using default values + defaultProfile->setDisplayName(tr("Desktop")); + defaultProfile->setAutoDetected(true); + defaultProfile->setIconPath(QLatin1String(":///DESKTOP///")); + + detectedSts << defaultProfile; + + // Find/update autodetected profiles: + Profile *toStore = 0; + foreach (Profile *currentDetected, detectedSts) { + toStore = currentDetected; + + // Check whether we had this profile stored and prefer the old one with the old id: + for (int i = 0; i < stsToCheck.count(); ++i) { + if (*(stsToCheck.at(i)) == *currentDetected) { + toStore = stsToCheck.at(i); + stsToCheck.removeAt(i); + delete currentDetected; + break; + } + } + addProfile(toStore); + } + + // Delete all loaded autodetected profiles that were not rediscovered: + qDeleteAll(stsToCheck); + + // Store manual tool chains + foreach (Profile *p, stsToRegister) + addProfile(p); + + Profile *p = find(userProfiles.defaultProfile); + if (p) + setDefaultProfile(p); +} + +ProfileManager::~ProfileManager() +{ + // Clean out profile information to avoid calling them during deregistration: + qDeleteAll(d->m_informationList); + qDeleteAll(d->m_profileList); + delete d; + m_instance = 0; +} + +void ProfileManager::saveProfiles() +{ + PersistentSettingsWriter writer; + writer.saveValue(QLatin1String(PROFILE_FILE_VERSION_KEY), 1); + + int count = 0; + foreach (Profile *p, profiles()) { + QVariantMap tmp = p->toMap(); + if (tmp.isEmpty()) + continue; + writer.saveValue(QString::fromLatin1(PROFILE_DATA_KEY) + QString::number(count), tmp); + ++count; + } + writer.saveValue(QLatin1String(PROFILE_COUNT_KEY), count); + writer.saveValue(QLatin1String(PROFILE_DEFAULT_KEY), + d->m_defaultProfile ? QString::fromLatin1(d->m_defaultProfile->id().name()) : QString()); + writer.save(settingsFileName(), QLatin1String("QtCreatorProfiles"), Core::ICore::mainWindow()); +} + +bool greaterPriority(ProfileInformation *a, ProfileInformation *b) +{ + return a->priority() > b->priority(); +} + +void ProfileManager::registerProfileInformation(ProfileInformation *pi) +{ + QList<ProfileInformation *>::iterator it + = qLowerBound(d->m_informationList.begin(), d->m_informationList.end(), pi, greaterPriority); + d->m_informationList.insert(it, pi); + + connect(pi, SIGNAL(validationNeeded()), this, SLOT(validateProfiles())); + + if (!d->m_initialized) + return; + + foreach (Profile *p, profiles()) { + if (!p->hasValue(pi->dataId())) + p->setValue(pi->dataId(), pi->defaultValue(p)); + } + + return; +} + +void ProfileManager::deregisterProfileInformation(ProfileInformation *pi) +{ + Q_ASSERT(d->m_informationList.contains(pi)); + d->m_informationList.removeAll(pi); + delete pi; +} + +ProfileManager::ProfileList ProfileManager::restoreProfiles(const QString &fileName) +{ + ProfileList result; + + PersistentSettingsReader reader; + if (!reader.load(fileName)) + return result; + QVariantMap data = reader.restoreValues(); + + // Check version: + int version = data.value(QLatin1String(PROFILE_FILE_VERSION_KEY), 0).toInt(); + if (version < 1) + return result; + + const int count = data.value(QLatin1String(PROFILE_COUNT_KEY), 0).toInt(); + for (int i = 0; i < count; ++i) { + const QString key = QString::fromLatin1(PROFILE_DATA_KEY) + QString::number(i); + if (!data.contains(key)) + break; + + const QVariantMap stMap = data.value(key).toMap(); + + Profile *p = new Profile; + if (p->fromMap(stMap)) { + result.profiles.append(p); + } else { + delete p; + qWarning("Warning: Unable to restore profiles stored in %s at position %d.", + qPrintable(QDir::toNativeSeparators(fileName)), i); + } + } + const QString defaultId = data.value(QLatin1String(PROFILE_DEFAULT_KEY)).toString(); + if (defaultId.isEmpty()) + return result; + + const Core::Id id = Core::Id(defaultId); + foreach (Profile *i, result.profiles) { + if (i->id() == id) { + result.defaultProfile = id; + break; + } + } + return result; +} + +QList<Profile *> ProfileManager::profiles(const ProfileMatcher *m) const +{ + if (!d->m_initialized) { + d->m_initialized = true; + const_cast<ProfileManager *>(this)->restoreProfiles(); + } + + QList<Profile *> result; + foreach (Profile *p, d->m_profileList) { + if (!m || m->matches(p)) + result.append(p); + } + return result; +} + +Profile *ProfileManager::find(const Core::Id &id) const +{ + if (!id.isValid()) + return 0; + + foreach (Profile *p, profiles()) { + if (p->id() == id) + return p; + } + return 0; +} + +Profile *ProfileManager::find(const ProfileMatcher *m) const +{ + QList<Profile *> matched = profiles(m); + return matched.isEmpty() ? 0 : matched.first(); +} + +Profile *ProfileManager::defaultProfile() +{ + if (!d->m_initialized) { + d->m_initialized = true; + restoreProfiles(); + } + return d->m_defaultProfile; +} + +QList<ProfileInformation *> ProfileManager::profileInformation() const +{ + return d->m_informationList; +} + +ProfileConfigWidget *ProfileManager::createConfigWidget(Profile *p) const +{ + if (!p) + return 0; + + Internal::ProfileManagerConfigWidget *result = new Internal::ProfileManagerConfigWidget(p); + foreach (ProfileInformation *pi, d->m_informationList) + result->addConfigWidget(pi->createConfigWidget(p)); + + return result; +} + +void ProfileManager::notifyAboutUpdate(ProjectExplorer::Profile *p) +{ + if (!p || !profiles().contains(p)) + return; + d->validateProfile(p); + emit profileUpdated(p); +} + +bool ProfileManager::registerProfile(ProjectExplorer::Profile *p) +{ + if (!p) + return true; + foreach (Profile *current, profiles()) { + if (p == current || *p == *current) + return false; + } + + // Make name unique: + QStringList names; + foreach (Profile *tmp, profiles()) + names << tmp->displayName(); + p->setDisplayName(Project::makeUnique(p->displayName(), names)); + + // make sure we have all the information in our profiles: + foreach (ProfileInformation *pi, d->m_informationList) { + if (!p->hasValue(pi->dataId())) + p->setValue(pi->dataId(), pi->defaultValue(p)); + } + + addProfile(p); + emit profileAdded(p); + return true; +} + +void ProfileManager::deregisterProfile(Profile *p) +{ + if (!p || !profiles().contains(p)) + return; + d->m_profileList.removeOne(p); + if (d->m_defaultProfile == p) { + QList<Profile *> stList = profiles(); + Profile *newDefault = 0; + foreach (Profile *cur, stList) { + if (cur->isValid()) { + newDefault = cur; + break; + } + } + setDefaultProfile(newDefault); + } + emit profileRemoved(p); + delete p; +} + +QList<Task> ProfileManager::validateProfile(Profile *p) +{ + QList<Task> result = d->validateProfile(p); + qSort(result); + return result; +} + +void ProfileManager::setDefaultProfile(Profile *p) +{ + if (d->m_defaultProfile == p) + return; + if (p && !profiles().contains(p)) + return; + d->m_defaultProfile = p; + emit defaultProfileChanged(); +} + +void ProfileManager::validateProfiles() +{ + foreach (Profile *p, profiles()) + d->validateProfile(p); +} + +void ProfileManager::addProfile(Profile *p) +{ + if (!p) + return; + d->validateProfile(p); + d->m_profileList.append(p); + if (!d->m_defaultProfile || + (!d->m_defaultProfile->isValid() && p->isValid())) + setDefaultProfile(p); +} + + +void ProfileInformation::addToEnvironment(const Profile *p, Utils::Environment &env) const +{ + Q_UNUSED(p); + Q_UNUSED(env); +} + +} // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/profilemanager.h b/src/plugins/projectexplorer/profilemanager.h new file mode 100644 index 0000000000..e9bac6dc4f --- /dev/null +++ b/src/plugins/projectexplorer/profilemanager.h @@ -0,0 +1,171 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#ifndef PROFILEMANAGER_H +#define PROFILEMANAGER_H + +#include "projectexplorer_export.h" + +#include "task.h" + +#include <coreplugin/id.h> +#include <utils/fileutils.h> + +#include <QObject> +#include <QPair> + +namespace Utils { class Environment; } + +namespace ProjectExplorer { +class Profile; +class ProfileConfigWidget; + +namespace Internal { +class ProfileManagerPrivate; +class ProfileModel; +} // namespace Internal + +/** + * @brief The ProfileInformation class + * + * One piece of information stored in the profile. + * + * This needs to get registered with the \a ProfileManager. + */ +class PROJECTEXPLORER_EXPORT ProfileInformation : public QObject +{ + Q_OBJECT + +public: + typedef QPair<QString, QString> Item; + typedef QList<Item> ItemList; + + virtual Core::Id dataId() const = 0; + + virtual unsigned int priority() const = 0; // the higher the closer to the top. + + virtual bool visibleIn(Profile *) { return true; } + virtual QVariant defaultValue(Profile *) const = 0; + + virtual QList<Task> validate(Profile *) const = 0; + + virtual ItemList toUserOutput(Profile *p) const = 0; + + virtual ProfileConfigWidget *createConfigWidget(Profile *) const = 0; + + virtual void addToEnvironment(const Profile *p, Utils::Environment &env) const; + +signals: + void validationNeeded(); +}; + +class PROJECTEXPLORER_EXPORT ProfileMatcher +{ +public: + virtual ~ProfileMatcher() { } + virtual bool matches(const Profile *p) const = 0; +}; + +class PROJECTEXPLORER_EXPORT ProfileManager : public QObject +{ + Q_OBJECT + +public: + static ProfileManager *instance(); + ~ProfileManager(); + + QList<Profile *> profiles(const ProfileMatcher *m = 0) const; + Profile *find(const Core::Id &id) const; + Profile *find(const ProfileMatcher *m) const; + Profile *defaultProfile(); + + QList<ProfileInformation *> profileInformation() const; + + ProfileConfigWidget *createConfigWidget(Profile *p) const; + +public slots: + bool registerProfile(ProjectExplorer::Profile *p); + void deregisterProfile(ProjectExplorer::Profile *p); + QList<Task> validateProfile(ProjectExplorer::Profile *p); + void setDefaultProfile(ProjectExplorer::Profile *p); + + void saveProfiles(); + + void registerProfileInformation(ProjectExplorer::ProfileInformation *pi); + void deregisterProfileInformation(ProjectExplorer::ProfileInformation *pi); + +signals: + void profileAdded(ProjectExplorer::Profile *); + // Profile is still valid when this call happens! + void profileRemoved(ProjectExplorer::Profile *); + // Profile was updated. + void profileUpdated(ProjectExplorer::Profile *); + // Default profile was changed. + void defaultProfileChanged(); + // Something changed. + void profilesChanged(); + +private slots: + void validateProfiles(); + +private: + explicit ProfileManager(QObject *parent = 0); + + // Make sure the this is only called after all + // ProfileInformation are registered! + void restoreProfiles(); + class ProfileList + { + public: + ProfileList() + { } + Core::Id defaultProfile; + QList<Profile *> profiles; + }; + ProfileList restoreProfiles(const QString &fileName); + + void notifyAboutUpdate(ProjectExplorer::Profile *p); + void addProfile(Profile *p); + + Internal::ProfileManagerPrivate *const d; + + static ProfileManager *m_instance; + + friend class Internal::ProfileManagerPrivate; // for the restoreToolChains methods + friend class ProjectExplorerPlugin; // for constructor + friend class Profile; + friend class Internal::ProfileModel; +}; + +} // namespace ProjectExplorer + +#endif // PROFILEMANAGER_H diff --git a/src/plugins/projectexplorer/profilemanagerconfigwidget.cpp b/src/plugins/projectexplorer/profilemanagerconfigwidget.cpp new file mode 100644 index 0000000000..04aed656bf --- /dev/null +++ b/src/plugins/projectexplorer/profilemanagerconfigwidget.cpp @@ -0,0 +1,132 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#include "profilemanagerconfigwidget.h" + +#include "profile.h" + +#include <QHBoxLayout> +#include <QFormLayout> +#include <QPushButton> +#include <QFileDialog> + +namespace ProjectExplorer { +namespace Internal { + +ProfileManagerConfigWidget::ProfileManagerConfigWidget(Profile *p, QWidget *parent) : + ProfileConfigWidget(parent), + m_layout(new QFormLayout), + m_iconButton(new QPushButton), + m_profile(p) +{ + m_layout->setMargin(0); + m_layout->setSpacing(6); + + m_iconButton->setMinimumSize(70, 70); + m_iconButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::QSizePolicy::Fixed); + QVBoxLayout *iconLayout = new QVBoxLayout; + iconLayout->addWidget(m_iconButton); + iconLayout->addStretch(); + + QHBoxLayout *masterLayout = new QHBoxLayout(this); + masterLayout->addLayout(iconLayout); + masterLayout->setMargin(0); + masterLayout->setSpacing(12); + masterLayout->addLayout(m_layout); + + discard(); + + connect(m_iconButton, SIGNAL(clicked()), this, SLOT(setIcon())); +} + +QString ProfileManagerConfigWidget::displayName() const +{ + return tr("Profiles"); +} + +void ProfileManagerConfigWidget::apply() +{ + foreach (ProfileConfigWidget *w, m_widgets) + w->apply(); + m_profile->setIconPath(m_iconPath); +} + +void ProfileManagerConfigWidget::discard() +{ + foreach (ProfileConfigWidget *w, m_widgets) + w->discard(); + m_iconButton->setIcon(m_profile->icon()); + m_iconPath = m_profile->iconPath(); +} + +bool ProfileManagerConfigWidget::isDirty() const +{ + foreach (ProfileConfigWidget *w, m_widgets) + if (w->isDirty()) + return true; + return m_profile->iconPath() != m_iconPath; +} + +void ProfileManagerConfigWidget::addConfigWidget(ProjectExplorer::ProfileConfigWidget *widget) +{ + Q_ASSERT(widget); + Q_ASSERT(!m_widgets.contains(widget)); + + connect(widget, SIGNAL(dirty()), this, SIGNAL(dirty())); + m_layout->addRow(widget->displayName(), widget); + m_widgets.append(widget); +} + +void ProfileManagerConfigWidget::makeReadOnly() +{ + foreach (ProfileConfigWidget *w, m_widgets) + w->makeReadOnly(); + m_iconButton->setEnabled(false); +} + +void ProfileManagerConfigWidget::setIcon() +{ + const QString path = QFileDialog::getOpenFileName(0, tr("Select Icon"), m_iconPath, tr("Images (*.png *.xpm *.jpg)")); + if (path.isEmpty()) + return; + + const QIcon icon = QIcon(path); + if (icon.isNull()) + return; + + m_iconButton->setIcon(icon); + m_iconPath = path; + emit dirty(); +} + +} // namespace Internal +} // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/profilemanagerconfigwidget.h b/src/plugins/projectexplorer/profilemanagerconfigwidget.h new file mode 100644 index 0000000000..0bf7204a29 --- /dev/null +++ b/src/plugins/projectexplorer/profilemanagerconfigwidget.h @@ -0,0 +1,78 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#ifndef PROFILEMANAGERWIDGET_H +#define PROFILEMANAGERWIDGET_H + +#include "profileconfigwidget.h" + +QT_BEGIN_NAMESPACE +class QHBoxLayout; +class QFormLayout; +class QPushButton; +QT_END_NAMESPACE + +namespace ProjectExplorer { +class Profile; + +namespace Internal { + +class ProfileManagerConfigWidget : public ProjectExplorer::ProfileConfigWidget +{ + Q_OBJECT + +public: + ProfileManagerConfigWidget(Profile *p, QWidget *parent = 0); + + QString displayName() const; + + void apply(); + void discard(); + bool isDirty() const; + void addConfigWidget(ProjectExplorer::ProfileConfigWidget *widget); + void makeReadOnly(); + +private slots: + void setIcon(); + +private: + QFormLayout *m_layout; + QPushButton *m_iconButton; + QList<ProfileConfigWidget *> m_widgets; + Profile *m_profile; + QString m_iconPath; +}; + +} // namespace Internal +} // namespace ProjectExplorer + +#endif // PROFILEMANAGERCONFIGWIDGET_H diff --git a/src/plugins/projectexplorer/profilemodel.cpp b/src/plugins/projectexplorer/profilemodel.cpp new file mode 100644 index 0000000000..b4da323a81 --- /dev/null +++ b/src/plugins/projectexplorer/profilemodel.cpp @@ -0,0 +1,521 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#include "profilemodel.h" + +#include "profile.h" +#include "profileconfigwidget.h" +#include "profilemanager.h" + +#include <utils/qtcassert.h> + +#include <QApplication> +#include <QLayout> +#include <QMessageBox> + +namespace ProjectExplorer { +namespace Internal { + +class ProfileNode +{ +public: + explicit ProfileNode(ProfileNode *pn, Profile *p = 0, bool c = false) : + parent(pn), profile(p), changed(c) + { + if (pn) + pn->childNodes.append(this); + widget = ProfileManager::instance()->createConfigWidget(p); + if (widget) { + if (p && p->isAutoDetected()) + widget->makeReadOnly(); + widget->setVisible(false); + } + } + + ~ProfileNode() + { + if (parent) + parent->childNodes.removeOne(this); + + // deleting a child removes it from childNodes + // so operate on a temporary list + QList<ProfileNode *> tmp = childNodes; + qDeleteAll(tmp); + Q_ASSERT(childNodes.isEmpty()); + } + + ProfileNode *parent; + QString newName; + QList<ProfileNode *> childNodes; + Profile *profile; + ProfileConfigWidget *widget; + bool changed; +}; + +// -------------------------------------------------------------------------- +// ProfileModel +// -------------------------------------------------------------------------- + +ProfileModel::ProfileModel(QBoxLayout *parentLayout, QObject *parent) : + QAbstractItemModel(parent), + m_parentLayout(parentLayout), + m_defaultNode(0) +{ + Q_ASSERT(m_parentLayout); + + connect(ProfileManager::instance(), SIGNAL(profileAdded(ProjectExplorer::Profile*)), + this, SLOT(addProfile(ProjectExplorer::Profile*))); + connect(ProfileManager::instance(), SIGNAL(profileRemoved(ProjectExplorer::Profile*)), + this, SLOT(removeProfile(ProjectExplorer::Profile*))); + connect(ProfileManager::instance(), SIGNAL(profileUpdated(ProjectExplorer::Profile*)), + this, SLOT(updateProfile(ProjectExplorer::Profile*))); + connect(ProfileManager::instance(), SIGNAL(defaultProfileChanged()), + this, SLOT(changeDefaultProfile())); + + m_root = new ProfileNode(0); + m_autoRoot = new ProfileNode(m_root); + m_manualRoot = new ProfileNode(m_root); + + foreach (Profile *p, ProfileManager::instance()->profiles()) + addProfile(p); + + changeDefaultProfile(); +} + +ProfileModel::~ProfileModel() +{ + delete m_root; +} + +QModelIndex ProfileModel::index(int row, int column, const QModelIndex &parent) const +{ + if (!parent.isValid()) { + if (row >= 0 && row < m_root->childNodes.count()) + return createIndex(row, column, m_root->childNodes.at(row)); + } + ProfileNode *node = static_cast<ProfileNode *>(parent.internalPointer()); + if (row < node->childNodes.count() && column == 0) + return createIndex(row, column, node->childNodes.at(row)); + else + return QModelIndex(); +} + +QModelIndex ProfileModel::parent(const QModelIndex &idx) const +{ + if (!idx.isValid()) + return QModelIndex(); + ProfileNode *node = static_cast<ProfileNode *>(idx.internalPointer()); + if (node->parent == m_root) + return QModelIndex(); + return index(node->parent); +} + +int ProfileModel::rowCount(const QModelIndex &parent) const +{ + if (!parent.isValid()) + return m_root->childNodes.count(); + ProfileNode *node = static_cast<ProfileNode *>(parent.internalPointer()); + return node->childNodes.count(); +} + +int ProfileModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + return 1; +} + +QVariant ProfileModel::data(const QModelIndex &index, int role) const +{ + static QIcon warningIcon(":/projectexplorer/images/compile_warning.png"); + + if (!index.isValid() || index.column() != 0) + return QVariant(); + + ProfileNode *node = static_cast<ProfileNode *>(index.internalPointer()); + QTC_ASSERT(node, return QVariant()); + if (node == m_autoRoot && role == Qt::DisplayRole) + return tr("Auto-detected"); + if (node == m_manualRoot && role == Qt::DisplayRole) + return tr("Manual"); + if (node->profile) { + if (role == Qt::FontRole) { + QFont f = QApplication::font(); + if (node->changed) + f.setBold(!f.bold()); + if (node == m_defaultNode) + f.setItalic(f.style() != QFont::StyleItalic); + return f; + } else if (role == Qt::DisplayRole || role == Qt::EditRole) { + QString baseName = node->newName.isEmpty() ? node->profile->displayName() : node->newName; + if (node == m_defaultNode) + //: Mark up a profile as the default one. + baseName = tr("%1 (default)").arg(baseName); + return baseName; + } else if (role == Qt::DecorationRole) { + return node->profile->isValid() ? QIcon() : warningIcon; + } else if (role == Qt::ToolTipRole) { + return node->profile->toHtml(); + } + } + return QVariant(); +} + +bool ProfileModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + if (!index.isValid()) + return false; + + ProfileNode *node = static_cast<ProfileNode *>(index.internalPointer()); + Q_ASSERT(node); + if (index.column() != 0 || !node->profile || role != Qt::EditRole) + return false; + node->newName = value.toString(); + if (!node->newName.isEmpty() && node->newName != node->profile->displayName()) + node->changed = true; + return true; +} + +Qt::ItemFlags ProfileModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) + return 0; + + ProfileNode *node = static_cast<ProfileNode *>(index.internalPointer()); + Q_ASSERT(node); + if (!node->profile) + return Qt::ItemIsEnabled; + + if (node->profile->isAutoDetected()) + return Qt::ItemIsEnabled | Qt::ItemIsSelectable; + + return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable; +} + +QVariant ProfileModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + Q_UNUSED(section); + if (orientation == Qt::Horizontal && role == Qt::DisplayRole) + return tr("Name"); + return QVariant(); +} + +Profile *ProfileModel::profile(const QModelIndex &index) +{ + if (!index.isValid()) + return 0; + ProfileNode *node = static_cast<ProfileNode *>(index.internalPointer()); + Q_ASSERT(node); + return node->profile; +} + +QModelIndex ProfileModel::indexOf(Profile *p) const +{ + ProfileNode *n = find(p); + return n ? index(n) : QModelIndex(); +} + +void ProfileModel::setDefaultProfile(const QModelIndex &index) +{ + if (!index.isValid()) + return; + ProfileNode *node = static_cast<ProfileNode *>(index.internalPointer()); + Q_ASSERT(node); + if (node->profile) + setDefaultNode(node); +} + +bool ProfileModel::isDefaultProfile(const QModelIndex &index) +{ + return m_defaultNode == static_cast<ProfileNode *>(index.internalPointer()); +} + +ProfileConfigWidget *ProfileModel::widget(const QModelIndex &index) +{ + if (!index.isValid()) + return 0; + ProfileNode *node = static_cast<ProfileNode *>(index.internalPointer()); + Q_ASSERT(node); + return node->widget; +} + +bool ProfileModel::isDirty() const +{ + foreach (ProfileNode *n, m_manualRoot->childNodes) { + if (n->changed) + return true; + } + return false; +} + +bool ProfileModel::isDirty(Profile *p) const +{ + ProfileNode *n = find(p); + return n ? !n->changed : false; +} + +void ProfileModel::setDirty() +{ + ProfileConfigWidget *w = qobject_cast<ProfileConfigWidget *>(sender()); + foreach (ProfileNode *n, m_manualRoot->childNodes) { + if (n->widget == w) { + n->changed = true; + emit dataChanged(index(n, 0), index(n, columnCount(QModelIndex()))); + } + } +} + +void ProfileModel::apply() +{ + // Remove unused profiles: + QList<ProfileNode *> nodes = m_toRemoveList; + foreach (ProfileNode *n, nodes) { + Q_ASSERT(!n->parent); + ProfileManager::instance()->deregisterProfile(n->profile); + } + Q_ASSERT(m_toRemoveList.isEmpty()); + + // Update profiles: + foreach (ProfileNode *n, m_manualRoot->childNodes) { + Q_ASSERT(n); + Q_ASSERT(n->profile); + if (n->changed) { + ProfileManager::instance()->blockSignals(true); + if (!n->newName.isEmpty()) { + n->profile->setDisplayName(n->newName); + n->newName.clear(); + } + if (n->widget) + n->widget->apply(); + n->changed = false; + + ProfileManager::instance()->blockSignals(false); + ProfileManager::instance()->notifyAboutUpdate(n->profile); + emit dataChanged(index(n, 0), index(n, columnCount(QModelIndex()))); + } + } + + // Add new (and already updated) profiles + QStringList removedSts; + nodes = m_toAddList; + foreach (ProfileNode *n, nodes) { + if (!ProfileManager::instance()->registerProfile(n->profile)) + removedSts << n->profile->displayName(); + } + + foreach (ProfileNode *n, m_toAddList) + markForRemoval(n->profile); + + if (removedSts.count() == 1) { + QMessageBox::warning(0, + tr("Duplicate profiles detected"), + tr("The following profile was already configured:<br>" + " %1<br>" + "It was not configured again.") + .arg(removedSts.at(0))); + + } else if (!removedSts.isEmpty()) { + QMessageBox::warning(0, + tr("Duplicate profile detected"), + tr("The following profiles were already configured:<br>" + " %1<br>" + "They were not configured again.") + .arg(removedSts.join(QLatin1String(",<br> ")))); + } + + // Set default profile: + if (m_defaultNode) + ProfileManager::instance()->setDefaultProfile(m_defaultNode->profile); +} + +void ProfileModel::markForRemoval(Profile *p) +{ + ProfileNode *node = find(p); + if (!node) + return; + + beginRemoveRows(index(m_manualRoot), m_manualRoot->childNodes.indexOf(node), m_manualRoot->childNodes.indexOf(node)); + m_manualRoot->childNodes.removeOne(node); + node->parent = 0; + if (m_toAddList.contains(node)) { + delete node->profile; + node->profile = 0; + m_toAddList.removeOne(node); + delete node; + } else { + m_toRemoveList.append(node); + } + endRemoveRows(); + + if (node == m_defaultNode) { + ProfileNode *newDefault = 0; + if (!m_autoRoot->childNodes.isEmpty()) + newDefault = m_autoRoot->childNodes.at(0); + else if (!m_manualRoot->childNodes.isEmpty()) + newDefault = m_manualRoot->childNodes.at(0); + setDefaultNode(newDefault); + } +} + +void ProfileModel::markForAddition(Profile *p) +{ + int pos = m_manualRoot->childNodes.size(); + beginInsertRows(index(m_manualRoot), pos, pos); + + ProfileNode *node = createNode(m_manualRoot, p, true); + m_toAddList.append(node); + + if (!m_defaultNode) + setDefaultNode(node); + + endInsertRows(); +} + +QModelIndex ProfileModel::index(ProfileNode *node, int column) const +{ + if (node->parent == 0) // is root (or was marked for deletion) + return QModelIndex(); + else if (node->parent == m_root) + return index(m_root->childNodes.indexOf(node), column, QModelIndex()); + else + return index(node->parent->childNodes.indexOf(node), column, index(node->parent)); +} + +ProfileNode *ProfileModel::find(Profile *p) const +{ + foreach (ProfileNode *n, m_autoRoot->childNodes) { + if (n->profile == p) + return n; + } + foreach (ProfileNode *n, m_manualRoot->childNodes) { + if (n->profile == p) + return n; + } + return 0; +} + +ProfileNode *ProfileModel::createNode(ProfileNode *parent, Profile *p, bool changed) +{ + ProfileNode *node = new ProfileNode(parent, p, changed); + if (node->widget) { + m_parentLayout->addWidget(node->widget); + connect(node->widget, SIGNAL(dirty()), + this, SLOT(setDirty())); + } + return node; +} + +void ProfileModel::setDefaultNode(ProfileNode *node) +{ + if (m_defaultNode) { + QModelIndex idx = index(m_defaultNode); + if (idx.isValid()) + emit dataChanged(idx, idx); + } + m_defaultNode = node; + if (m_defaultNode) { + QModelIndex idx = index(m_defaultNode); + if (idx.isValid()) + emit dataChanged(idx, idx); + } +} + +void ProfileModel::addProfile(Profile *p) +{ + QList<ProfileNode *> nodes = m_toAddList; + foreach (ProfileNode *n, nodes) { + if (n->profile == p) { + m_toAddList.removeOne(n); + // do not delete n: Still used elsewhere! + return; + } + } + + ProfileNode *parent = m_manualRoot; + if (p->isAutoDetected()) + parent = m_autoRoot; + int row = parent->childNodes.count(); + + beginInsertRows(index(parent), row, row); + createNode(parent, p, false); + endInsertRows(); + + emit profileStateChanged(); +} + +void ProfileModel::removeProfile(Profile *p) +{ + QList<ProfileNode *> nodes = m_toRemoveList; + foreach (ProfileNode *n, nodes) { + if (n->profile == p) { + m_toRemoveList.removeOne(n); + delete n; + return; + } + } + + ProfileNode *parent = m_manualRoot; + if (p->isAutoDetected()) + parent = m_autoRoot; + int row = 0; + ProfileNode *node = 0; + foreach (ProfileNode *current, parent->childNodes) { + if (current->profile == p) { + node = current; + break; + } + ++row; + } + + beginRemoveRows(index(parent), row, row); + parent->childNodes.removeAt(row); + delete node; + endRemoveRows(); + + emit profileStateChanged(); +} + +void ProfileModel::updateProfile(Profile *p) +{ + ProfileNode *n = find(p); + if (n->widget) + n->widget->discard(); + QModelIndex idx = index(n); + emit dataChanged(idx, idx); +} + +void ProfileModel::changeDefaultProfile() +{ + setDefaultNode(find(ProfileManager::instance()->defaultProfile())); +} + +} // namespace Internal +} // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/profilemodel.h b/src/plugins/projectexplorer/profilemodel.h new file mode 100644 index 0000000000..edd4af0a3b --- /dev/null +++ b/src/plugins/projectexplorer/profilemodel.h @@ -0,0 +1,124 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#ifndef PROFILEMODEL_H +#define PROFILEMODEL_H + +#include "projectexplorer_export.h" + +#include <QAbstractItemModel> + +QT_BEGIN_NAMESPACE +class QTreeWidgetItem; +class QBoxLayout; +QT_END_NAMESPACE + +namespace ProjectExplorer { + +class Profile; +class ProfileConfigWidget; +class ProfileFactory; +class ProfileManager; + +namespace Internal { + +class ProfileNode; + +// -------------------------------------------------------------------------- +// ProfileModel: +// -------------------------------------------------------------------------- + +class ProfileModel : public QAbstractItemModel +{ + Q_OBJECT + +public: + explicit ProfileModel(QBoxLayout *parentLayout, QObject *parent = 0); + ~ProfileModel(); + + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; + QModelIndex parent(const QModelIndex &index) const; + int rowCount(const QModelIndex &parent = QModelIndex()) const; + int columnCount(const QModelIndex &parent = QModelIndex()) const; + + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); + Qt::ItemFlags flags(const QModelIndex &index) const; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + + Profile *profile(const QModelIndex &); + QModelIndex indexOf(Profile *p) const; + + void setDefaultProfile(const QModelIndex &index); + bool isDefaultProfile(const QModelIndex &index); + + ProfileConfigWidget *widget(const QModelIndex &); + + bool isDirty() const; + bool isDirty(Profile *p) const; + + void apply(); + + void markForRemoval(Profile *p); + void markForAddition(Profile *p); + +signals: + void profileStateChanged(); + +private slots: + void addProfile(ProjectExplorer::Profile *p); + void removeProfile(ProjectExplorer::Profile *p); + void updateProfile(ProjectExplorer::Profile *p); + void changeDefaultProfile(); + void setDirty(); + +private: + QModelIndex index(ProfileNode *, int column = 0) const; + ProfileNode *find(Profile *) const; + ProfileNode *createNode(ProfileNode *parent, Profile *p, bool changed); + void setDefaultNode(ProfileNode *node); + + ProfileNode *m_root; + ProfileNode *m_autoRoot; + ProfileNode *m_manualRoot; + + QList<ProfileNode *> m_toAddList; + QList<ProfileNode *> m_toRemoveList; + + QBoxLayout *m_parentLayout; + ProfileNode *m_defaultNode; +}; + +} // namespace Internal +} // namespace ProjectExplorer + +#endif // PROFILEMODEL_H diff --git a/src/plugins/projectexplorer/profileoptionspage.cpp b/src/plugins/projectexplorer/profileoptionspage.cpp new file mode 100644 index 0000000000..7cc7d80a89 --- /dev/null +++ b/src/plugins/projectexplorer/profileoptionspage.cpp @@ -0,0 +1,253 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#include "profileoptionspage.h" + +#include "profilemodel.h" +#include "profile.h" +#include "projectexplorerconstants.h" +#include "profileconfigwidget.h" +#include "profilemanager.h" + +#include <coreplugin/icore.h> + +#include <utils/qtcassert.h> + +#include <QHBoxLayout> +#include <QHeaderView> +#include <QItemSelectionModel> +#include <QPushButton> +#include <QTreeView> +#include <QVBoxLayout> + +namespace ProjectExplorer { + +// -------------------------------------------------------------------------- +// ProfileOptionsPage: +// -------------------------------------------------------------------------- + +ProfileOptionsPage::ProfileOptionsPage() : + m_model(0), m_selectionModel(0), m_currentWidget(0), m_toShow(0) +{ + setId(Constants::PROFILE_SETTINGS_PAGE_ID); + setDisplayName(tr("Targets")); + setCategory(QLatin1String(Constants::PROJECTEXPLORER_SETTINGS_CATEGORY)); + setDisplayCategory(QCoreApplication::translate("ProjectExplorer", + Constants::PROJECTEXPLORER_SETTINGS_TR_CATEGORY)); + setCategoryIcon(QLatin1String(Constants::PROJECTEXPLORER_SETTINGS_CATEGORY_ICON)); +} + +QWidget *ProfileOptionsPage::createPage(QWidget *parent) +{ + m_configWidget = new QWidget(parent); + + m_profilesView = new QTreeView(m_configWidget); + m_profilesView->setUniformRowHeights(true); + m_profilesView->header()->setStretchLastSection(true); + + m_addButton = new QPushButton(tr("Add"), m_configWidget); + m_cloneButton = new QPushButton(tr("Clone"), m_configWidget); + m_delButton = new QPushButton(tr("Remove"), m_configWidget); + m_makeDefaultButton = new QPushButton(tr("Make Default"), m_configWidget); + + QVBoxLayout *buttonLayout = new QVBoxLayout(); + buttonLayout->setContentsMargins(0, 0, 0, 0); + buttonLayout->addWidget(m_addButton); + buttonLayout->addWidget(m_cloneButton); + buttonLayout->addWidget(m_delButton); + buttonLayout->addWidget(m_makeDefaultButton); + buttonLayout->addItem(new QSpacerItem(10, 40, QSizePolicy::Minimum, QSizePolicy::Expanding)); + + QVBoxLayout *verticalLayout = new QVBoxLayout(); + verticalLayout->addWidget(m_profilesView); + + QHBoxLayout *horizontalLayout = new QHBoxLayout(m_configWidget); + horizontalLayout->addLayout(verticalLayout); + horizontalLayout->addLayout(buttonLayout); + + Q_ASSERT(!m_model); + m_model = new Internal::ProfileModel(verticalLayout); + connect(m_model, SIGNAL(profileStateChanged()), this, SLOT(updateState())); + + m_profilesView->setModel(m_model); + m_profilesView->header()->setResizeMode(0, QHeaderView::Stretch); + m_profilesView->expandAll(); + + m_selectionModel = m_profilesView->selectionModel(); + connect(m_selectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)), + this, SLOT(profileSelectionChanged())); + connect(ProfileManager::instance(), SIGNAL(profileAdded(ProjectExplorer::Profile*)), + this, SLOT(profileSelectionChanged())); + connect(ProfileManager::instance(), SIGNAL(profileRemoved(ProjectExplorer::Profile*)), + this, SLOT(profileSelectionChanged())); + connect(ProfileManager::instance(), SIGNAL(profileUpdated(ProjectExplorer::Profile*)), + this, SLOT(profileSelectionChanged())); + + // Set up add menu: + connect(m_addButton, SIGNAL(clicked()), this, SLOT(addNewProfile())); + connect(m_cloneButton, SIGNAL(clicked()), this, SLOT(cloneProfile())); + connect(m_delButton, SIGNAL(clicked()), this, SLOT(removeProfile())); + connect(m_makeDefaultButton, SIGNAL(clicked()), this, SLOT(makeDefaultProfile())); + + m_searchKeywords = tr("Profiles"); + + updateState(); + + if (m_toShow) + m_selectionModel->select(m_model->indexOf(m_toShow), + QItemSelectionModel::Clear + | QItemSelectionModel::SelectCurrent + | QItemSelectionModel::Rows); + m_toShow = 0; + + return m_configWidget; +} + +void ProfileOptionsPage::apply() +{ + if (m_model) + m_model->apply(); +} + +void ProfileOptionsPage::finish() +{ + if (m_model) { + delete m_model; + m_model = 0; + } + + m_configWidget = 0; // deleted by settingsdialog + m_selectionModel = 0; // child of m_configWidget + m_profilesView = 0; // child of m_configWidget + m_currentWidget = 0; // deleted by the model + m_toShow = 0; +} + +bool ProfileOptionsPage::matches(const QString &s) const +{ + return m_searchKeywords.contains(s, Qt::CaseInsensitive); +} + +void ProfileOptionsPage::showProfile(Profile *p) +{ + m_toShow = p; +} + +void ProfileOptionsPage::profileSelectionChanged() +{ + if (m_currentWidget) + m_currentWidget->setVisible(false); + + QModelIndex current = currentIndex(); + m_currentWidget = current.isValid() ? m_model->widget(current) : 0; + + if (m_currentWidget) + m_currentWidget->setVisible(true); + updateState(); +} + +void ProfileOptionsPage::addNewProfile() +{ + Profile *p = new Profile; + m_model->markForAddition(p); + + QModelIndex newIdx = m_model->indexOf(p); + m_selectionModel->select(newIdx, + QItemSelectionModel::Clear + | QItemSelectionModel::SelectCurrent + | QItemSelectionModel::Rows); +} + +void ProfileOptionsPage::cloneProfile() +{ + Profile *clone = m_model->profile(currentIndex()); + if (!clone) + return; + + Profile *p = new Profile(*clone); + + m_model->markForAddition(p); + + QModelIndex newIdx = m_model->indexOf(p); + m_selectionModel->select(newIdx, + QItemSelectionModel::Clear + | QItemSelectionModel::SelectCurrent + | QItemSelectionModel::Rows); +} + +void ProfileOptionsPage::removeProfile() +{ + Profile *p = m_model->profile(currentIndex()); + if (!p) + return; + m_model->markForRemoval(p); +} + +void ProfileOptionsPage::makeDefaultProfile() +{ + m_model->setDefaultProfile(currentIndex()); + updateState(); +} + +void ProfileOptionsPage::updateState() +{ + if (!m_profilesView) + return; + + bool canCopy = false; + bool canDelete = false; + bool canMakeDefault = false; + QModelIndex index = currentIndex(); + Profile *p = m_model->profile(index); + if (p) { + canCopy = p->isValid(); + canDelete = !p->isAutoDetected(); + canMakeDefault = !m_model->isDefaultProfile(index); + } + + m_cloneButton->setEnabled(canCopy); + m_delButton->setEnabled(canDelete); + m_makeDefaultButton->setEnabled(canMakeDefault); +} + +QModelIndex ProfileOptionsPage::currentIndex() const +{ + if (!m_selectionModel) + return QModelIndex(); + + QModelIndexList idxs = m_selectionModel->selectedRows(); + if (idxs.count() != 1) + return QModelIndex(); + return idxs.at(0); +} + +} // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/profileoptionspage.h b/src/plugins/projectexplorer/profileoptionspage.h new file mode 100644 index 0000000000..ec60543cc4 --- /dev/null +++ b/src/plugins/projectexplorer/profileoptionspage.h @@ -0,0 +1,104 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#ifndef PROFILEOPTIONSPAGE_H +#define PROFILEOPTIONSPAGE_H + +#include "projectexplorer_export.h" + +#include <coreplugin/dialogs/ioptionspage.h> + +#include <QModelIndex> + +QT_BEGIN_NAMESPACE +class QItemSelectionModel; +class QTreeView; +class QPushButton; +QT_END_NAMESPACE + +namespace ProjectExplorer { + +namespace Internal { class ProfileModel; } + +class Profile; +class ProfileConfigWidget; +class ProfileFactory; +class ProfileManager; + +// -------------------------------------------------------------------------- +// ProfileOptionsPage: +// -------------------------------------------------------------------------- + +class PROJECTEXPLORER_EXPORT ProfileOptionsPage : public Core::IOptionsPage +{ + Q_OBJECT + +public: + ProfileOptionsPage(); + + QWidget *createPage(QWidget *parent); + void apply(); + void finish(); + bool matches(const QString &) const; + + void showProfile(Profile *p); + +private slots: + void profileSelectionChanged(); + void addNewProfile(); + void cloneProfile(); + void removeProfile(); + void makeDefaultProfile(); + void updateState(); + +private: + QModelIndex currentIndex() const; + + QTreeView *m_profilesView; + QPushButton *m_addButton; + QPushButton *m_cloneButton; + QPushButton *m_delButton; + QPushButton *m_makeDefaultButton; + + QWidget *m_configWidget; + QString m_searchKeywords; + + Internal::ProfileModel *m_model; + QItemSelectionModel *m_selectionModel; + ProfileConfigWidget *m_currentWidget; + + Profile *m_toShow; +}; + +} // namespace ProjectExplorer + +#endif // PROFILEOPTIONSPAGE_H diff --git a/src/plugins/projectexplorer/project.cpp b/src/plugins/projectexplorer/project.cpp index 2f7641ec83..c2ef837aa4 100644 --- a/src/plugins/projectexplorer/project.cpp +++ b/src/plugins/projectexplorer/project.cpp @@ -32,11 +32,14 @@ #include "project.h" +#include "buildconfiguration.h" +#include "deployconfiguration.h" #include "editorconfiguration.h" #include "environment.h" #include "projectexplorer.h" #include "projectexplorerconstants.h" #include "projectnodes.h" +#include "runconfiguration.h" #include "target.h" #include "settingsaccessor.h" @@ -44,6 +47,8 @@ #include <coreplugin/icontext.h> #include <extensionsystem/pluginmanager.h> #include <projectexplorer/buildmanager.h> +#include <projectexplorer/profile.h> +#include <projectexplorer/profilemanager.h> #include <limits> #include <utils/qtcassert.h> @@ -112,7 +117,7 @@ Project::~Project() bool Project::hasActiveBuildSettings() const { - return activeTarget() && activeTarget()->buildConfigurationFactory(); + return activeTarget() && IBuildConfigurationFactory::find(activeTarget()); } QString Project::makeUnique(const QString &preferredName, const QStringList &usedNames) @@ -143,7 +148,7 @@ void Project::changeBuildConfigurationEnabled() void Project::addTarget(Target *t) { QTC_ASSERT(t && !d->m_targets.contains(t), return); - QTC_ASSERT(!target(t->id()), return); + QTC_ASSERT(!target(t->profile()), return); Q_ASSERT(t->project() == this); // Check that we don't have a configuration with the same displayName @@ -160,6 +165,10 @@ void Project::addTarget(Target *t) SLOT(changeEnvironment())); connect(t, SIGNAL(buildConfigurationEnabledChanged()), this, SLOT(changeBuildConfigurationEnabled())); + connect(t, SIGNAL(requestBuildSystemEvaluation()), + this, SLOT(triggerBuildSystemEvaluation())); + connect(t, SIGNAL(buildDirectoryChanged()), + this, SLOT(onBuildDirectoryChanged())); emit addedTarget(t); // check activeTarget: @@ -216,7 +225,7 @@ void Project::setActiveTarget(Target *target) } } -Target *Project::target(Core::Id id) const +Target *Project::target(const Core::Id id) const { foreach (Target * target, d->m_targets) { if (target->id() == id) @@ -225,6 +234,55 @@ Target *Project::target(Core::Id id) const return 0; } +Target *Project::target(Profile *p) const +{ + foreach (Target *target, d->m_targets) { + if (target->profile() == p) + return target; + } + return 0; +} + +bool Project::supportsProfile(Profile *p) const +{ + Q_UNUSED(p); + return true; +} + +Target *Project::createTarget(Profile *p) +{ + if (target(p)) + return 0; + + Target *t = new Target(this, p); + t->createDefaultSetup(); + + return t; +} + +Target *Project::restoreTarget(const QVariantMap &data) +{ + Core::Id id = idFromMap(data); + if (target(id)) { + qWarning("Warning: Duplicated target id found, not restoring second target with id '%s'. Continuing.", + qPrintable(id.toString())); + return 0; + } + + Profile *p = ProfileManager::instance()->find(id); + if (!p) { + qWarning("Warning: No profile '%s' found. Continuing.", qPrintable(id.toString())); + return 0; + } + + Target *t = new Target(this, p); + if (!t->fromMap(data)) { + delete t; + return 0; + } + return t; +} + void Project::saveSettings() { emit aboutToSaveSettings(); @@ -314,32 +372,15 @@ bool Project::fromMap(const QVariantMap &map) } QVariantMap targetMap = map.value(key).toMap(); - QList<ITargetFactory *> factories = - ExtensionSystem::PluginManager::getObjects<ITargetFactory>(); - - Target *t = 0; + Target *t = restoreTarget(targetMap); + if (!t) + continue; - Core::Id id = idFromMap(targetMap); - if (target(id)) { - qWarning("Warning: Duplicated target id found, not restoring second target with id '%s'. Continuing.", - qPrintable(id.toString())); - } else { - foreach (ITargetFactory *factory, factories) { - if (factory->canRestore(this, targetMap)) { - t = factory->restore(this, targetMap); - break; - } - } - - if (!t) { - qWarning("Warning: Unable to restore target '%s'. Continuing.", qPrintable(id.toString())); - continue; - } - addTarget(t); - if (i == active) - setActiveTarget(t); - } + addTarget(t); + if (i == active) + setActiveTarget(t); } + return true; } @@ -363,6 +404,9 @@ void Project::setProjectLanguage(Core::Context language) d->m_projectLanguage = language; } +void Project::evaluateBuildSystem() +{ buildSystemEvaluationFinished(true); } + Core::Context Project::projectContext() const { return d->m_projectContext; @@ -380,7 +424,10 @@ QVariant Project::namedSettings(const QString &name) const void Project::setNamedSettings(const QString &name, QVariant &value) { - d->m_pluginSettings.insert(name, value); + if (value.isNull()) + d->m_pluginSettings.remove(name); + else + d->m_pluginSettings.insert(name, value); } bool Project::needsConfiguration() const @@ -393,4 +440,39 @@ void Project::configureAsExampleProject(const QStringList &platforms) Q_UNUSED(platforms); } +void Project::triggerBuildSystemEvaluation() +{ + Target *target = qobject_cast<Target *>(sender()); + if (target && target != activeTarget()) + return; + + evaluateBuildSystem(); +} + +void Project::buildSystemEvaluationFinished(bool success) +{ + if (!success) + return; + + // Create new run configurations: + foreach (Target *t, targets()) + t->updateDefaultRunConfigurations(); + + emit buildSystemEvaluated(); +} + +void Project::onBuildDirectoryInitialized() +{ + Target *target = qobject_cast<Target *>(sender()); + if (target && target == activeTarget()) + emit buildDirectoryInitialized(); +} + +void Project::onBuildDirectoryChanged() +{ + Target *target = qobject_cast<Target *>(sender()); + if (target && target == activeTarget()) + emit buildDirectoryChanged(); +} + } // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/project.h b/src/plugins/projectexplorer/project.h index 49d0aec07b..20a5f58038 100644 --- a/src/plugins/projectexplorer/project.h +++ b/src/plugins/projectexplorer/project.h @@ -52,6 +52,7 @@ class BuildConfigWidget; class IProjectManager; class EditorConfiguration; class ProjectNode; +class Profile; class Target; class ProjectPrivate; @@ -89,7 +90,12 @@ public: // Note: activeTarget can be 0 (if no targets are defined). Target *activeTarget() const; void setActiveTarget(Target *target); - Target *target(Core::Id id) const; + Target *target(const Core::Id id) const; + Target *target(Profile *p) const; + virtual bool supportsProfile(Profile *p) const; + + Target *createTarget(Profile *p); + Target *restoreTarget(const QVariantMap &data); void saveSettings(); bool restoreSettings(); @@ -120,6 +126,12 @@ public: virtual bool needsConfiguration() const; virtual void configureAsExampleProject(const QStringList &platforms); +public slots: + void triggerBuildSystemEvaluation(); + +protected slots: + void buildSystemEvaluationFinished(bool success); + signals: void displayNameChanged(); void fileListChanged(); @@ -133,6 +145,11 @@ signals: void environmentChanged(); void buildConfigurationEnabledChanged(); + // The build directory of the current target/build configuration was successfully + // initialized (or configured). + void buildDirectoryInitialized(); + void buildDirectoryChanged(); + void buildSystemEvaluated(); void settingsLoaded(); void aboutToSaveSettings(); @@ -143,9 +160,18 @@ protected: virtual void setProjectContext(Core::Context context); virtual void setProjectLanguage(Core::Context language); + // Implement this to (re-)evaluate the build system of the project. + // + // This method is triggered by one of its active children (active*Configuration + // of the activeTarget) whenever some settings that has influence on the build + // system parsing is changed. + virtual void evaluateBuildSystem(); + private slots: void changeEnvironment(); void changeBuildConfigurationEnabled(); + void onBuildDirectoryInitialized(); + void onBuildDirectoryChanged(); private: ProjectPrivate *d; diff --git a/src/plugins/projectexplorer/projectconfiguration.cpp b/src/plugins/projectexplorer/projectconfiguration.cpp index 78b3a05a25..bdb4718db7 100644 --- a/src/plugins/projectexplorer/projectconfiguration.cpp +++ b/src/plugins/projectexplorer/projectconfiguration.cpp @@ -41,7 +41,7 @@ const char DEFAULT_DISPLAY_NAME_KEY[] = "ProjectExplorer.ProjectConfiguration.De ProjectConfiguration::ProjectConfiguration(QObject *parent, const Core::Id &id) : QObject(parent), m_id(id) -{ } +{ setObjectName(id.toString()); } ProjectConfiguration::ProjectConfiguration(QObject *parent, const ProjectConfiguration *source) : QObject(parent), diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index 8d9ed394b4..dbc0fd66cb 100644 --- a/src/plugins/projectexplorer/projectexplorer.cpp +++ b/src/plugins/projectexplorer/projectexplorer.cpp @@ -37,6 +37,8 @@ #include "gcctoolchainfactories.h" #include "project.h" #include "projectexplorersettings.h" +#include "profilemanager.h" +#include "profileoptionspage.h" #include "target.h" #include "targetsettingspanel.h" #include "toolchainmanager.h" @@ -63,6 +65,7 @@ #include "processstep.h" #include "projectexplorerconstants.h" #include "customwizard.h" +#include "profileinformation.h" #include "projectfilewizardextension.h" #include "projecttreewidget.h" #include "projectwindow.h" @@ -247,6 +250,8 @@ struct ProjectExplorerPluginPrivate { Core::IMode *m_projectsMode; TaskHub *m_taskHub; + ProfileManager *m_profileManager; + ToolChainManager *m_toolChainManager; bool m_shuttingDown; }; @@ -256,6 +261,8 @@ ProjectExplorerPluginPrivate::ProjectExplorerPluginPrivate() : m_delayedRunConfiguration(0), m_runMode(NoRunMode), m_projectsMode(0), + m_profileManager(0), + m_toolChainManager(0), m_shuttingDown(false) { } @@ -295,6 +302,10 @@ ProjectExplorerPlugin::~ProjectExplorerPlugin() removeObject(d->m_welcomePage); delete d->m_welcomePage; removeObject(this); + // Force sequence of deletion: + delete d->m_profileManager; // remove all the profile informations + delete d->m_toolChainManager; + delete d; } @@ -334,8 +345,10 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er addAutoReleasedObject(new Internal::DesktopDeviceFactory); - new ToolChainManager(this); + d->m_profileManager = new ProfileManager; // register before ToolChainManager + d->m_toolChainManager = new ToolChainManager; addAutoReleasedObject(new Internal::ToolChainOptionsPage); + addAutoReleasedObject(new ProfileOptionsPage); d->m_taskHub = new TaskHub; addAutoReleasedObject(d->m_taskHub); @@ -1095,15 +1108,17 @@ void ProjectExplorerPlugin::extensionsInitialized() addAutoReleasedObject(pf); } d->m_buildManager->extensionsInitialized(); -} -bool ProjectExplorerPlugin::delayedInitialize() -{ + // Register ProfileInformation: + // Only do this now to make sure all device factories were properly initialized. + ProfileManager::instance()->registerProfileInformation(new SysRootProfileInformation); + ProfileManager::instance()->registerProfileInformation(new DeviceProfileInformation); + ProfileManager::instance()->registerProfileInformation(new DeviceTypeProfileInformation); + ProfileManager::instance()->registerProfileInformation(new ToolChainProfileInformation); + DeviceManager *dm = DeviceManager::instance(); if (dm->find(Core::Id(Constants::DESKTOP_DEVICE_ID)).isNull()) DeviceManager::instance()->addDevice(IDevice::Ptr(new DesktopDevice)); - - return true; } void ProjectExplorerPlugin::loadCustomWizards() @@ -2623,6 +2638,9 @@ void ProjectExplorerPlugin::addExistingFiles(const QStringList &filePaths) void ProjectExplorerPlugin::addExistingFiles(ProjectNode *projectNode, const QStringList &filePaths) { + if (!projectNode) // can happen when project is not yet parsed + return; + const QString dir = directoryFor(projectNode); QStringList fileNames = filePaths; QHash<FileType, QString> fileTypeToFiles; diff --git a/src/plugins/projectexplorer/projectexplorer.h b/src/plugins/projectexplorer/projectexplorer.h index 489db72b59..2037050f8d 100644 --- a/src/plugins/projectexplorer/projectexplorer.h +++ b/src/plugins/projectexplorer/projectexplorer.h @@ -105,7 +105,6 @@ public: //PluginInterface bool initialize(const QStringList &arguments, QString *errorMessage); void extensionsInitialized(); - bool delayedInitialize(); ShutdownFlag aboutToShutdown(); void setProjectExplorerSettings(const Internal::ProjectExplorerSettings &pes); diff --git a/src/plugins/projectexplorer/projectexplorer.pro b/src/plugins/projectexplorer/projectexplorer.pro index a9b64a52b8..9f8c632f53 100644 --- a/src/plugins/projectexplorer/projectexplorer.pro +++ b/src/plugins/projectexplorer/projectexplorer.pro @@ -20,6 +20,14 @@ HEADERS += projectexplorer.h \ gcctoolchain.h \ projectexplorer_export.h \ projectwindow.h \ + profile.h \ + profileconfigwidget.h \ + profileinformation.h \ + profileinformationconfigwidget.h \ + profilemanager.h \ + profilemanagerconfigwidget.h \ + profilemodel.h \ + profileoptionspage.h \ buildmanager.h \ buildsteplist.h \ compileoutputwindow.h \ @@ -122,6 +130,13 @@ SOURCES += projectexplorer.cpp \ clangparser.cpp \ gcctoolchain.cpp \ projectwindow.cpp \ + profile.cpp \ + profileinformation.cpp \ + profileinformationconfigwidget.cpp \ + profilemanager.cpp \ + profilemanagerconfigwidget.cpp \ + profilemodel.cpp \ + profileoptionspage.cpp \ buildmanager.cpp \ buildsteplist.cpp \ compileoutputwindow.cpp \ @@ -209,7 +224,6 @@ SOURCES += projectexplorer.cpp \ devicesupport/devicesettingspage.cpp FORMS += processstep.ui \ - toolchainoptionspage.ui \ editorsettingspropertiespage.ui \ sessiondialog.ui \ projectwizardpage.ui \ diff --git a/src/plugins/projectexplorer/projectexplorer.qbs b/src/plugins/projectexplorer/projectexplorer.qbs index a59814d774..f5684dc478 100644 --- a/src/plugins/projectexplorer/projectexplorer.qbs +++ b/src/plugins/projectexplorer/projectexplorer.qbs @@ -108,6 +108,21 @@ QtcPlugin { "processparameters.h", "processstep.cpp", "processstep.h", + "profile.cpp", + "profile.h", + "profileconfigwidget.h", + "profileinformation.cpp", + "profileinformation.h", + "profileinformationconfigwidget.cpp", + "profileinformationconfigwidget.h", + "profilemanager.cpp", + "profilemanager.h", + "profilemanagerconfigwidget.cpp", + "profilemanagerconfigwidget.h", + "profilemodel.cpp", + "profilemodel.h", + "profileoptionspage.cpp", + "profileoptionspage.h", "project.cpp", "project.h", "projectconfiguration.cpp", @@ -158,7 +173,6 @@ QtcPlugin { "toolchainconfigwidget.h", "toolchainmanager.h", "toolchainoptionspage.h", - "toolchainoptionspage.ui", "vcsannotatetaskhandler.h", "environmentitemswidget.h", "abi.cpp", diff --git a/src/plugins/projectexplorer/projectexplorerconstants.h b/src/plugins/projectexplorer/projectexplorerconstants.h index 04fcd6cf17..f7d984a515 100644 --- a/src/plugins/projectexplorer/projectexplorerconstants.h +++ b/src/plugins/projectexplorer/projectexplorerconstants.h @@ -182,6 +182,7 @@ const char PROJECTEXPLORER_SETTINGS_TR_CATEGORY[] = QT_TRANSLATE_NOOP("ProjectEx const char PROJECTEXPLORER_SETTINGS_CATEGORY_ICON[] = ":/core/images/category_buildrun.png"; const char PROJECTEXPLORER_SETTINGS_ID[] = "A.ProjectExplorer.ProjectExplorer"; const char TOOLCHAIN_SETTINGS_PAGE_ID[] = "M.ProjectExplorer.ToolChainOptions"; +const char PROFILE_SETTINGS_PAGE_ID[] = "D.ProjectExplorer.ProfileOptions"; // Device settings page const char DEVICE_SETTINGS_CATEGORY[] = "X.Devices"; diff --git a/src/plugins/projectexplorer/projectwindow.cpp b/src/plugins/projectexplorer/projectwindow.cpp index 9707b49e13..1ef5d92720 100644 --- a/src/plugins/projectexplorer/projectwindow.cpp +++ b/src/plugins/projectexplorer/projectwindow.cpp @@ -34,6 +34,7 @@ #include "doubletabwidget.h" +#include "profilemanager.h" #include "project.h" #include "projectexplorer.h" #include "projectexplorerconstants.h" @@ -128,7 +129,7 @@ PanelsWidget::PanelsWidget(QWidget *parent) : // side of the screen. m_root->setFixedWidth(900); m_root->setContentsMargins(0, 0, 40, 0); - + QPalette pal = m_root->palette(); QColor background = Utils::StyleHelper::mergedColors( palette().window().color(), Qt::white, 85); @@ -262,9 +263,7 @@ ProjectWindow::~ProjectWindow() void ProjectWindow::extensionsInitialized() { - foreach (ITargetFactory *fac, ExtensionSystem::PluginManager::getObjects<ITargetFactory>()) - connect(fac, SIGNAL(canCreateTargetIdsChanged()), - this, SLOT(targetFactoriesChanged())); + connect(ProfileManager::instance(), SIGNAL(profilesChanged()), this, SLOT(handleProfilesChanges())); QList<IProjectPanelFactory *> list = ExtensionSystem::PluginManager::getObjects<IProjectPanelFactory>(); qSort(list.begin(), list.end(), &IPanelFactory::prioritySort); @@ -286,7 +285,7 @@ void ProjectWindow::projectUpdated(Project *p) m_tabWidget->setCurrentIndex(index); } -void ProjectWindow::targetFactoriesChanged() +void ProjectWindow::handleProfilesChanges() { bool changed = false; int index = m_tabWidget->currentIndex(); @@ -309,13 +308,12 @@ bool ProjectWindow::useTargetPage(ProjectExplorer::Project *project) if (project->targets().size() > 1) return true; int count = 0; - foreach (ITargetFactory *fac, ExtensionSystem::PluginManager::getObjects<ITargetFactory>()) { - foreach (Core::Id targetId, fac->supportedTargetIds()) { - if (fac->canCreate(project, targetId)) - ++count; - if (count > 1) - return true; - } + QList<Profile *> profiles = ProfileManager::instance()->profiles(); + foreach (Profile *p, profiles) { + if (project->supportsProfile(p)) + ++count; + if (count > 1) + return true; } return false; } diff --git a/src/plugins/projectexplorer/projectwindow.h b/src/plugins/projectexplorer/projectwindow.h index 1a15fad6af..5a5ec3385b 100644 --- a/src/plugins/projectexplorer/projectwindow.h +++ b/src/plugins/projectexplorer/projectwindow.h @@ -87,7 +87,7 @@ public slots: void projectUpdated(ProjectExplorer::Project *p); private slots: - void targetFactoriesChanged(); + void handleProfilesChanges(); void showProperties(int index, int subIndex); void registerProject(ProjectExplorer::Project*); void deregisterProject(ProjectExplorer::Project*); diff --git a/src/plugins/projectexplorer/runconfiguration.cpp b/src/plugins/projectexplorer/runconfiguration.cpp index d445dcb1ec..d4cada4b63 100644 --- a/src/plugins/projectexplorer/runconfiguration.cpp +++ b/src/plugins/projectexplorer/runconfiguration.cpp @@ -38,6 +38,7 @@ #include "abi.h" #include "buildconfiguration.h" #include "projectexplorerconstants.h" +#include "profileinformation.h" #include <extensionsystem/pluginmanager.h> #include <utils/qtcassert.h> @@ -66,91 +67,6 @@ const char USE_QML_DEBUGGER_AUTO_KEY[] = "RunConfiguration.UseQmlDebuggerAuto"; const char QML_DEBUG_SERVER_PORT_KEY[] = "RunConfiguration.QmlDebugServerPort"; const char USE_MULTIPROCESS_KEY[] = "RunConfiguration.UseMultiProcess"; -// Function objects: - -class RunConfigurationFactoryMatcher -{ -public: - RunConfigurationFactoryMatcher(Target * target) : m_target(target) - { } - - virtual ~RunConfigurationFactoryMatcher() { } - - virtual bool operator()(IRunConfigurationFactory *) const = 0; - - Target *target() const - { - return m_target; - } - -private: - Target *m_target; -}; - -class CreateMatcher : public RunConfigurationFactoryMatcher -{ -public: - CreateMatcher(Target *target, const Core::Id id) : - RunConfigurationFactoryMatcher(target), - m_id(id) - { } - - bool operator()(IRunConfigurationFactory *factory) const - { - return factory->canCreate(target(), m_id); - } - -private: - const Core::Id m_id; -}; - -class CloneMatcher : public RunConfigurationFactoryMatcher -{ -public: - CloneMatcher(Target *target, RunConfiguration *source) : - RunConfigurationFactoryMatcher(target), - m_source(source) - { } - - bool operator()(IRunConfigurationFactory *factory) const - { - return factory->canClone(target(), m_source); - } - -private: - RunConfiguration *m_source; -}; - -class RestoreMatcher : public RunConfigurationFactoryMatcher -{ -public: - RestoreMatcher(Target *target, const QVariantMap &map) : - RunConfigurationFactoryMatcher(target), - m_map(map) - { } - - bool operator()(IRunConfigurationFactory *factory) const - { - return factory->canRestore(target(), m_map); - } - -private: - QVariantMap m_map; -}; - -// Helper methods: - -IRunConfigurationFactory *findRunConfigurationFactory(RunConfigurationFactoryMatcher &matcher) -{ - QList<IRunConfigurationFactory *> factories - = ExtensionSystem::PluginManager::getObjects<IRunConfigurationFactory>(); - foreach (IRunConfigurationFactory *factory, factories) { - if (matcher(factory)) - return factory; - } - return 0; -} - } // namespace /*! @@ -404,6 +320,11 @@ QString RunConfiguration::disabledReason() const return QString(); } +bool RunConfiguration::isConfigured() const +{ + return true; +} + /*! \fn virtual QWidget *ProjectExplorer::RunConfiguration::createConfigurationWidget() @@ -439,7 +360,7 @@ ProjectExplorer::Abi RunConfiguration::abi() const BuildConfiguration *bc = target()->activeBuildConfiguration(); if (!bc) return Abi::hostAbi(); - ToolChain *tc = bc->toolChain(); + ToolChain *tc = ProjectExplorer::ToolChainProfileInformation::toolChain(target()->profile()); if (!tc) return Abi::hostAbi(); return tc->targetAbi(); @@ -516,22 +437,27 @@ IRunConfigurationFactory::~IRunConfigurationFactory() { } -IRunConfigurationFactory *IRunConfigurationFactory::createFactory(Target *parent, const Core::Id id) +IRunConfigurationFactory *IRunConfigurationFactory::find(Target *parent, const QVariantMap &map) { - CreateMatcher matcher(parent, id); - return findRunConfigurationFactory(matcher); -} - -IRunConfigurationFactory *IRunConfigurationFactory::cloneFactory(Target *parent, RunConfiguration *source) -{ - CloneMatcher matcher(parent, source); - return findRunConfigurationFactory(matcher); + QList<IRunConfigurationFactory *> factories + = ExtensionSystem::PluginManager::instance()->getObjects<IRunConfigurationFactory>(); + foreach (IRunConfigurationFactory *factory, factories) { + if (factory->canRestore(parent, map)) + return factory; + } + return 0; } -IRunConfigurationFactory *IRunConfigurationFactory::restoreFactory(Target *parent, const QVariantMap &map) +QList<IRunConfigurationFactory *> IRunConfigurationFactory::find(Target *parent) { - RestoreMatcher matcher(parent, map); - return findRunConfigurationFactory(matcher); + QList<IRunConfigurationFactory *> factories + = ExtensionSystem::PluginManager::instance()->getObjects<IRunConfigurationFactory>(); + QList<IRunConfigurationFactory *> result; + foreach (IRunConfigurationFactory *factory, factories) { + if (!factory->availableCreationIds(parent).isEmpty()) + result << factory; + } + return result; } /*! diff --git a/src/plugins/projectexplorer/runconfiguration.h b/src/plugins/projectexplorer/runconfiguration.h index 78a523e4b9..4d145370b7 100644 --- a/src/plugins/projectexplorer/runconfiguration.h +++ b/src/plugins/projectexplorer/runconfiguration.h @@ -147,18 +147,19 @@ class PROJECTEXPLORER_EXPORT RunConfiguration : public ProjectConfiguration Q_OBJECT public: - virtual ~RunConfiguration(); + ~RunConfiguration(); virtual bool isEnabled() const; virtual QString disabledReason() const; virtual QWidget *createConfigurationWidget() = 0; + virtual bool isConfigured() const; Target *target() const; virtual Utils::OutputFormatter *createOutputFormatter() const; - virtual bool fromMap(const QVariantMap &map); - virtual QVariantMap toMap() const; + bool fromMap(const QVariantMap &map); + QVariantMap toMap() const; DebuggerRunConfigurationAspect *debuggerAspect() const { return m_debuggerAspect; } @@ -212,9 +213,8 @@ public: virtual bool canClone(Target *parent, RunConfiguration *product) const = 0; virtual RunConfiguration *clone(Target *parent, RunConfiguration *product) = 0; - static IRunConfigurationFactory *createFactory(Target *parent, const Core::Id id); - static IRunConfigurationFactory *cloneFactory(Target *parent, RunConfiguration *source); - static IRunConfigurationFactory *restoreFactory(Target *parent, const QVariantMap &map); + static IRunConfigurationFactory *find(Target *parent, const QVariantMap &map); + static QList<IRunConfigurationFactory *> find(Target *parent); signals: void availableCreationIdsChanged(); diff --git a/src/plugins/projectexplorer/runconfigurationmodel.cpp b/src/plugins/projectexplorer/runconfigurationmodel.cpp index 66fc77ec7d..e047451d72 100644 --- a/src/plugins/projectexplorer/runconfigurationmodel.cpp +++ b/src/plugins/projectexplorer/runconfigurationmodel.cpp @@ -182,6 +182,9 @@ void RunConfigurationModel::addedRunConfiguration(ProjectExplorer::RunConfigurat void RunConfigurationModel::removedRunConfiguration(ProjectExplorer::RunConfiguration *rc) { int i = m_runConfigurations.indexOf(rc); + if (i < 0) + return; + beginRemoveRows(QModelIndex(), i, i); m_runConfigurations.removeAt(i); endRemoveRows(); diff --git a/src/plugins/projectexplorer/runsettingspropertiespage.cpp b/src/plugins/projectexplorer/runsettingspropertiespage.cpp index d0497bfcbf..b9c7b8b4c3 100644 --- a/src/plugins/projectexplorer/runsettingspropertiespage.cpp +++ b/src/plugins/projectexplorer/runsettingspropertiespage.cpp @@ -292,6 +292,7 @@ void RunSettingsWidget::addRunConfiguration() RunConfiguration *newRC = fai.factory->create(m_target, fai.id); if (!newRC) return; + QTC_CHECK(newRC->id() == fai.id); m_target->addRunConfiguration(newRC); m_target->setActiveRunConfiguration(newRC); m_removeRunToolButton->setEnabled(m_target->runConfigurations().size() > 1); @@ -370,9 +371,12 @@ void RunSettingsWidget::currentDeployConfigurationChanged(int index) void RunSettingsWidget::aboutToShowDeployMenu() { m_addDeployMenu->clear(); - QList<Core::Id> ids = m_target->availableDeployConfigurationIds(); + DeployConfigurationFactory *factory = DeployConfigurationFactory::find(m_target); + if (!factory) + return; + QList<Core::Id> ids = factory->availableCreationIds(m_target); foreach (Core::Id id, ids) { - QAction *action = m_addDeployMenu->addAction(m_target->displayNameForDeployConfigurationId(id)); + QAction *action = m_addDeployMenu->addAction(factory->displayNameForId(id)); action->setData(QVariant::fromValue(id)); connect(action, SIGNAL(triggered()), this, SLOT(addDeployConfiguration())); @@ -385,9 +389,18 @@ void RunSettingsWidget::addDeployConfiguration() if (!act) return; Core::Id id = act->data().value<Core::Id>(); - DeployConfiguration *newDc = m_target->createDeployConfiguration(id); + DeployConfigurationFactory *factory = DeployConfigurationFactory::find(m_target); + if (!factory) + return; + DeployConfiguration *newDc = 0; + foreach (Core::Id id, factory->availableCreationIds(m_target)) { + if (!factory->canCreate(m_target, id)) + continue; + newDc = factory->create(m_target, id); + } if (!newDc) return; + QTC_CHECK(!newDc || newDc->id() == id); m_target->addDeployConfiguration(newDc); m_target->setActiveDeployConfiguration(newDc); m_removeDeployToolButton->setEnabled(m_target->deployConfigurations().size() > 1); diff --git a/src/plugins/projectexplorer/settingsaccessor.cpp b/src/plugins/projectexplorer/settingsaccessor.cpp index d19eadf5f8..f3330fbdde 100644 --- a/src/plugins/projectexplorer/settingsaccessor.cpp +++ b/src/plugins/projectexplorer/settingsaccessor.cpp @@ -38,9 +38,12 @@ #include "projectexplorersettings.h" #include "projectexplorerconstants.h" #include "target.h" +#include "profile.h" +#include "profilemanager.h" #include <coreplugin/icore.h> #include <coreplugin/idocument.h> +#include <extensionsystem/pluginmanager.h> #include <utils/qtcassert.h> #include <utils/qtcprocess.h> #include <utils/persistentsettings.h> @@ -341,6 +344,52 @@ public: QVariantMap update(Project *project, const QVariantMap &map); }; +// Version 10 introduces disabling buildsteps, and handles upgrading custom process steps +class Version11Handler : public UserFileVersionHandler +{ +public: + Version11Handler(); + ~Version11Handler(); + + int userFileVersion() const + { + return 11; + } + + QString displayUserFileVersion() const + { + return QLatin1String("2.6pre1"); + } + + QVariantMap update(Project *project, const QVariantMap &map); + +private: + void addBuildConfiguration(const QString &origTarget, Profile *p, + bool targetActive, + const QVariantMap &bc, bool bcActive); + void addOtherConfiguration(const QString &origTarget, + const QList<QVariantMap> &dcs, int activeDc, + const QList<QVariantMap> &rcs, int activeRc); + + void parseQtversionFile(); + void parseToolChainFile(); + + class ToolChainExtraData { + public: + explicit ToolChainExtraData(const QString &mks = QString(), const QString &d = QString()) : + m_mkspec(mks), m_debugger(d) + { } + + QString m_mkspec; + QString m_debugger; + }; + + QHash<QString, ToolChainExtraData> m_toolChainExtras; + QHash<int, QString> m_qtVersionExtras; + + QHash<Profile *, QVariantMap> m_targets; +}; + } // namespace // @@ -429,6 +478,7 @@ SettingsAccessor::SettingsAccessor() : addVersionHandler(new Version8Handler); addVersionHandler(new Version9Handler); addVersionHandler(new Version10Handler); + addVersionHandler(new Version11Handler); } SettingsAccessor::~SettingsAccessor() @@ -2277,3 +2327,287 @@ QVariantMap Version10Handler::update(Project *project, const QVariantMap &map) QLatin1String("ProjectExplorer.BuildStep.Enabled"))); return renameKeys(changes, QVariantMap(map)); } + +Version11Handler::Version11Handler() +{ + parseQtversionFile(); + parseToolChainFile(); +} + +Version11Handler::~Version11Handler() +{ + ProfileManager *pm = ProfileManager::instance(); + if (!pm) // Can happen during teardown! + return; + QList<Profile *> knownProfiles = pm->profiles(); + foreach (Profile *p, m_targets.keys()) { + if (!knownProfiles.contains(p)) + delete p; + } + m_targets.clear(); +} + +QVariantMap Version11Handler::update(Project *project, const QVariantMap &map) +{ + Q_UNUSED(project); + QVariantMap result; + ProfileManager *pm = ProfileManager::instance(); + + foreach (Profile *p, pm->profiles()) + m_targets.insert(p, QVariantMap()); + + QMapIterator<QString, QVariant> globalIt(map); + int activeTarget = map.value(QLatin1String("ProjectExplorer.Project.ActiveTarget"), 0).toInt(); + + while (globalIt.hasNext()) { + globalIt.next(); + const QString &globalKey = globalIt.key(); + // Keep everything but targets: + if (!globalKey.startsWith(QLatin1String("ProjectExplorer.Project.Target."))) { + result.insert(globalKey, globalIt.value()); + continue; + } + + // Update Targets: + const QVariantMap &target = globalIt.value().toMap(); + int targetPos = globalKey.mid(globalKey.lastIndexOf(QLatin1Char('.'))).toInt(); + + QVariantMap extraTargetData; + QList<QVariantMap> bcs; + int activeBc = -1; + QList<QVariantMap> dcs; + int activeDc = -1; + QList<QVariantMap> rcs; + int activeRc = -1; + + // Read old target: + QMapIterator<QString, QVariant> targetIt(target); + while (targetIt.hasNext()) { + targetIt.next(); + const QString &targetKey = targetIt.key(); + QList<QVariantMap> newTargets; + // BuildConfigurations: + if (targetKey == QLatin1String("ProjectExplorer.Target.ActiveBuildConfiguration")) + activeBc = targetIt.value().toInt(); + else if (targetKey == QLatin1String("ProjectExplorer.Target.BuildConfigurationCount")) + continue; + else if (targetKey.startsWith(QLatin1String("ProjectExplorer.Target.BuildConfiguration."))) + bcs.append(targetIt.value().toMap()); + else + + // DeployConfigurations: + if (targetKey == QLatin1String("ProjectExplorer.Target.ActiveDeployConfiguration")) + activeDc = targetIt.value().toInt(); + else if (targetKey == QLatin1String("ProjectExplorer.Target.DeployConfigurationCount")) + continue; + else if (targetKey.startsWith(QLatin1String("ProjectExplorer.Target.DeployConfiguration."))) + dcs.append(targetIt.value().toMap()); + else + + // RunConfigurations: + if (targetKey == QLatin1String("ProjectExplorer.Target.ActiveRunConfiguration")) + activeRc = targetIt.value().toInt(); + else if (targetKey == QLatin1String("ProjectExplorer.Target.RunConfigurationCount")) + continue; + else if (targetKey.startsWith(QLatin1String("ProjectExplorer.Target.RunConfiguration."))) + rcs.append(targetIt.value().toMap()); + + // Rest (the target's ProjectConfiguration QList<QVariantMap> newTargets; related settings only as there is nothing else) + else + extraTargetData.insert(targetKey, targetIt.value()); + } + + const QString targetId = extraTargetData.value(QLatin1String("ProjectExplorer.ProjectConfiguration.Id")).toString(); + // Check each BCs/DCs and create profiles as needed + int bcPos = 0; + foreach (const QVariantMap &bc, bcs) { + const QString targetId = extraTargetData.value(QLatin1String("ProjectExplorer.ProjectConfiguration.Id")).toString(); + Profile *tmp = new Profile; + tmp->setDisplayName(extraTargetData.value(QLatin1String("ProjectExplorer.ProjectConfiguration.DisplayName")).toString()); + + if (targetId == QLatin1String("Qt4ProjectManager.Target.AndroidDeviceTarget")) + tmp->setIconPath(QLatin1String(":/android/images/QtAndroid.png")); + else if (targetId == QLatin1String("Qt4ProjectManager.Target.HarmattanDeviceTarget")) + tmp->setIconPath(QLatin1String(":/projectexplorer/images/MaemoDevice.png")); + else if (targetId == QLatin1String("Qt4ProjectManager.Target.MaemoDeviceTarget")) + tmp->setIconPath(QLatin1String(":/projectexplorer/images/MaemoDevice.png")); + else if (targetId == QLatin1String("Qt4ProjectManager.Target.MeegoDeviceTarget")) + tmp->setIconPath(QLatin1String(":/projectexplorer/images/MaemoDevice.png")); + else if (targetId == QLatin1String("Qt4ProjectManager.Target.S60DeviceTarget")) + tmp->setIconPath(QLatin1String(":/projectexplorer/images/SymbianDevice.png")); + else if (targetId == QLatin1String("Qt4ProjectManager.Target.QtSimulatorTarget")) + tmp->setIconPath(QLatin1String(":/projectexplorer/images/SymbianEmulator.png")); + // use default desktop icon + + // Tool chain + QString tcId = bc.value(QLatin1String("CMakeProjectManager.CMakeBuildConfiguration.ToolChain")).toString(); + if (tcId.isEmpty()) + tcId = bc.value(QLatin1String("ProjectExplorer.BuildCOnfiguration.ToolChain")).toString(); + tmp->setValue(Core::Id("PE.Profile.ToolChain"), tcId); + + // QtVersion + int qtVersionId = bc.value(QLatin1String("Qt4ProjectManager.Qt4BuildConfiguration.QtVersionId"), -1).toInt(); + tmp->setValue(Core::Id("QtSupport.QtInformation"), qtVersionId); + + // Debugger + mkspec + if (m_toolChainExtras.contains(tcId)) { + tmp->setValue(Core::Id("Debugger.Information"), m_toolChainExtras.value(tcId).m_debugger); + tmp->setValue(Core::Id("QtPM4.mkSpecInformation"), m_toolChainExtras.value(tcId).m_mkspec); + } + + // SysRoot + if (m_qtVersionExtras.contains(qtVersionId)) + tmp->setValue(Core::Id("PE.Profile.SysRoot"), m_qtVersionExtras.value(qtVersionId)); + + // Device + if (dcs.isEmpty()) { + QByteArray devId; + if (targetId == QLatin1String("Qt4ProjectManager.Target.S60DeviceTarget")) + devId = QByteArray("Symbian Device"); + else + devId = QByteArray("Desktop Device"); + + tmp->setValue(Core::Id("PE.Profile.Device"), devId); + } else { + foreach (const QVariantMap &dc, dcs) { + QByteArray devId = dc.value(QLatin1String("Qt4ProjectManager.MaemoRunConfiguration.DeviceId")).toString().toUtf8(); + if (devId.isEmpty()) + devId = QByteArray("Desktop Device"); + tmp->setValue(Core::Id("PE.Profile.Device"), devId); + } // dcs + } + + addBuildConfiguration(targetId, tmp, activeTarget == targetPos, bc, bcPos == activeBc); + + ++bcPos; + } // bcs + + addOtherConfiguration(targetId, dcs, activeDc, rcs, activeRc); + } + + int newPos = 0; + QList<Profile *> knownProfiles = pm->profiles(); + // Generate new target data: + foreach (Profile *p, m_targets.keys()) { + QVariantMap data = m_targets.value(p); + if (data.isEmpty()) + continue; + + if (!knownProfiles.contains(p)) + pm->registerProfile(p); + + data.insert(QLatin1String("ProjectExplorer.ProjectConfiguration.Id"), p->id().name()); + data.insert(QLatin1String("ProjectExplorer.Target.Profile"), p->id().name()); + data.insert(QLatin1String("ProjectExplorer.ProjectConfiguration.DisplayName"), p->displayName()); + data.insert(QLatin1String("ProjectExplorer.ProjectConfiguration.DefaultDisplayName"), p->displayName()); + + result.insert(QString::fromLatin1("ProjectExplorer.Project.Target.") + QString::number(newPos), data); + if (data.value(QLatin1String("IsActive"), false).toBool()) + result.insert(QLatin1String("ProjectExplorer.Project.ActiveTarget"), newPos); + ++newPos; + } + result.insert(QLatin1String("ProjectExplorer.Project.TargetCount"), newPos); + + return result; +} + +void Version11Handler::addBuildConfiguration(const QString &origTarget, Profile *p, bool targetActive, + const QVariantMap &bc, bool bcActive) +{ + foreach (Profile *i, m_targets.keys()) { + if (*i == *p) { + delete p; + p = i; + } + } + QVariantMap merged = m_targets.value(p); + + int bcCount = merged.value(QLatin1String("ProjectExplorer.Target.BuildConfigurationCount"), 0).toInt(); + merged.insert(QString::fromLatin1("ProjectExplorer.Target.BuildConfiguration.") + QString::number(bcCount), bc); + if (bcActive) + merged.insert(QLatin1String("ProjectExplorer.Target.ActiveBuildConfiguration"), bcCount); + merged.insert(QLatin1String("ProjectExplorer.Target.BuildConfigurationCount"), bcCount + 1); + + if (targetActive && bcActive) + merged.insert(QLatin1String("Update.IsActive"), true); + merged.insert(QLatin1String("Update.OriginalTarget"), origTarget); + + m_targets.insert(p, merged); +} + +void Version11Handler::addOtherConfiguration(const QString &origTarget, const QList<QVariantMap> &dcs, int activeDc, const QList<QVariantMap> &rcs, int activeRc) +{ + foreach (Profile *tmp, m_targets.keys()) { + QVariantMap data = m_targets.value(tmp); + if (data.isEmpty()) + continue; + const QString dataTarget = data.value(QLatin1String("Update.OriginalTarget")).toString(); + if (dataTarget != origTarget) + continue; + + int dcCount = dcs.count(); + data.insert(QLatin1String("ProjectExplorer.Target.DeployConfigurationCount"), dcCount); + for (int i = 0; i < dcCount; ++i) + data.insert(QString::fromLatin1("ProjectExplorer.Target.DeployConfiguration.") + QString::number(i), dcs.at(i)); + data.insert(QLatin1String("ProjectExplorer.Target.ActiveDeployConfiguration"), activeDc); + + int rcCount = rcs.count(); + data.insert(QLatin1String("ProjectExplorer.Target.RunConfigurationCount"), rcCount); + for (int i = 0; i < rcCount; ++i) + data.insert(QString::fromLatin1("ProjectExplorer.Target.RunConfiguration.") + QString::number(i), rcs.at(i)); + data.insert(QLatin1String("ProjectExplorer.Target.ActiveRunConfiguration"), activeRc); + + m_targets.insert(tmp, data); + } +} + +void Version11Handler::parseQtversionFile() +{ + ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); + QFileInfo settingsLocation(pm->settings()->fileName()); + QString fileName = settingsLocation.absolutePath() + QLatin1String("/qtversion.xml"); + Utils::PersistentSettingsReader reader; + if (!reader.load(fileName)) + return; + QVariantMap data = reader.restoreValues(); + + int count = data.value(QLatin1String("QtVersion.Count"), 0).toInt(); + for (int i = 0; i < count; ++i) { + const QString key = QString::fromLatin1("QtVersion.") + QString::number(i); + if (!data.contains(key)) + continue; + + const QVariantMap qtversionMap = data.value(key).toMap(); + QString sysRoot = qtversionMap.value(QLatin1String("SystemRoot")).toString(); + int id = qtversionMap.value(QLatin1String("Id")).toInt(); + if (id > -1 && !sysRoot.isEmpty()) + m_qtVersionExtras.insert(id, sysRoot); + } +} + +void Version11Handler::parseToolChainFile() +{ + ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); + QFileInfo settingsLocation(pm->settings()->fileName()); + QString fileName = settingsLocation.absolutePath() + QLatin1String("/toolChains.xml"); + Utils::PersistentSettingsReader reader; + if (!reader.load(fileName)) + return; + QVariantMap data = reader.restoreValues(); + int count = data.value(QLatin1String("ToolChain.Count"), 0).toInt(); + for (int i = 0; i < count; ++i) { + const QString key = QString::fromLatin1("ToolChain.") + QString::number(i); + if (!data.contains(key)) + continue; + + const QVariantMap tcMap = data.value(key).toMap(); + QString id = tcMap.value(QLatin1String("ProjectExplorer.ToolChain.Id")).toString(); + if (id.isEmpty()) + continue; + QString mkspec = tcMap.value(QLatin1String("ProjectExplorer.ToolChain.MkSpecOverride")).toString(); + QString debugger = tcMap.value(QLatin1String("ProjectExplorer.GccToolChain.Debugger")).toString(); + + m_toolChainExtras.insert(id, ToolChainExtraData(mkspec, debugger)); + } +} + diff --git a/src/plugins/projectexplorer/target.cpp b/src/plugins/projectexplorer/target.cpp index a3a86af7a1..a35c37aca7 100644 --- a/src/plugins/projectexplorer/target.cpp +++ b/src/plugins/projectexplorer/target.cpp @@ -32,13 +32,14 @@ #include "target.h" -#include "toolchain.h" +#include "profile.h" +#include "profileinformation.h" +#include "profilemanager.h" #include "buildconfiguration.h" #include "deployconfiguration.h" #include "project.h" #include "projectexplorerconstants.h" #include "runconfiguration.h" -#include "toolchainmanager.h" #include <limits> #include <coreplugin/coreconstants.h> @@ -48,6 +49,7 @@ #include <projectexplorer/projectexplorer.h> #include <utils/qtcassert.h> +#include <QDebug> #include <QIcon> #include <QPainter> @@ -94,6 +96,8 @@ public: QPixmap m_connectedPixmap; QPixmap m_readyToUsePixmap; QPixmap m_disconnectedPixmap; + + Profile *m_profile; }; TargetPrivate::TargetPrivate() : @@ -103,7 +107,8 @@ TargetPrivate::TargetPrivate() : m_activeRunConfiguration(0), m_connectedPixmap(QLatin1String(":/projectexplorer/images/DeviceConnected.png")), m_readyToUsePixmap(QLatin1String(":/projectexplorer/images/DeviceReadyToUse.png")), - m_disconnectedPixmap(QLatin1String(":/projectexplorer/images/DeviceDisconnected.png")) + m_disconnectedPixmap(QLatin1String(":/projectexplorer/images/DeviceDisconnected.png")), + m_profile(0) { } @@ -113,16 +118,28 @@ QList<DeployConfigurationFactory *> TargetPrivate::deployFactories() const } -Target::Target(Project *project, const Core::Id id) : - ProjectConfiguration(project, id), +Target::Target(Project *project, Profile *p) : + ProjectConfiguration(project, p->id()), d(new TargetPrivate) { connect(DeviceManager::instance(), SIGNAL(updated()), this, SLOT(updateDeviceState())); + + d->m_profile = p; + + setDisplayName(d->m_profile->displayName()); + setIcon(d->m_profile->icon()); + + ProfileManager *pm = ProfileManager::instance(); + connect(pm, SIGNAL(profileUpdated(ProjectExplorer::Profile*)), + this, SLOT(handleProfileUpdates(ProjectExplorer::Profile*))); + connect(pm, SIGNAL(profileRemoved(ProjectExplorer::Profile*)), + this, SLOT(handleProfileRemoval(ProjectExplorer::Profile*))); } Target::~Target() { qDeleteAll(d->m_buildConfigurations); + qDeleteAll(d->m_deployConfigurations); qDeleteAll(d->m_runConfigurations); delete d; } @@ -155,19 +172,47 @@ void Target::changeRunConfigurationEnabled() emit runConfigurationEnabledChanged(); } +void Target::onBuildDirectoryChanged() +{ + BuildConfiguration *bc = qobject_cast<BuildConfiguration *>(sender()); + if (bc) + emit buildDirectoryChanged(); +} + +void Target::handleProfileUpdates(Profile *p) +{ + if (p != d->m_profile) + return; + + setDisplayName(p->displayName()); + setIcon(p->icon()); + updateDefaultDeployConfigurations(); + emit profileChanged(); +} + +void Target::handleProfileRemoval(Profile *p) +{ + if (p != d->m_profile) + return; + d->m_profile = 0; + project()->removeTarget(this); +} + Project *Target::project() const { return static_cast<Project *>(parent()); } +Profile *Target::profile() const +{ + return d->m_profile; +} + void Target::addBuildConfiguration(BuildConfiguration *configuration) { QTC_ASSERT(configuration && !d->m_buildConfigurations.contains(configuration), return); Q_ASSERT(configuration->target() == this); - if (!buildConfigurationFactory()) - return; - // Check that we don't have a configuration with the same displayName QString configurationDisplayName = configuration->displayName(); QStringList displayNames; @@ -175,18 +220,12 @@ void Target::addBuildConfiguration(BuildConfiguration *configuration) displayNames << bc->displayName(); configurationDisplayName = Project::makeUnique(configurationDisplayName, displayNames); if (configurationDisplayName != configuration->displayName()) { - if (configuration->usesDefaultDisplayName()) { + if (configuration->usesDefaultDisplayName()) configuration->setDefaultDisplayName(configurationDisplayName); - } else { + else configuration->setDisplayName(configurationDisplayName); - } } - // Make sure we have a sane tool chain if at all possible - if (!configuration->toolChain() - || !possibleToolChains(configuration).contains(configuration->toolChain())) - configuration->setToolChain(preferredToolChain(configuration)); - // add it d->m_buildConfigurations.push_back(configuration); @@ -194,9 +233,11 @@ void Target::addBuildConfiguration(BuildConfiguration *configuration) connect(configuration, SIGNAL(environmentChanged()), SLOT(changeEnvironment())); - connect(configuration, SIGNAL(enabledChanged()), this, SLOT(changeBuildConfigurationEnabled())); + connect(configuration, SIGNAL(requestBuildSystemEvaluation()), + this, SLOT(onRequestBuildSystemEvaluation())); + if (!activeBuildConfiguration()) setActiveBuildConfiguration(configuration); @@ -247,6 +288,8 @@ void Target::setActiveBuildConfiguration(BuildConfiguration *configuration) emit activeBuildConfigurationChanged(d->m_activeBuildConfiguration); emit environmentChanged(); emit buildConfigurationEnabledChanged(); + emit buildDirectoryChanged(); + emit requestBuildSystemEvaluation(); } } @@ -270,6 +313,7 @@ void Target::addDeployConfiguration(DeployConfiguration *dc) d->m_deployConfigurations.push_back(dc); connect(dc, SIGNAL(enabledChanged()), this, SLOT(changeDeployConfigurationEnabled())); + connect(dc, SIGNAL(requestBuildSystemEvaluation()), this, SLOT(onRequestBuildSystemEvaluation())); emit addedDeployConfiguration(dc); @@ -322,36 +366,11 @@ void Target::setActiveDeployConfiguration(DeployConfiguration *dc) d->m_activeDeployConfiguration = dc; emit activeDeployConfigurationChanged(d->m_activeDeployConfiguration); emit deployConfigurationEnabledChanged(); + emit requestBuildSystemEvaluation(); } updateDeviceState(); } -QList<Core::Id> Target::availableDeployConfigurationIds() -{ - QList<Core::Id> ids; - foreach (const DeployConfigurationFactory * const factory, d->deployFactories()) - ids << factory->availableCreationIds(this); - return ids; -} - -QString Target::displayNameForDeployConfigurationId(Core::Id &id) -{ - foreach (const DeployConfigurationFactory * const factory, d->deployFactories()) { - if (factory->availableCreationIds(this).contains(id)) - return factory->displayNameForId(id); - } - return QString(); -} - -DeployConfiguration *Target::createDeployConfiguration(Core::Id id) -{ - foreach (DeployConfigurationFactory * const factory, d->deployFactories()) { - if (factory->canCreate(this, id)) - return factory->create(this, id); - } - return 0; -} - QList<RunConfiguration *> Target::runConfigurations() const { return d->m_runConfigurations; @@ -410,6 +429,7 @@ void Target::setActiveRunConfiguration(RunConfiguration* configuration) d->m_activeRunConfiguration = configuration; emit activeRunConfigurationChanged(d->m_activeRunConfiguration); emit runConfigurationEnabledChanged(); + emit requestBuildSystemEvaluation(); } updateDeviceState(); } @@ -452,31 +472,14 @@ void Target::setToolTip(const QString &text) emit toolTipChanged(); } -QList<ToolChain *> Target::possibleToolChains(BuildConfiguration *) const -{ - QList<ToolChain *> tcList = ToolChainManager::instance()->toolChains(); - QList<ToolChain *> result; - foreach (ToolChain *tc, tcList) { - QList<Core::Id> restricted = tc->restrictedToTargets(); - if (restricted.isEmpty() || restricted.contains(id())) - result.append(tc); - } - return result; -} - -ToolChain *Target::preferredToolChain(BuildConfiguration *bc) const -{ - QList<ToolChain *> tcs = possibleToolChains(bc); - if (tcs.isEmpty()) - return 0; - return tcs.at(0); -} - QVariantMap Target::toMap() const { - const QList<BuildConfiguration *> bcs = buildConfigurations(); + if (!d->m_profile) // Profile was deleted, target is only around to be copied. + return QVariantMap(); QVariantMap map(ProjectConfiguration::toMap()); + + const QList<BuildConfiguration *> bcs = buildConfigurations(); map.insert(QLatin1String(ACTIVE_BC_KEY), bcs.indexOf(d->m_activeBuildConfiguration)); map.insert(QLatin1String(BC_COUNT_KEY), bcs.size()); for (int i = 0; i < bcs.size(); ++i) @@ -497,6 +500,153 @@ QVariantMap Target::toMap() const return map; } +void Target::createDefaultSetup() +{ + updateDefaultBuildConfigurations(); + updateDefaultDeployConfigurations(); + updateDefaultRunConfigurations(); +} + +void Target::updateDefaultBuildConfigurations() +{ + IBuildConfigurationFactory *bcFactory = IBuildConfigurationFactory::find(this); + if (!bcFactory) { + qWarning("No build configuration factory found for target id '%s'.", qPrintable(id().toString())); + return; + } + QList<Core::Id> bcIds = bcFactory->availableCreationIds(this); + foreach (Core::Id id, bcIds) { + if (!bcFactory->canCreate(this, id)) + continue; + BuildConfiguration *bc = bcFactory->create(this, id, tr("Default build")); + if (!bc) + continue; + QTC_CHECK(bc->id() == id); + addBuildConfiguration(bc); + } +} + +void Target::updateDefaultDeployConfigurations() +{ + DeployConfigurationFactory *dcFactory = DeployConfigurationFactory::find(this); + if (!dcFactory) { + qWarning("No deployment configuration factory found for target id '%s'.", qPrintable(id().toString())); + return; + } + QList<Core::Id> dcIds = dcFactory->availableCreationIds(this); + QList<DeployConfiguration *> dcList = deployConfigurations(); + + foreach (DeployConfiguration *dc, dcList) { + if (dcIds.contains(dc->id())) + dcIds.removeOne(dc->id()); + else + removeDeployConfiguration(dc); + } + + foreach (Core::Id id, dcIds) { + if (!dcFactory->canCreate(this, id)) + continue; + DeployConfiguration *dc = dcFactory->create(this, id); + if (dc) { + QTC_CHECK(dc->id() == id); + addDeployConfiguration(dc); + } + } +} + +void Target::updateDefaultRunConfigurations() +{ + QList<IRunConfigurationFactory *> rcFactories = IRunConfigurationFactory::find(this); + if (rcFactories.isEmpty()) { + qWarning("No run configuration factory found for target id '%s'.", qPrintable(id().toString())); + return; + } + + QList<RunConfiguration *> existingConfigured; // Existing configured RCs + QList<RunConfiguration *> existingUnconfigured; // Existing unconfigured RCs + QList<RunConfiguration *> newConfigured; // NEW configured Rcs + QList<RunConfiguration *> newUnconfigured; // NEW unconfigured RCs + + + // sort existing RCs into configured/unconfigured. + foreach (RunConfiguration *rc, runConfigurations()) { + if (rc->isConfigured()) + existingConfigured << rc; + else + existingUnconfigured << rc; + } + int configuredCount = existingConfigured.count(); + + // find all RC ids that can get created: + QList<Core::Id> factoryIds; + foreach (IRunConfigurationFactory *rcFactory, rcFactories) + factoryIds.append(rcFactory->availableCreationIds(this)); + + // Put outdated RCs into toRemove, do not bother with factories + // that produce already existing RCs + QList<RunConfiguration *> toRemove; + foreach (RunConfiguration *rc, existingConfigured) { + if (factoryIds.contains(rc->id())) + factoryIds.removeOne(rc->id()); // Already there + else + toRemove << rc; + } + configuredCount -= toRemove.count(); + + // Create new RCs and put them into newConfigured/newUnconfigured + foreach (Core::Id id, factoryIds) { + IRunConfigurationFactory *factory = 0; + foreach (IRunConfigurationFactory *i, rcFactories) { + if (i->canCreate(this, id)) { + factory = i; + break; + } + } + if (!factory) + continue; + + RunConfiguration *rc = factory->create(this, id); + if (!rc) + continue; + QTC_CHECK(rc->id() == id); + if (!rc->isConfigured()) + newUnconfigured << rc; + else + newConfigured << rc; + } + configuredCount += newConfigured.count(); + + // Decide what to do with the different categories: + bool removeExistingUnconfigured = false; + if (configuredCount > 0) { + // new non-Custom Executable RCs were added + removeExistingUnconfigured = true; + qDeleteAll(newUnconfigured); + newUnconfigured.clear(); + } else { + // no new RCs, use old or new CERCs? + if (!existingUnconfigured.isEmpty()) { + qDeleteAll(newUnconfigured); + newUnconfigured.clear(); + } + } + + // Do actual changes: + foreach (RunConfiguration *rc, toRemove) + removeRunConfiguration(rc); + + if (removeExistingUnconfigured) { + foreach (RunConfiguration *rc, existingUnconfigured) + removeRunConfiguration(rc); + existingUnconfigured.clear(); + } + + foreach (RunConfiguration *rc, newConfigured) + addRunConfiguration(rc); + foreach (RunConfiguration *rc, newUnconfigured) + addRunConfiguration(rc); +} + static QString formatToolTip(const IDevice::DeviceInfo &input) { QStringList lines; @@ -507,7 +657,7 @@ static QString formatToolTip(const IDevice::DeviceInfo &input) void Target::updateDeviceState() { - IDevice::ConstPtr current = currentDevice(); + IDevice::ConstPtr current = DeviceProfileInformation::device(profile()); QPixmap overlay; if (current.isNull()) { @@ -547,11 +697,6 @@ void Target::updateDeviceState() setToolTip(current.isNull() ? QString() : formatToolTip(current->deviceInformation())); } -ProjectExplorer::IDevice::ConstPtr Target::currentDevice() const -{ - return DeviceManager::instance()->find(ProjectExplorer::Constants::DESKTOP_DEVICE_ID); -} - void Target::setEnabled(bool enabled) { if (enabled == d->m_isEnabled) @@ -566,6 +711,10 @@ bool Target::fromMap(const QVariantMap &map) if (!ProjectConfiguration::fromMap(map)) return false; + d->m_profile = ProfileManager::instance()->find(id()); + if (!d->m_profile) + return false; + bool ok; int bcCount = map.value(QLatin1String(BC_COUNT_KEY), 0).toInt(&ok); if (!ok || bcCount < 0) @@ -580,14 +729,23 @@ bool Target::fromMap(const QVariantMap &map) const QString key = QString::fromLatin1(BC_KEY_PREFIX) + QString::number(i); if (!map.contains(key)) return false; - BuildConfiguration *bc = buildConfigurationFactory()->restore(this, map.value(key).toMap()); - if (!bc) + const QVariantMap valueMap = map.value(key).toMap(); + IBuildConfigurationFactory *factory = IBuildConfigurationFactory::find(this, valueMap); + if (!factory) { + qWarning("No factory found to restore build configuration!"); + continue; + } + BuildConfiguration *bc = factory->restore(this, valueMap); + if (!bc) { + qWarning("Failed '%s' to restore build configuration!", qPrintable(factory->objectName())); continue; + } + QTC_CHECK(bc->id() == ProjectExplorer::idFromMap(valueMap)); addBuildConfiguration(bc); if (i == activeConfiguration) setActiveBuildConfiguration(bc); } - if (buildConfigurations().isEmpty() && buildConfigurationFactory()) + if (buildConfigurations().isEmpty() && IBuildConfigurationFactory::find(this)) return false; int dcCount = map.value(QLatin1String(DC_COUNT_KEY), 0).toInt(&ok); @@ -603,16 +761,18 @@ bool Target::fromMap(const QVariantMap &map) const QString key = QString::fromLatin1(DC_KEY_PREFIX) + QString::number(i); if (!map.contains(key)) return false; - DeployConfiguration *dc = 0; - foreach (DeployConfigurationFactory * const factory, d->deployFactories()) { - QVariantMap valueMap = map.value(key).toMap(); - if (factory->canRestore(this, valueMap)) { - dc = factory->restore(this, valueMap); - break; - } + QVariantMap valueMap = map.value(key).toMap(); + DeployConfigurationFactory *factory = DeployConfigurationFactory::find(this, valueMap); + if (!factory) { + qWarning("No factory found to restore deployment configuration!"); + continue; } - if (!dc) + DeployConfiguration *dc = factory->restore(this, valueMap); + if (!dc) { + qWarning("Factory '%s' failed to restore deployment configuration!", qPrintable(factory->objectName())); continue; + } + QTC_CHECK(dc->id() == ProjectExplorer::idFromMap(valueMap)); addDeployConfiguration(dc); if (i == activeConfiguration) setActiveDeployConfiguration(dc); @@ -632,32 +792,40 @@ bool Target::fromMap(const QVariantMap &map) if (!map.contains(key)) return false; + // Ignore missing RCs: We will just populate them using the default ones. QVariantMap valueMap = map.value(key).toMap(); - IRunConfigurationFactory *factory = IRunConfigurationFactory::restoreFactory(this, valueMap); - if (!factory) - continue; // Skip RCs we do not know about.) - + IRunConfigurationFactory *factory = IRunConfigurationFactory::find(this, valueMap); + if (!factory || !factory->canRestore(this, valueMap)) + continue; RunConfiguration *rc = factory->restore(this, valueMap); if (!rc) continue; + QTC_CHECK(rc->id() == ProjectExplorer::idFromMap(valueMap)); addRunConfiguration(rc); if (i == activeConfiguration) setActiveRunConfiguration(rc); } - // Ignore missing RCs: We will just populate them using the default ones. return true; } -// ------------------------------------------------------------------------- -// ITargetFactory -// ------------------------------------------------------------------------- +void Target::onRequestBuildSystemEvaluation() +{ + ProjectConfiguration *config = qobject_cast<ProjectConfiguration *>(sender()); + if (!config) + return; + if (config == static_cast<ProjectConfiguration *>(activeBuildConfiguration()) + || config == static_cast<ProjectConfiguration *>(activeDeployConfiguration())) + emit requestBuildSystemEvaluation(); +} -ITargetFactory::ITargetFactory(QObject *parent) : - QObject(parent) +void Target::onBuildDirectoryInitialized() { - connect(ToolChainManager::instance(), SIGNAL(toolChainsChanged()), - this, SIGNAL(canCreateTargetIdsChanged())); + BuildConfiguration *bc = qobject_cast<BuildConfiguration *>(sender()); + if (!bc) + return; + if (bc == activeBuildConfiguration()) + emit buildDirectoryInitialized(); } } // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/target.h b/src/plugins/projectexplorer/target.h index 1b05c9c07b..69e4fb4459 100644 --- a/src/plugins/projectexplorer/target.h +++ b/src/plugins/projectexplorer/target.h @@ -43,12 +43,12 @@ namespace Utils { class Environment; } namespace ProjectExplorer { class RunConfiguration; -class ToolChain; class BuildConfiguration; class DeployConfiguration; class IBuildConfigurationFactory; class DeployConfigurationFactory; class IRunConfigurationFactory; +class Profile; class Project; class BuildConfigWidget; @@ -59,11 +59,14 @@ class PROJECTEXPLORER_EXPORT Target : public ProjectConfiguration Q_OBJECT public: - virtual ~Target(); + Target(Project *parent, Profile *p); + ~Target(); - virtual BuildConfigWidget *createConfigWidget() = 0; Project *project() const; + // Profile: + Profile *profile() const; + // Build configuration void addBuildConfiguration(BuildConfiguration *configuration); bool removeBuildConfiguration(BuildConfiguration *configuration); @@ -72,8 +75,6 @@ public: BuildConfiguration *activeBuildConfiguration() const; void setActiveBuildConfiguration(BuildConfiguration *configuration); - virtual IBuildConfigurationFactory *buildConfigurationFactory() const = 0; - // DeployConfiguration void addDeployConfiguration(DeployConfiguration *dc); bool removeDeployConfiguration(DeployConfiguration *dc); @@ -82,10 +83,6 @@ public: DeployConfiguration *activeDeployConfiguration() const; void setActiveDeployConfiguration(DeployConfiguration *configuration); - QList<Core::Id> availableDeployConfigurationIds(); - QString displayNameForDeployConfigurationId(Core::Id &id); - DeployConfiguration *createDeployConfiguration(Core::Id id); - // Running QList<RunConfiguration *> runConfigurations() const; void addRunConfiguration(RunConfiguration *runConfiguration); @@ -108,10 +105,12 @@ public: QString toolTip() const; void setToolTip(const QString &text); - virtual QList<ToolChain *> possibleToolChains(BuildConfiguration *) const; - virtual ToolChain *preferredToolChain(BuildConfiguration *) const; + QVariantMap toMap() const; - virtual QVariantMap toMap() const; + void createDefaultSetup(); + void updateDefaultBuildConfigurations(); + void updateDefaultDeployConfigurations(); + void updateDefaultRunConfigurations(); signals: void targetEnabled(bool); @@ -119,6 +118,8 @@ signals: void overlayIconChanged(); void toolTipChanged(); + void profileChanged(); + // TODO clean up signal names // might be better to also have aboutToRemove signals void removedRunConfiguration(ProjectExplorer::RunConfiguration *); @@ -143,14 +144,23 @@ signals: void deployConfigurationEnabledChanged(); void runConfigurationEnabledChanged(); -protected: - Target(Project *parent, const Core::Id id); + /// Emitted whenever the project should (re-)evaluate the build system + void requestBuildSystemEvaluation(); + /// Emitted whenever the current build configuration has finished to initialize its build directory. + void buildDirectoryInitialized(); + /// Emitted whenever the current build configuartion changed or the build directory of the current + /// build configuration was changed. + void buildDirectoryChanged(); - virtual ProjectExplorer::IDevice::ConstPtr currentDevice() const; +public slots: + void onRequestBuildSystemEvaluation(); + void onBuildDirectoryInitialized(); + void onBuildDirectoryChanged(); +protected: void setEnabled(bool); - virtual bool fromMap(const QVariantMap &map); + bool fromMap(const QVariantMap &map); protected slots: void updateDeviceState(); @@ -161,31 +171,13 @@ private slots: void changeDeployConfigurationEnabled(); void changeRunConfigurationEnabled(); + void handleProfileUpdates(ProjectExplorer::Profile *p); + void handleProfileRemoval(ProjectExplorer::Profile *p); + private: TargetPrivate *d; -}; -class PROJECTEXPLORER_EXPORT ITargetFactory : - public QObject -{ - Q_OBJECT - -public: - explicit ITargetFactory(QObject *parent = 0); - - virtual QList<Core::Id> supportedTargetIds() const = 0; - virtual bool supportsTargetId(const Core::Id id) const = 0; - - // used to translate the types to names to display to the user - virtual QString displayNameForId(const Core::Id id) const = 0; - - virtual bool canCreate(Project *parent, const Core::Id id) const = 0; - virtual Target *create(Project *parent, const Core::Id id) = 0; - virtual bool canRestore(Project *parent, const QVariantMap &map) const = 0; - virtual Target *restore(Project *parent, const QVariantMap &map) = 0; - -signals: - void canCreateTargetIdsChanged(); + friend class Project; }; } // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/targetselector.cpp b/src/plugins/projectexplorer/targetselector.cpp index 707160377d..20a3023187 100644 --- a/src/plugins/projectexplorer/targetselector.cpp +++ b/src/plugins/projectexplorer/targetselector.cpp @@ -80,6 +80,12 @@ void TargetSelector::insertTarget(int index, const QString &name) update(); } +void TargetSelector::renameTarget(int index, const QString &name) +{ + m_targets[index].name = name; + update(); +} + void TargetSelector::removeTarget(int index) { QTC_ASSERT(index >= 0 && index < m_targets.count(), return); diff --git a/src/plugins/projectexplorer/targetselector.h b/src/plugins/projectexplorer/targetselector.h index 6aaadf849b..752bb1c14e 100644 --- a/src/plugins/projectexplorer/targetselector.h +++ b/src/plugins/projectexplorer/targetselector.h @@ -70,6 +70,7 @@ public: public: void insertTarget(int index, const QString &name); + void renameTarget(int index, const QString &name); void removeTarget(int index); void setCurrentIndex(int index); void setCurrentSubIndex(int subindex); diff --git a/src/plugins/projectexplorer/targetsettingspanel.cpp b/src/plugins/projectexplorer/targetsettingspanel.cpp index a94c34fde4..3646d10fa1 100644 --- a/src/plugins/projectexplorer/targetsettingspanel.cpp +++ b/src/plugins/projectexplorer/targetsettingspanel.cpp @@ -41,7 +41,10 @@ #include <extensionsystem/pluginmanager.h> #include <projectexplorer/projectexplorer.h> +#include <projectexplorer/profile.h> +#include <projectexplorer/profilemanager.h> #include <projectexplorer/buildmanager.h> +#include <utils/qtcassert.h> #include <QCoreApplication> #include <QLabel> @@ -84,13 +87,8 @@ TargetSettingsPanelWidget::TargetSettingsPanelWidget(Project *project) : connect(m_project, SIGNAL(activeTargetChanged(ProjectExplorer::Target*)), this, SLOT(activeTargetChanged(ProjectExplorer::Target*))); - QList<ITargetFactory *> factories = - ExtensionSystem::PluginManager::getObjects<ITargetFactory>(); - - foreach (ITargetFactory *fac, factories) { - connect(fac, SIGNAL(canCreateTargetIdsChanged()), - this, SLOT(updateTargetAddAndRemoveButtons())); - } + connect(ProfileManager::instance(), SIGNAL(profilesChanged()), + this, SLOT(updateTargetAddAndRemoveButtons())); } TargetSettingsPanelWidget::~TargetSettingsPanelWidget() @@ -213,19 +211,10 @@ void TargetSettingsPanelWidget::currentTargetChanged(int targetIndex, int subInd void TargetSettingsPanelWidget::addTarget(QAction *action) { - Core::Id id = action->data().value<Core::Id>(); - Q_ASSERT(!m_project->target(id)); - QList<ITargetFactory *> factories = - ExtensionSystem::PluginManager::getObjects<ITargetFactory>(); - - Target *target = 0; - foreach (ITargetFactory *fac, factories) { - if (fac->canCreate(m_project, id)) { - target = fac->create(m_project, id); - break; - } - } + Profile *p = ProfileManager::instance()->find(action->data().value<Core::Id>()); + QTC_ASSERT(!m_project->target(p), return); + Target *target = m_project->createTarget(p); if (!target) return; m_project->addTarget(target); @@ -278,6 +267,7 @@ void TargetSettingsPanelWidget::targetAdded(ProjectExplorer::Target *target) } } + connect(target, SIGNAL(displayNameChanged()), this, SLOT(renameTarget())); updateTargetAddAndRemoveButtons(); } @@ -312,35 +302,42 @@ void TargetSettingsPanelWidget::updateTargetAddAndRemoveButtons() m_addMenu->clear(); - QList<ITargetFactory *> factories = - ExtensionSystem::PluginManager::getObjects<ITargetFactory>(); - - foreach (ITargetFactory *fac, factories) { - foreach (Core::Id id, fac->supportedTargetIds()) { - if (m_project->target(id)) - continue; - if (!fac->canCreate(m_project, id)) - continue; - QString displayName = fac->displayNameForId(id); - QAction *action = new QAction(displayName, m_addMenu); - action->setData(QVariant::fromValue(id)); - bool added = false; - foreach (QAction *existing, m_addMenu->actions()) { - if (existing->text() > action->text()) { - m_addMenu->insertAction(existing, action); - added = true; - } - } + foreach (Profile *p, ProfileManager::instance()->profiles()) { + if (m_project->target(p)) + continue; + if (!m_project->supportsProfile(p)) + continue; - if (!added) - m_addMenu->addAction(action); + QAction *action = new QAction(p->displayName(), m_addMenu); + action->setData(QVariant::fromValue(p->id())); + + bool inserted = false; + foreach (QAction *existing, m_addMenu->actions()) { + if (existing->text() > action->text()) { + m_addMenu->insertAction(existing, action); + inserted = true; + break; + } } + if (!inserted) + m_addMenu->addAction(action); } m_selector->setAddButtonEnabled(!m_addMenu->actions().isEmpty()); m_selector->setRemoveButtonEnabled(m_project->targets().count() > 1); } +void TargetSettingsPanelWidget::renameTarget() +{ + Target *t = qobject_cast<Target *>(sender()); + if (!t) + return; + const int pos = m_targets.indexOf(t); + if (pos < 0) + return; + m_selector->renameTarget(pos, t->displayName()); +} + int TargetSettingsPanelWidget::currentSubIndex() const { return m_selector->currentSubIndex(); diff --git a/src/plugins/projectexplorer/targetsettingspanel.h b/src/plugins/projectexplorer/targetsettingspanel.h index d95c358d1b..5f84c6fe22 100644 --- a/src/plugins/projectexplorer/targetsettingspanel.h +++ b/src/plugins/projectexplorer/targetsettingspanel.h @@ -71,6 +71,7 @@ private slots: void removedTarget(ProjectExplorer::Target *target); void activeTargetChanged(ProjectExplorer::Target *target); void updateTargetAddAndRemoveButtons(); + void renameTarget(); private: Target *m_currentTarget; diff --git a/src/plugins/projectexplorer/targetsettingswidget.cpp b/src/plugins/projectexplorer/targetsettingswidget.cpp index 18d9e06561..f8f8b3c835 100644 --- a/src/plugins/projectexplorer/targetsettingswidget.cpp +++ b/src/plugins/projectexplorer/targetsettingswidget.cpp @@ -78,6 +78,12 @@ void TargetSettingsWidget::insertTarget(int index, const QString &name) updateTargetSelector(); } +void TargetSettingsWidget::renameTarget(int index, const QString &name) +{ + m_targetSelector->renameTarget(index, name); + // geometry won't change, so no need to updateTargetSelector() +} + void TargetSettingsWidget::removeTarget(int index) { m_targetSelector->removeTarget(index); diff --git a/src/plugins/projectexplorer/targetsettingswidget.h b/src/plugins/projectexplorer/targetsettingswidget.h index dedede723f..ebc3c48dd7 100644 --- a/src/plugins/projectexplorer/targetsettingswidget.h +++ b/src/plugins/projectexplorer/targetsettingswidget.h @@ -65,6 +65,7 @@ public: public: void insertTarget(int index, const QString &name); + void renameTarget(int index, const QString &name); void removeTarget(int index); void setCurrentIndex(int index); void setCurrentSubIndex(int index); diff --git a/src/plugins/projectexplorer/toolchain.cpp b/src/plugins/projectexplorer/toolchain.cpp index 75eeb0baea..1c92f3c77b 100644 --- a/src/plugins/projectexplorer/toolchain.cpp +++ b/src/plugins/projectexplorer/toolchain.cpp @@ -32,6 +32,7 @@ #include "toolchain.h" +#include "abi.h" #include "toolchainmanager.h" #include <extensionsystem/pluginmanager.h> @@ -43,30 +44,6 @@ static const char ID_KEY[] = "ProjectExplorer.ToolChain.Id"; static const char DISPLAY_NAME_KEY[] = "ProjectExplorer.ToolChain.DisplayName"; static const char AUTODETECT_KEY[] = "ProjectExplorer.ToolChain.Autodetect"; -static const char MKSPEC_KEY[] = "ProjectExplorer.ToolChain.MkSpecOverride"; - -namespace { - -QString mkspecListToString(const QList<Utils::FileName> &specList) -{ - QStringList result; - foreach (const Utils::FileName &spec, specList) - result.append(spec.toString()); - return result.join(QChar::fromLatin1(';')); -} - -QList<Utils::FileName> mkspecListFromString(const QString &string) -{ - QList<Utils::FileName> result; - QStringList partList; - if (!string.isEmpty()) - partList = string.split(QLatin1Char(';')); - foreach (const QString &part, partList) - result.append(Utils::FileName::fromString(part)); - return result; -} - -} // namespace namespace ProjectExplorer { namespace Internal { @@ -94,7 +71,6 @@ public: QString m_id; bool m_autodetect; mutable QString m_displayName; - QList<Utils::FileName> m_mkspecList; }; } // namespace Internal @@ -150,31 +126,9 @@ QString ToolChain::id() const return d->m_id; } -/*! - \brief Returns a list of target ids that this tool chain is restricted to. - - An empty list is shows that the toolchain is compatible with all targets. -*/ - -QList<Core::Id> ToolChain::restrictedToTargets() const -{ - return QList<Core::Id>(); -} - -QList<Utils::FileName> ToolChain::mkspecList() const +Utils::FileName ToolChain::suggestedDebugger() { - if (d->m_mkspecList.isEmpty()) - return suggestedMkspecList(); - return d->m_mkspecList; -} - -void ToolChain::setMkspecList(const QList<Utils::FileName> &specList) -{ - QList<Utils::FileName> oldSpecList = mkspecList(); - d->m_mkspecList = specList; - - if (oldSpecList != mkspecList()) - toolChainUpdated(); + return ToolChainManager::instance()->defaultDebugger(targetAbi()); } bool ToolChain::canClone() const @@ -211,7 +165,6 @@ QVariantMap ToolChain::toMap() const result.insert(QLatin1String(ID_KEY), id()); result.insert(QLatin1String(DISPLAY_NAME_KEY), displayName()); result.insert(QLatin1String(AUTODETECT_KEY), isAutoDetected()); - result.insert(QLatin1String(MKSPEC_KEY), mkspecListToString(d->m_mkspecList)); return result; } @@ -241,7 +194,6 @@ bool ToolChain::fromMap(const QVariantMap &data) // make sure we have new style ids: d->m_id = data.value(QLatin1String(ID_KEY)).toString(); d->m_autodetect = data.value(QLatin1String(AUTODETECT_KEY), false).toBool(); - d->m_mkspecList = mkspecListFromString(data.value(QLatin1String(MKSPEC_KEY)).toString()); return true; } diff --git a/src/plugins/projectexplorer/toolchain.h b/src/plugins/projectexplorer/toolchain.h index 31211acc7d..1ce975d2c6 100644 --- a/src/plugins/projectexplorer/toolchain.h +++ b/src/plugins/projectexplorer/toolchain.h @@ -73,8 +73,9 @@ public: bool isAutoDetected() const; QString id() const; - // No need to implement this for new tool chains: - virtual QString legacyId() const { return QString(); } + + virtual QList<Utils::FileName> suggestedMkspecList() const { return QList<Utils::FileName>(); } + Utils::FileName suggestedDebugger(); virtual QString type() const = 0; virtual QString typeDisplayName() const = 0; @@ -82,8 +83,6 @@ public: virtual bool isValid() const = 0; - virtual QList<Core::Id> restrictedToTargets() const; - virtual QByteArray predefinedMacros(const QStringList &cxxflags) const = 0; enum CompilerFlags { @@ -95,12 +94,7 @@ public: virtual void addToEnvironment(Utils::Environment &env) const = 0; virtual QString makeCommand() const = 0; - QList<Utils::FileName> mkspecList() const; - void setMkspecList(const QList<Utils::FileName> &specList); - virtual QList<Utils::FileName> suggestedMkspecList() const { return QList<Utils::FileName>(); } - virtual Utils::FileName compilerCommand() const = 0; - virtual Utils::FileName debuggerCommand() const = 0; virtual QString defaultMakeTarget() const; virtual IOutputParser *outputParser() const = 0; diff --git a/src/plugins/projectexplorer/toolchainconfigwidget.cpp b/src/plugins/projectexplorer/toolchainconfigwidget.cpp index 3ad7e4da4c..93ad2f5d49 100644 --- a/src/plugins/projectexplorer/toolchainconfigwidget.cpp +++ b/src/plugins/projectexplorer/toolchainconfigwidget.cpp @@ -44,46 +44,6 @@ #include <QLabel> #include <QPushButton> -namespace { - -const char DEFAULT_MKSPEC[] = "default"; - -QString mkspecListToString(const QList<Utils::FileName> &specList) -{ - QStringList specStrings; - foreach (const Utils::FileName &spec, specList) { - if (spec.isEmpty()) - specStrings.append(QLatin1String(DEFAULT_MKSPEC)); - else - specStrings.append(spec.toUserOutput()); - } - QString specString = specStrings.join(QChar::fromAscii(';')); - if (specString.isEmpty()) - return QLatin1String(DEFAULT_MKSPEC); - return specString; -} - -QList<Utils::FileName> mkspecListFromString(const QString &specString) -{ - QStringList specList = specString.split(QLatin1Char(';')); - QList<Utils::FileName> result; - foreach (const QString &spec, specList) { - QString trimmed = spec.trimmed(); - if (trimmed == QLatin1String(DEFAULT_MKSPEC)) - result.append(Utils::FileName()); - else - result.append(Utils::FileName::fromUserInput(trimmed)); - } - - if (result.size() == 1 && result.at(0).isEmpty()) - return QList<Utils::FileName>(); - - return result; -} - - -} // namespace - namespace ProjectExplorer { namespace Internal { @@ -95,21 +55,13 @@ class ToolChainConfigWidgetPrivate { public: ToolChainConfigWidgetPrivate(ToolChain *tc) : - m_toolChain(tc), m_debuggerPathChooser(0), - m_mkspecLayout(0), m_mkspecEdit(0), m_mkspecResetButton(0), m_mkspecEdited(false), - m_errorLabel(0) + m_toolChain(tc), m_errorLabel(0) { QTC_CHECK(tc); } ToolChain *m_toolChain; - Utils::PathChooser *m_debuggerPathChooser; - QHBoxLayout *m_mkspecLayout; - QLineEdit *m_mkspecEdit; - QPushButton *m_mkspecResetButton; - bool m_mkspecEdited; QLabel *m_errorLabel; - QList<Utils::FileName> m_suggestedMkspec; }; } // namespace Internal @@ -134,132 +86,7 @@ ToolChain *ToolChainConfigWidget::toolChain() const } void ToolChainConfigWidget::makeReadOnly() -{ - if (d->m_debuggerPathChooser) - d->m_debuggerPathChooser->setEnabled(false); - if (d->m_mkspecEdit) - d->m_mkspecEdit->setEnabled(false); - if (d->m_mkspecResetButton) - d->m_mkspecResetButton->setEnabled(false); -} - -void ToolChainConfigWidget::emitDirty() -{ - if (d->m_mkspecEdit) - d->m_mkspecEdited = (mkspecListFromString(d->m_mkspecEdit->text()) != d->m_suggestedMkspec); - if (d->m_mkspecResetButton) - d->m_mkspecResetButton->setEnabled(d->m_mkspecEdited); - emit dirty(); -} - -void ToolChainConfigWidget::resetMkspecList() -{ - if (!d->m_mkspecEdit || !d->m_mkspecEdited) - return; - d->m_mkspecEdit->setText(mkspecListToString(d->m_suggestedMkspec)); - d->m_mkspecEdited = false; -} - -void ToolChainConfigWidget::addDebuggerCommandControls(QFormLayout *lt, - const QStringList &versionArguments) -{ - ensureDebuggerPathChooser(versionArguments); - lt->addRow(tr("&Debugger:"), d->m_debuggerPathChooser); -} - -void ToolChainConfigWidget::addDebuggerCommandControls(QGridLayout *lt, - int row, int column, - const QStringList &versionArguments) -{ - ensureDebuggerPathChooser(versionArguments); - QLabel *label = new QLabel(tr("&Debugger:")); - label->setBuddy(d->m_debuggerPathChooser); - lt->addWidget(label, row, column); - lt->addWidget(d->m_debuggerPathChooser, row, column + 1); -} - -void ToolChainConfigWidget::ensureDebuggerPathChooser(const QStringList &versionArguments) -{ - if (d->m_debuggerPathChooser) - return; - d->m_debuggerPathChooser = new Utils::PathChooser; - d->m_debuggerPathChooser->setExpectedKind(Utils::PathChooser::ExistingCommand); - d->m_debuggerPathChooser->setCommandVersionArguments(versionArguments); - connect(d->m_debuggerPathChooser, SIGNAL(changed(QString)), this, SLOT(emitDirty())); -} - -void ToolChainConfigWidget::addDebuggerAutoDetection(QObject *receiver, const char *autoDetectSlot) -{ - QTC_ASSERT(d->m_debuggerPathChooser, return); - d->m_debuggerPathChooser->addButton(tr("Autodetect"), receiver, autoDetectSlot); -} - -Utils::FileName ToolChainConfigWidget::debuggerCommand() const -{ - QTC_ASSERT(d->m_debuggerPathChooser, return Utils::FileName()); - return d->m_debuggerPathChooser->fileName(); -} - -void ToolChainConfigWidget::setDebuggerCommand(const Utils::FileName &debugger) -{ - QTC_ASSERT(d->m_debuggerPathChooser, return); - d->m_debuggerPathChooser->setFileName(debugger); -} - -void ToolChainConfigWidget::addMkspecControls(QFormLayout *lt) -{ - ensureMkspecEdit(); - lt->addRow(tr("mkspec:"), d->m_mkspecLayout); -} - -void ToolChainConfigWidget::addMkspecControls(QGridLayout *lt, int row, int column) -{ - ensureMkspecEdit(); - QLabel *label = new QLabel(tr("mkspec:")); - label->setBuddy(d->m_mkspecEdit); - lt->addWidget(label, row, column); - lt->addLayout(d->m_mkspecLayout, row, column + 1); -} - -void ToolChainConfigWidget::ensureMkspecEdit() -{ - if (d->m_mkspecEdit) - return; - - QTC_CHECK(!d->m_mkspecLayout); - QTC_CHECK(!d->m_mkspecResetButton); - - d->m_suggestedMkspec = d->m_toolChain->suggestedMkspecList(); - - d->m_mkspecLayout = new QHBoxLayout; - d->m_mkspecLayout->setMargin(0); - - d->m_mkspecEdit = new QLineEdit; - d->m_mkspecEdit->setWhatsThis(tr("All possible mkspecs separated by a semicolon (';').")); - d->m_mkspecResetButton = new QPushButton(tr("Reset")); - d->m_mkspecResetButton->setEnabled(d->m_mkspecEdited); - d->m_mkspecLayout->addWidget(d->m_mkspecEdit); - d->m_mkspecLayout->addWidget(d->m_mkspecResetButton); - - connect(d->m_mkspecEdit, SIGNAL(textChanged(QString)), this, SLOT(emitDirty())); - connect(d->m_mkspecResetButton, SIGNAL(clicked()), this, SLOT(resetMkspecList())); -} - -QList<Utils::FileName> ToolChainConfigWidget::mkspecList() const -{ - QTC_ASSERT(d->m_mkspecEdit, return QList<Utils::FileName>()); - - return mkspecListFromString(d->m_mkspecEdit->text()); -} - -void ToolChainConfigWidget::setMkspecList(const QList<Utils::FileName> &specList) -{ - QTC_ASSERT(d->m_mkspecEdit, return); - - d->m_mkspecEdit->setText(mkspecListToString(specList)); - - emitDirty(); -} +{ } void ToolChainConfigWidget::addErrorLabel(QFormLayout *lt) { diff --git a/src/plugins/projectexplorer/toolchainconfigwidget.h b/src/plugins/projectexplorer/toolchainconfigwidget.h index 1bc25b6661..2314df576c 100644 --- a/src/plugins/projectexplorer/toolchainconfigwidget.h +++ b/src/plugins/projectexplorer/toolchainconfigwidget.h @@ -74,33 +74,14 @@ signals: void dirty(); protected slots: - void emitDirty(); - void resetMkspecList(); void setErrorMessage(const QString &); void clearErrorMessage(); protected: - void addDebuggerCommandControls(QFormLayout *lt, - const QStringList &versionArguments = QStringList()); - void addDebuggerCommandControls(QGridLayout *lt, - int row = 0, int column = 0, - const QStringList &versionArguments = QStringList()); - void addDebuggerAutoDetection(QObject *receiver, const char *autoDetectSlot); - void addMkspecControls(QFormLayout *lt); - void addMkspecControls(QGridLayout *lt, int row = 0, int column = 0); void addErrorLabel(QFormLayout *lt); void addErrorLabel(QGridLayout *lt, int row = 0, int column = 0, int colSpan = 1); - Utils::FileName debuggerCommand() const; - void setDebuggerCommand(const Utils::FileName &debugger); - - QList<Utils::FileName> mkspecList() const; - void setMkspecList(const QList<Utils::FileName> &specList); - private: - void ensureDebuggerPathChooser(const QStringList &versionArguments); - void ensureMkspecEdit(); - Internal::ToolChainConfigWidgetPrivate *d; }; diff --git a/src/plugins/projectexplorer/toolchainmanager.cpp b/src/plugins/projectexplorer/toolchainmanager.cpp index b87a38f8da..5b76d3f9ca 100644 --- a/src/plugins/projectexplorer/toolchainmanager.cpp +++ b/src/plugins/projectexplorer/toolchainmanager.cpp @@ -31,7 +31,9 @@ **************************************************************************/ #include "toolchainmanager.h" + #include "abi.h" +#include "profileinformation.h" #include "toolchain.h" #include <coreplugin/icore.h> @@ -51,15 +53,17 @@ static const char TOOLCHAIN_FILE_VERSION_KEY[] = "Version"; static const char DEFAULT_DEBUGGER_COUNT_KEY[] = "DefaultDebugger.Count"; static const char DEFAULT_DEBUGGER_ABI_KEY[] = "DefaultDebugger.Abi."; static const char DEFAULT_DEBUGGER_PATH_KEY[] = "DefaultDebugger.Path."; -static const char TOOLCHAIN_FILENAME[] = "/toolChains.xml"; +static const char TOOLCHAIN_FILENAME[] = "/qtcreator/toolchains.xml"; +static const char LEGACY_TOOLCHAIN_FILENAME[] = "/toolChains.xml"; using Utils::PersistentSettingsWriter; using Utils::PersistentSettingsReader; -static QString settingsFileName() +static QString settingsFileName(const QString &path) { - QFileInfo settingsLocation(ExtensionSystem::PluginManager::settings()->fileName()); - return settingsLocation.absolutePath() + QLatin1String(TOOLCHAIN_FILENAME); + ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); + QFileInfo settingsLocation(pm->settings()->fileName()); + return settingsLocation.absolutePath() + path; } namespace ProjectExplorer { @@ -89,8 +93,7 @@ private: ToolChainManagerPrivate::ToolChainManagerPrivate(ToolChainManager *parent) : q(parent), m_initialized(false) -{ -} +{ } QList<ToolChain *> &ToolChainManagerPrivate::toolChains() { @@ -109,7 +112,6 @@ QList<ToolChain *> &ToolChainManagerPrivate::toolChains() ToolChainManager *ToolChainManager::instance() { - Q_ASSERT(m_instance); return m_instance; } @@ -119,6 +121,7 @@ ToolChainManager::ToolChainManager(QObject *parent) : { Q_ASSERT(!m_instance); m_instance = this; + connect(Core::ICore::instance(), SIGNAL(saveSettingsRequested()), this, SLOT(saveToolChains())); connect(this, SIGNAL(toolChainAdded(ProjectExplorer::ToolChain*)), @@ -137,7 +140,7 @@ void ToolChainManager::restoreToolChains() // read all tool chains from SDK QFileInfo systemSettingsFile(Core::ICore::settings(QSettings::SystemScope)->fileName()); QList<ToolChain *> readTcs = - restoreToolChains(systemSettingsFile.absolutePath() + QLatin1String(TOOLCHAIN_FILENAME)); + restoreToolChains(systemSettingsFile.absolutePath() + QLatin1String(LEGACY_TOOLCHAIN_FILENAME)); // make sure we mark these as autodetected! foreach (ToolChain *tc, readTcs) tc->setAutoDetected(true); @@ -145,8 +148,12 @@ void ToolChainManager::restoreToolChains() tcsToRegister = readTcs; // SDK TCs are always considered to be up-to-date, so no need to // recheck them. - // read all tool chains from user file - readTcs = restoreToolChains(settingsFileName()); + // read all tool chains from user file. + // Read legacy settings once and keep them around... + QString fileName = settingsFileName(QLatin1String(TOOLCHAIN_FILENAME)); + if (!QFileInfo(fileName).exists()) + fileName = settingsFileName(QLatin1String(LEGACY_TOOLCHAIN_FILENAME)); + readTcs = restoreToolChains(fileName); foreach (ToolChain *tc, readTcs) { if (tc->isAutoDetected()) @@ -214,7 +221,7 @@ void ToolChainManager::saveToolChains() } } writer.saveValue(QLatin1String(TOOLCHAIN_COUNT_KEY), count); - writer.save(settingsFileName(), QLatin1String("QtCreatorToolChains"), Core::ICore::mainWindow()); + writer.save(settingsFileName(QLatin1String(TOOLCHAIN_FILENAME)), QLatin1String("QtCreatorToolChains"), Core::ICore::mainWindow()); // Do not save default debuggers! Those are set by the SDK! } @@ -296,7 +303,7 @@ ToolChain *ToolChainManager::findToolChain(const QString &id) const return 0; foreach (ToolChain *tc, d->toolChains()) { - if (tc->id() == id || (!tc->legacyId().isEmpty() && tc->legacyId() == id)) + if (tc->id() == id) return tc; } return 0; diff --git a/src/plugins/projectexplorer/toolchainoptionspage.cpp b/src/plugins/projectexplorer/toolchainoptionspage.cpp index 1cdbe5bafa..5cd461ef70 100644 --- a/src/plugins/projectexplorer/toolchainoptionspage.cpp +++ b/src/plugins/projectexplorer/toolchainoptionspage.cpp @@ -42,13 +42,20 @@ #include <utils/qtcassert.h> -#include <QSignalMapper> -#include <QTextStream> #include <QAction> +#include <QApplication> +#include <QHBoxLayout> +#include <QHeaderView> #include <QItemSelectionModel> #include <QLabel> #include <QMenu> #include <QMessageBox> +#include <QPushButton> +#include <QSignalMapper> +#include <QSpacerItem> +#include <QTextStream> +#include <QTreeView> +#include <QVBoxLayout> namespace ProjectExplorer { namespace Internal { @@ -92,11 +99,11 @@ public: // ToolChainModel // -------------------------------------------------------------------------- -ToolChainModel::ToolChainModel(QWidget *configWidgetParent, QObject *parent) : +ToolChainModel::ToolChainModel(QBoxLayout *parentLayout, QObject *parent) : QAbstractItemModel(parent), - m_configWidgetParent(configWidgetParent) + m_parentLayout(parentLayout) { - Q_ASSERT(m_configWidgetParent); + Q_ASSERT(m_parentLayout); connect(ToolChainManager::instance(), SIGNAL(toolChainAdded(ProjectExplorer::ToolChain*)), this, SLOT(addToolChain(ProjectExplorer::ToolChain*))); @@ -404,9 +411,8 @@ ToolChainNode *ToolChainModel::createNode(ToolChainNode *parent, ToolChain *tc, { ToolChainNode *node = new ToolChainNode(parent, tc, changed); if (node->widget) { - m_configWidgetParent->layout()->addWidget(node->widget); - connect(node->widget, SIGNAL(dirty()), - this, SLOT(setDirty())); + m_parentLayout->addWidget(node->widget); + connect(node->widget, SIGNAL(dirty()), this, SLOT(setDirty())); } return node; } @@ -471,7 +477,8 @@ void ToolChainModel::removeToolChain(ToolChain *tc) // -------------------------------------------------------------------------- ToolChainOptionsPage::ToolChainOptionsPage() : - m_ui(0), m_model(0), m_selectionModel(0), m_currentTcWidget(0) + m_model(0), m_selectionModel(0), m_currentTcWidget(0), + m_toolChainView(0), m_addButton(0), m_cloneButton(0), m_delButton(0) { setId(QLatin1String(Constants::TOOLCHAIN_SETTINGS_PAGE_ID)); setDisplayName(tr("Tool Chains")); @@ -488,19 +495,39 @@ QWidget *ToolChainOptionsPage::createPage(QWidget *parent) m_currentTcWidget = 0; - m_ui = new Ui::ToolChainOptionsPage; - m_ui->setupUi(m_configWidget); + m_toolChainView = new QTreeView(m_configWidget); + m_toolChainView->setUniformRowHeights(true); + m_toolChainView->header()->setStretchLastSection(false); + m_addButton = new QPushButton(tr("Add"), m_configWidget); + m_cloneButton = new QPushButton(tr("Clone"), m_configWidget); + m_delButton = new QPushButton(tr("Remove"), m_configWidget); + + QVBoxLayout *buttonLayout = new QVBoxLayout(); + buttonLayout->setSpacing(6); + buttonLayout->setContentsMargins(0, 0, 0, 0); + buttonLayout->addWidget(m_addButton); + buttonLayout->addWidget(m_cloneButton); + buttonLayout->addWidget(m_delButton); + buttonLayout->addItem(new QSpacerItem(10, 40, QSizePolicy::Minimum, QSizePolicy::Expanding)); + + QVBoxLayout *verticalLayout = new QVBoxLayout(); + verticalLayout->addWidget(m_toolChainView); + + QHBoxLayout *horizontalLayout = new QHBoxLayout(m_configWidget); + horizontalLayout->addLayout(verticalLayout); + horizontalLayout->addLayout(buttonLayout); Q_ASSERT(!m_model); - m_model = new ToolChainModel(m_configWidget); + m_model = new ToolChainModel(verticalLayout); + connect(m_model, SIGNAL(toolChainStateChanged()), this, SLOT(updateState())); - m_ui->toolChainView->setModel(m_model); - m_ui->toolChainView->header()->setResizeMode(0, QHeaderView::ResizeToContents); - m_ui->toolChainView->header()->setResizeMode(1, QHeaderView::Stretch); - m_ui->toolChainView->expandAll(); + m_toolChainView->setModel(m_model); + m_toolChainView->header()->setResizeMode(0, QHeaderView::ResizeToContents); + m_toolChainView->header()->setResizeMode(1, QHeaderView::Stretch); + m_toolChainView->expandAll(); - m_selectionModel = m_ui->toolChainView->selectionModel(); + m_selectionModel = m_toolChainView->selectionModel(); connect(m_selectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(toolChainSelectionChanged())); connect(ToolChainManager::instance(), SIGNAL(toolChainsChanged()), @@ -510,7 +537,7 @@ QWidget *ToolChainOptionsPage::createPage(QWidget *parent) m_factories = ExtensionSystem::PluginManager::getObjects<ToolChainFactory>(); // Set up add menu: - QMenu *addMenu = new QMenu(m_ui->addButton); + QMenu *addMenu = new QMenu(m_addButton); QSignalMapper *mapper = new QSignalMapper(addMenu); connect(mapper, SIGNAL(mapped(QObject*)), this, SLOT(createToolChain(QObject*))); @@ -524,12 +551,12 @@ QWidget *ToolChainOptionsPage::createPage(QWidget *parent) addMenu->addAction(action); } } - connect(m_ui->cloneButton, SIGNAL(clicked()), mapper, SLOT(map())); - mapper->setMapping(m_ui->cloneButton, static_cast<QObject *>(0)); + connect(m_cloneButton, SIGNAL(clicked()), mapper, SLOT(map())); + mapper->setMapping(m_cloneButton, static_cast<QObject *>(0)); - m_ui->addButton->setMenu(addMenu); + m_addButton->setMenu(addMenu); - connect(m_ui->delButton, SIGNAL(clicked()), this, SLOT(removeToolChain())); + connect(m_delButton, SIGNAL(clicked()), this, SLOT(removeToolChain())); // setup keywords: if (m_searchKeywords.isEmpty()) { @@ -562,8 +589,12 @@ void ToolChainOptionsPage::finish() m_configWidget = 0; // deleted by settingsdialog m_selectionModel = 0; // child of m_configWidget - m_ui = 0; // child of m_configWidget m_currentTcWidget = 0; // deleted by the model + // childs of m_configWidget + m_toolChainView = 0; + m_addButton = 0; + m_cloneButton = 0; + m_delButton = 0; } bool ToolChainOptionsPage::matches(const QString &s) const @@ -619,7 +650,7 @@ void ToolChainOptionsPage::removeToolChain() void ToolChainOptionsPage::updateState() { - if (!m_ui) + if (!m_cloneButton) return; bool canCopy = false; @@ -630,8 +661,8 @@ void ToolChainOptionsPage::updateState() canDelete = !tc->isAutoDetected(); } - m_ui->cloneButton->setEnabled(canCopy); - m_ui->delButton->setEnabled(canDelete); + m_cloneButton->setEnabled(canCopy); + m_delButton->setEnabled(canDelete); } QModelIndex ToolChainOptionsPage::currentIndex() const diff --git a/src/plugins/projectexplorer/toolchainoptionspage.h b/src/plugins/projectexplorer/toolchainoptionspage.h index 2049154455..9d882b2001 100644 --- a/src/plugins/projectexplorer/toolchainoptionspage.h +++ b/src/plugins/projectexplorer/toolchainoptionspage.h @@ -33,15 +33,16 @@ #ifndef TOOLCHAINOPTIONSPAGE_H #define TOOLCHAINOPTIONSPAGE_H -#include "ui_toolchainoptionspage.h" - #include <coreplugin/dialogs/ioptionspage.h> #include <QAbstractItemModel> QT_BEGIN_NAMESPACE +class QBoxLayout; +class QItemSelectionModel; +class QPushButton; +class QTreeView; class QTreeWidgetItem; -class QWidget; QT_END_NAMESPACE namespace ProjectExplorer { @@ -63,7 +64,7 @@ class ToolChainModel : public QAbstractItemModel Q_OBJECT public: - explicit ToolChainModel(QWidget *configWidgetParent, QObject *parent = 0); + explicit ToolChainModel(QBoxLayout *parentLayout, QObject *parent = 0); ~ToolChainModel(); QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; @@ -109,7 +110,7 @@ private: QList<ToolChainNode *> m_toAddList; QList<ToolChainNode *> m_toRemoveList; - QWidget *m_configWidgetParent; + QBoxLayout *m_parentLayout; }; // -------------------------------------------------------------------------- @@ -137,7 +138,6 @@ private slots: private: QModelIndex currentIndex() const; - Ui::ToolChainOptionsPage *m_ui; QWidget *m_configWidget; QString m_searchKeywords; @@ -145,6 +145,10 @@ private: QList<ToolChainFactory *> m_factories; QItemSelectionModel * m_selectionModel; ToolChainConfigWidget *m_currentTcWidget; + QTreeView *m_toolChainView; + QPushButton *m_addButton; + QPushButton *m_cloneButton; + QPushButton *m_delButton; }; } // namespace Internal diff --git a/src/plugins/projectexplorer/toolchainoptionspage.ui b/src/plugins/projectexplorer/toolchainoptionspage.ui deleted file mode 100644 index 8c31359673..0000000000 --- a/src/plugins/projectexplorer/toolchainoptionspage.ui +++ /dev/null @@ -1,112 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>ProjectExplorer::Internal::ToolChainOptionsPage</class> - <widget class="QWidget" name="ProjectExplorer::Internal::ToolChainOptionsPage"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>398</width> - <height>296</height> - </rect> - </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <widget class="QTreeView" name="toolChainView"> - <property name="uniformRowHeights"> - <bool>true</bool> - </property> - <attribute name="headerStretchLastSection"> - <bool>false</bool> - </attribute> - </widget> - </item> - <item> - <layout class="QVBoxLayout" name="_2"> - <property name="spacing"> - <number>6</number> - </property> - <property name="margin"> - <number>0</number> - </property> - <item> - <widget class="QPushButton" name="addButton"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>21</width> - <height>23</height> - </size> - </property> - <property name="text"> - <string>Add</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="cloneButton"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>21</width> - <height>23</height> - </size> - </property> - <property name="text"> - <string>Clone</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="delButton"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>21</width> - <height>23</height> - </size> - </property> - <property name="text"> - <string>Remove</string> - </property> - </widget> - </item> - <item> - <spacer> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>10</width> - <height>40</height> - </size> - </property> - </spacer> - </item> - </layout> - </item> - </layout> - </item> - </layout> - </widget> - <resources/> - <connections/> -</ui> diff --git a/src/plugins/projectexplorer/wincetoolchain.cpp b/src/plugins/projectexplorer/wincetoolchain.cpp index 8108746528..eb08ddba9e 100644 --- a/src/plugins/projectexplorer/wincetoolchain.cpp +++ b/src/plugins/projectexplorer/wincetoolchain.cpp @@ -50,7 +50,6 @@ #include <QXmlStreamReader> #define KEY_ROOT "ProjectExplorer.WinCEToolChain." -static const char debuggerCommandKeyC[] = KEY_ROOT"Debugger"; static const char msvcVerKeyC[] = KEY_ROOT"MSVCVer"; static const char ceVerKeyC[] = KEY_ROOT"CEVer"; static const char binPathKeyC[] = KEY_ROOT"BinPath"; @@ -278,23 +277,6 @@ WinCEToolChain *WinCEToolChain::readFromMap(const QVariantMap &data) return 0; } -QString WinCEToolChain::legacyId() const -{ - const QChar colon = QLatin1Char(':'); - QString id = QLatin1String(Constants::WINCE_TOOLCHAIN_ID); - id += colon; - id += m_msvcVer; - id += colon; - id += m_binPath; - id += colon; - id += m_includePath; - id += colon; - id += m_libPath; - id += colon; - id += m_debuggerCommand.toString(); - return id; -} - QString WinCEToolChain::type() const { return QLatin1String("wince"); @@ -330,8 +312,6 @@ QString WinCEToolChain::ceVer() const QVariantMap WinCEToolChain::toMap() const { QVariantMap data = ToolChain::toMap(); - if (!m_debuggerCommand.isEmpty()) - data.insert(QLatin1String(debuggerCommandKeyC), m_debuggerCommand.toString()); data.insert(QLatin1String(msvcVerKeyC), m_msvcVer); data.insert(QLatin1String(ceVerKeyC), m_ceVer); @@ -356,7 +336,6 @@ bool WinCEToolChain::fromMap(const QVariantMap &data) m_libPath = data.value(QLatin1String(libPathKeyC)).toString(); m_vcvarsBat = data.value(QLatin1String(vcVarsKeyC)).toString(); - m_debuggerCommand = Utils::FileName::fromString(data.value(QLatin1String(debuggerCommandKeyC)).toString()); const QString abiString = data.value(QLatin1String(supportedAbiKeyC)).toString(); m_abi = Abi(abiString); diff --git a/src/plugins/projectexplorer/wincetoolchain.h b/src/plugins/projectexplorer/wincetoolchain.h index f09a1ded26..2f8e7db30b 100644 --- a/src/plugins/projectexplorer/wincetoolchain.h +++ b/src/plugins/projectexplorer/wincetoolchain.h @@ -57,7 +57,6 @@ public: const QString &libPath, bool autodetect = false); - QString legacyId() const; QList<Utils::FileName> suggestedMkspecList() const; static WinCEToolChain *readFromMap(const QVariantMap &data); @@ -65,8 +64,6 @@ public: QString type() const; QString typeDisplayName() const; - Utils::FileName mkspecList() const; - QString ceVer() const; QVariantMap toMap() const; |