diff --git a/src/libs/utils/environmentdialog.cpp b/src/libs/utils/environmentdialog.cpp index 82cc998e372..ee569fea9a4 100644 --- a/src/libs/utils/environmentdialog.cpp +++ b/src/libs/utils/environmentdialog.cpp @@ -8,14 +8,18 @@ namespace Utils { std::optional EnvironmentDialog::getEnvironmentItems( - QWidget *parent, const EnvironmentItems &initial, const QString &placeholderText, Polisher polisher) + QWidget *parent, + const EnvironmentItems &initial, + const QString &placeholderText, + Polisher polisher, + const QString &dialogTitle) { return getNameValueItems( parent, initial, placeholderText, polisher, - Tr::tr("Edit Environment")); + dialogTitle.isEmpty() ? Tr::tr("Edit Environment") : dialogTitle); } } // namespace Utils diff --git a/src/libs/utils/environmentdialog.h b/src/libs/utils/environmentdialog.h index 335ba7ffe58..69340e6a951 100644 --- a/src/libs/utils/environmentdialog.h +++ b/src/libs/utils/environmentdialog.h @@ -13,10 +13,12 @@ namespace Utils { class QTCREATOR_UTILS_EXPORT EnvironmentDialog : public NameValuesDialog { public: - static std::optional getEnvironmentItems(QWidget *parent = nullptr, - const EnvironmentItems &initial = {}, - const QString &placeholderText = {}, - Polisher polish = {}); + static std::optional getEnvironmentItems( + QWidget *parent = nullptr, + const EnvironmentItems &initial = {}, + const QString &placeholderText = {}, + Polisher polish = {}, + const QString &dialogTitle = {}); }; } // namespace Utils diff --git a/src/plugins/mcusupport/mcukitmanager.cpp b/src/plugins/mcusupport/mcukitmanager.cpp index 194c5efd840..a50f1d0135a 100644 --- a/src/plugins/mcusupport/mcukitmanager.cpp +++ b/src/plugins/mcusupport/mcukitmanager.cpp @@ -247,7 +247,7 @@ public: if (McuSupportOptions::kitsNeedQtVersion()) changes.append({QLatin1String("LD_LIBRARY_PATH"), "%{Qt:QT_INSTALL_LIBS}"}); - EnvironmentKitAspect::setEnvironmentChanges(k, changes); + EnvironmentKitAspect::setBuildEnvChanges(k, changes); } static void setKitCMakeOptions(Kit *k, diff --git a/src/plugins/projectexplorer/environmentaspect.cpp b/src/plugins/projectexplorer/environmentaspect.cpp index 43107b6141d..5b2295d8132 100644 --- a/src/plugins/projectexplorer/environmentaspect.cpp +++ b/src/plugins/projectexplorer/environmentaspect.cpp @@ -5,6 +5,7 @@ #include "buildconfiguration.h" #include "environmentaspectwidget.h" +#include "environmentkitaspect.h" #include "kit.h" #include "projectexplorer.h" #include "projectexplorersettings.h" @@ -30,8 +31,11 @@ EnvironmentAspect::EnvironmentAspect(AspectContainer *container) setId("EnvironmentAspect"); setConfigWidgetCreator([this] { return new EnvironmentAspectWidget(this); }); addDataExtractor(this, &EnvironmentAspect::environment, &Data::environment); - if (qobject_cast(container)) { - addModifier([](Environment &env) { env.modify(projectExplorerSettings().appEnvChanges); }); + if (const auto runConfig = qobject_cast(container)) { + addModifier([runConfig](Environment &env) { + env.modify(projectExplorerSettings().appEnvChanges); + env.modify(EnvironmentKitAspect::runEnvChanges(runConfig->kit())); + }); connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::settingsChanged, this, &EnvironmentAspect::environmentChanged); } diff --git a/src/plugins/projectexplorer/environmentkitaspect.cpp b/src/plugins/projectexplorer/environmentkitaspect.cpp index 19b56be9cc0..1d33e7e6b3b 100644 --- a/src/plugins/projectexplorer/environmentkitaspect.cpp +++ b/src/plugins/projectexplorer/environmentkitaspect.cpp @@ -10,7 +10,6 @@ #include "toolchain.h" #include -#include #include #include #include @@ -23,8 +22,8 @@ #include #include +#include #include -#include using namespace Utils; @@ -41,57 +40,76 @@ static bool enforcesMSVCEnglish(const EnvironmentItems &changes) return changes.contains(forceMSVCEnglishItem()); } +static Id buildEnvId() { return "PE.Profile.Environment"; } +static Id runEnvId() { return "PE.Profile.RunEnvironment"; } + namespace Internal { class EnvironmentKitAspectImpl final : public KitAspect { public: EnvironmentKitAspectImpl(Kit *workingCopy, const KitAspectFactory *factory) : KitAspect(workingCopy, factory), - m_summaryLabel(createSubWidget()), - m_manageButton(createSubWidget()), - m_mainWidget(createSubWidget()) + m_mainWidget(createSubWidget()), + m_buildEnvButton(createSubWidget()), + m_runEnvButton(createSubWidget()) { - auto *layout = new QVBoxLayout; - layout->setContentsMargins(0, 0, 0, 0); - layout->addWidget(m_summaryLabel); + addMutableAction(m_mainWidget); if (HostOsInfo::isWindowsHost()) - initMSVCOutputSwitch(layout); - m_mainWidget->setLayout(layout); + initMSVCOutputSwitch(); refresh(); - m_manageButton->setText(Tr::tr("Change...")); - connect(m_manageButton, &QAbstractButton::clicked, - this, &EnvironmentKitAspectImpl::editEnvironmentChanges); + m_buildEnvButton->setText(Tr::tr("Edit Build Environment...")); + m_buildEnvButton->setIcon({}); + m_runEnvButton->setText(Tr::tr("Edit Run Environment...")); + connect(m_buildEnvButton, &QAbstractButton::clicked, + this, &EnvironmentKitAspectImpl::editBuildEnvironmentChanges); + connect(m_runEnvButton, &QAbstractButton::clicked, + this, &EnvironmentKitAspectImpl::editRunEnvironmentChanges); } private: void addToInnerLayout(Layouting::Layout &layout) override { - addMutableAction(m_mainWidget); + Layouting::Layout box(new QHBoxLayout); + box.setContentsMargins(0, 0, 0, 0); + box.attachTo(m_mainWidget); + if (m_vslangCheckbox) + box.addItem(m_vslangCheckbox); + box.addItems({m_buildEnvButton, m_runEnvButton}); + box.addItem(Layouting::Stretch(1)); layout.addItem(m_mainWidget); - layout.addItem(m_manageButton); } - void makeReadOnly() override { m_manageButton->setEnabled(false); } + void makeReadOnly() override + { + if (m_vslangCheckbox) + m_vslangCheckbox->setEnabled(false); + m_buildEnvButton->setEnabled(false); + m_runEnvButton->setEnabled(false); + } void refresh() override { - const EnvironmentItems changes = EnvironmentKitAspect::environmentChanges(kit()); - const QString shortSummary = EnvironmentItem::toStringList(changes).join("; "); - m_summaryLabel->setText(shortSummary.isEmpty() ? Tr::tr("No changes to apply.") : shortSummary); + const auto toString = [](const EnvironmentItems &changes) { + return EnvironmentItem::toStringList(changes).join("\n"); + }; + m_buildEnvButton->setToolTip(toString(EnvironmentKitAspect::buildEnvChanges(kit()))); + m_runEnvButton->setToolTip(toString(EnvironmentKitAspect::runEnvChanges(kit()))); + + // TODO: Set an icon on the button representing whether there are changes or not. } - void editEnvironmentChanges() + void editBuildEnvironmentChanges() { - MacroExpander *expander = kit()->macroExpander(); - EnvironmentDialog::Polisher polisher = [expander](QWidget *w) { - VariableChooser::addSupportForChildWidgets(w, expander); - }; auto changes = EnvironmentDialog::getEnvironmentItems( - m_summaryLabel, EnvironmentKitAspect::environmentChanges(kit()), QString(), polisher); + m_mainWidget, + EnvironmentKitAspect::buildEnvChanges(kit()), + QString(), + polisher(), + Tr::tr("Edit Build Environment")); if (!changes) return; - if (HostOsInfo::isWindowsHost()) { + if (m_vslangCheckbox) { // re-add what envWithoutMSVCEnglishEnforcement removed // or update vslang checkbox if user added it manually if (m_vslangCheckbox->isChecked() && !enforcesMSVCEnglish(*changes)) @@ -99,33 +117,51 @@ private: else if (enforcesMSVCEnglish(*changes)) m_vslangCheckbox->setChecked(true); } - EnvironmentKitAspect::setEnvironmentChanges(kit(), *changes); + EnvironmentKitAspect::setBuildEnvChanges(kit(), *changes); } - void initMSVCOutputSwitch(QVBoxLayout *layout) + void editRunEnvironmentChanges() { - m_vslangCheckbox = new QCheckBox(Tr::tr("Force UTF-8 MSVC compiler output")); - layout->addWidget(m_vslangCheckbox); + if (const auto changes = EnvironmentDialog::getEnvironmentItems( + m_mainWidget, + EnvironmentKitAspect::runEnvChanges(kit()), + QString(), + polisher(), + Tr::tr("Edit Run Environment"))) { + EnvironmentKitAspect::setRunEnvChanges(kit(), *changes); + } + } + + EnvironmentDialog::Polisher polisher() const + { + return [expander = kit()->macroExpander()](QWidget *w) { + VariableChooser::addSupportForChildWidgets(w, expander); + }; + } + + void initMSVCOutputSwitch() + { + m_vslangCheckbox = new QCheckBox(Tr::tr("Force UTF-8 MSVC output")); m_vslangCheckbox->setToolTip(Tr::tr("Either switches MSVC to English or keeps the language and " "just forces UTF-8 output (may vary depending on the used MSVC " "compiler).")); m_vslangCheckbox->setChecked( - enforcesMSVCEnglish(EnvironmentKitAspect::environmentChanges(kit()))); + enforcesMSVCEnglish(EnvironmentKitAspect::buildEnvChanges(kit()))); connect(m_vslangCheckbox, &QCheckBox::clicked, this, [this](bool checked) { - EnvironmentItems changes = EnvironmentKitAspect::environmentChanges(kit()); + EnvironmentItems changes = EnvironmentKitAspect::buildEnvChanges(kit()); const bool hasVsLangEntry = enforcesMSVCEnglish(changes); if (checked && !hasVsLangEntry) changes.append(forceMSVCEnglishItem()); else if (!checked && hasVsLangEntry) changes.removeAll(forceMSVCEnglishItem()); - EnvironmentKitAspect::setEnvironmentChanges(kit(), changes); + EnvironmentKitAspect::setBuildEnvChanges(kit(), changes); }); } - ElidingLabel *m_summaryLabel; - QPushButton *m_manageButton; - QCheckBox *m_vslangCheckbox; - QWidget *m_mainWidget; + QWidget * const m_mainWidget; + QPushButton * const m_buildEnvButton; + QPushButton * const m_runEnvButton; + QCheckBox *m_vslangCheckbox = nullptr; }; class EnvironmentKitAspectFactory : public KitAspectFactory @@ -157,7 +193,7 @@ Tasks EnvironmentKitAspectFactory::validate(const Kit *k) const Tasks result; QTC_ASSERT(k, return result); - const QVariant variant = k->value(EnvironmentKitAspect::id()); + const QVariant variant = k->value(buildEnvId()); if (!variant.isNull() && !variant.canConvert(QMetaType(QMetaType::QVariantList))) result << BuildSystemTask(Task::Error, Tr::tr("The environment setting value is invalid.")); @@ -168,24 +204,32 @@ void EnvironmentKitAspectFactory::fix(Kit *k) { QTC_ASSERT(k, return); - const QVariant variant = k->value(EnvironmentKitAspect::id()); - if (!variant.isNull() && !variant.canConvert(QMetaType(QMetaType::QVariantList))) { - qWarning("Kit \"%s\" has a wrong environment value set.", qPrintable(k->displayName())); - EnvironmentKitAspect::setEnvironmentChanges(k, EnvironmentItems()); + if (const QVariant variant = k->value(buildEnvId()); + !variant.isNull() && !variant.canConvert(QMetaType(QMetaType::QVariantList))) { + qWarning("Kit \"%s\" has a wrong build environment value set.", qPrintable(k->displayName())); + EnvironmentKitAspect::setBuildEnvChanges(k, EnvironmentItems()); + } + if (const QVariant variant = k->value(runEnvId()); + !variant.isNull() && !variant.canConvert(QMetaType(QMetaType::QVariantList))) { + qWarning("Kit \"%s\" has a wrong run environment value set.", qPrintable(k->displayName())); + EnvironmentKitAspect::setRunEnvChanges(k, EnvironmentItems()); } } void EnvironmentKitAspectFactory::addToBuildEnvironment(const Kit *k, Environment &env) const { const QStringList values - = transform(EnvironmentItem::toStringList(EnvironmentKitAspect::environmentChanges(k)), + = transform(EnvironmentItem::toStringList(EnvironmentKitAspect::buildEnvChanges(k)), [k](const QString &v) { return k->macroExpander()->expand(v); }); env.modify(EnvironmentItem::fromStringList(values)); } void EnvironmentKitAspectFactory::addToRunEnvironment(const Kit *k, Environment &env) const { - addToBuildEnvironment(k, env); + const QStringList values + = transform(EnvironmentItem::toStringList(EnvironmentKitAspect::runEnvChanges(k)), + [k](const QString &v) { return k->macroExpander()->expand(v); }); + env.modify(EnvironmentItem::fromStringList(values)); } KitAspect *EnvironmentKitAspectFactory::createKitAspect(Kit *k) const @@ -196,8 +240,14 @@ KitAspect *EnvironmentKitAspectFactory::createKitAspect(Kit *k) const KitAspectFactory::ItemList EnvironmentKitAspectFactory::toUserOutput(const Kit *k) const { - return {{Tr::tr("Environment"), - EnvironmentItem::toStringList(EnvironmentKitAspect::environmentChanges(k)).join("
")}}; + ItemList list; + const auto addIfNotEmpty = [&](const QString &displayName, const EnvironmentItems &changes) { + if (!changes.isEmpty()) + list.emplaceBack(displayName, EnvironmentItem::toStringList(changes).join("
")); + }; + addIfNotEmpty(Tr::tr("Build Environment"), EnvironmentKitAspect::buildEnvChanges(k)); + addIfNotEmpty(Tr::tr("Run Environment"), EnvironmentKitAspect::runEnvChanges(k)); + return list; } const EnvironmentKitAspectFactory theEnvironmentKitAspectFactory; @@ -206,20 +256,33 @@ const EnvironmentKitAspectFactory theEnvironmentKitAspectFactory; Id EnvironmentKitAspect::id() { - return "PE.Profile.Environment"; + return buildEnvId(); } -EnvironmentItems EnvironmentKitAspect::environmentChanges(const Kit *k) +EnvironmentItems EnvironmentKitAspect::buildEnvChanges(const Kit *k) { if (k) - return EnvironmentItem::fromStringList(k->value(EnvironmentKitAspect::id()).toStringList()); + return EnvironmentItem::fromStringList(k->value(buildEnvId()).toStringList()); return {}; } -void EnvironmentKitAspect::setEnvironmentChanges(Kit *k, const EnvironmentItems &changes) +void EnvironmentKitAspect::setBuildEnvChanges(Kit *k, const EnvironmentItems &changes) { if (k) - k->setValue(EnvironmentKitAspect::id(), EnvironmentItem::toStringList(changes)); + k->setValue(buildEnvId(), EnvironmentItem::toStringList(changes)); +} + +EnvironmentItems EnvironmentKitAspect::runEnvChanges(const Kit *k) +{ + if (k) + return EnvironmentItem::fromStringList(k->value(runEnvId()).toStringList()); + return {}; +} + +void EnvironmentKitAspect::setRunEnvChanges(Kit *k, const Utils::EnvironmentItems &changes) +{ + if (k) + k->setValue(runEnvId(), EnvironmentItem::toStringList(changes)); } } // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/environmentkitaspect.h b/src/plugins/projectexplorer/environmentkitaspect.h index b7ebc155576..5985c08ac28 100644 --- a/src/plugins/projectexplorer/environmentkitaspect.h +++ b/src/plugins/projectexplorer/environmentkitaspect.h @@ -16,8 +16,12 @@ class PROJECTEXPLORER_EXPORT EnvironmentKitAspect { public: static Utils::Id id(); - static Utils::EnvironmentItems environmentChanges(const Kit *k); - static void setEnvironmentChanges(Kit *k, const Utils::EnvironmentItems &changes); + + static Utils::EnvironmentItems buildEnvChanges(const Kit *k); + static void setBuildEnvChanges(Kit *k, const Utils::EnvironmentItems &changes); + + static Utils::EnvironmentItems runEnvChanges(const Kit *k); + static void setRunEnvChanges(Kit *k, const Utils::EnvironmentItems &changes); }; } // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/extracompiler.cpp b/src/plugins/projectexplorer/extracompiler.cpp index e72ce3772dd..c11e3c4bc64 100644 --- a/src/plugins/projectexplorer/extracompiler.cpp +++ b/src/plugins/projectexplorer/extracompiler.cpp @@ -277,7 +277,7 @@ Environment ExtraCompiler::buildEnvironment() const if (BuildConfiguration *bc = target->activeBuildConfiguration()) return bc->environment(); - const EnvironmentItems changes = EnvironmentKitAspect::environmentChanges(target->kit()); + const EnvironmentItems changes = EnvironmentKitAspect::buildEnvChanges(target->kit()); Environment env = Environment::systemEnvironment(); env.modify(changes); return env; diff --git a/src/plugins/qnx/qnxsettingspage.cpp b/src/plugins/qnx/qnxsettingspage.cpp index a5db2b60423..bc1ee131ef9 100644 --- a/src/plugins/qnx/qnxsettingspage.cpp +++ b/src/plugins/qnx/qnxsettingspage.cpp @@ -283,7 +283,7 @@ void QnxConfiguration::createKit(const QnxTarget &target) k->setSticky(DebuggerKitAspect::id(), true); k->setSticky(QmakeProjectManager::Constants::KIT_INFORMATION_ID, true); - EnvironmentKitAspect::setEnvironmentChanges(k, qnxEnvironmentItems()); + EnvironmentKitAspect::setBuildEnvChanges(k, qnxEnvironmentItems()); }; // add kit with device and qt version not sticky