ProjectExplorer: Let users define a common run environment

That is, environment variables that should be set in all run
configurations of all projects, but not e.g. in build configurations.

Fixes: QTCREATORBUG-29530
Change-Id: If48d6d9bf006a293c2cbbf0d8d1aa16f9bf604f4
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
Christian Kandeler
2023-10-04 15:42:20 +02:00
parent 6b81c93a66
commit 007fd9fa9b
4 changed files with 52 additions and 0 deletions

View File

@@ -6,6 +6,8 @@
#include "buildconfiguration.h" #include "buildconfiguration.h"
#include "environmentaspectwidget.h" #include "environmentaspectwidget.h"
#include "kit.h" #include "kit.h"
#include "projectexplorer.h"
#include "projectexplorersettings.h"
#include "projectexplorertr.h" #include "projectexplorertr.h"
#include "target.h" #include "target.h"
@@ -28,6 +30,13 @@ EnvironmentAspect::EnvironmentAspect(AspectContainer *container)
setId("EnvironmentAspect"); setId("EnvironmentAspect");
setConfigWidgetCreator([this] { return new EnvironmentAspectWidget(this); }); setConfigWidgetCreator([this] { return new EnvironmentAspectWidget(this); });
addDataExtractor(this, &EnvironmentAspect::environment, &Data::environment); addDataExtractor(this, &EnvironmentAspect::environment, &Data::environment);
if (qobject_cast<RunConfiguration *>(container)) {
addModifier([](Environment &env) {
env.modify(ProjectExplorerPlugin::projectExplorerSettings().appEnvChanges);
});
connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::settingsChanged,
this, &EnvironmentAspect::environmentChanged);
}
} }
void EnvironmentAspect::setDeviceSelector(Target *target, DeviceSelector selector) void EnvironmentAspect::setDeviceSelector(Target *target, DeviceSelector selector)

View File

@@ -274,6 +274,7 @@ const char CLEAR_ISSUES_ON_REBUILD_SETTINGS_KEY[] = "ProjectExplorer/Settings/Cl
const char ABORT_BUILD_ALL_ON_ERROR_SETTINGS_KEY[] const char ABORT_BUILD_ALL_ON_ERROR_SETTINGS_KEY[]
= "ProjectExplorer/Settings/AbortBuildAllOnError"; = "ProjectExplorer/Settings/AbortBuildAllOnError";
const char LOW_BUILD_PRIORITY_SETTINGS_KEY[] = "ProjectExplorer/Settings/LowBuildPriority"; const char LOW_BUILD_PRIORITY_SETTINGS_KEY[] = "ProjectExplorer/Settings/LowBuildPriority";
const char APP_ENV_CHANGES_SETTINGS_KEY[] = "ProjectExplorer/Settings/AppEnvChanges";
const char CUSTOM_PARSER_COUNT_KEY[] = "ProjectExplorer/Settings/CustomParserCount"; const char CUSTOM_PARSER_COUNT_KEY[] = "ProjectExplorer/Settings/CustomParserCount";
const char CUSTOM_PARSER_PREFIX_KEY[] = "ProjectExplorer/Settings/CustomParser"; const char CUSTOM_PARSER_PREFIX_KEY[] = "ProjectExplorer/Settings/CustomParser";
@@ -1701,6 +1702,8 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
dd->m_projectExplorerSettings.lowBuildPriority dd->m_projectExplorerSettings.lowBuildPriority
= s->value(Constants::LOW_BUILD_PRIORITY_SETTINGS_KEY, defaultSettings.lowBuildPriority) = s->value(Constants::LOW_BUILD_PRIORITY_SETTINGS_KEY, defaultSettings.lowBuildPriority)
.toBool(); .toBool();
dd->m_projectExplorerSettings.appEnvChanges = EnvironmentItem::fromStringList(
s->value(Constants::APP_ENV_CHANGES_SETTINGS_KEY).toStringList());
const int customParserCount = s->value(Constants::CUSTOM_PARSER_COUNT_KEY).toInt(); const int customParserCount = s->value(Constants::CUSTOM_PARSER_COUNT_KEY).toInt();
for (int i = 0; i < customParserCount; ++i) { for (int i = 0; i < customParserCount; ++i) {
@@ -2260,6 +2263,8 @@ void ProjectExplorerPluginPrivate::savePersistentSettings()
s->setValueWithDefault(Constants::STOP_BEFORE_BUILD_SETTINGS_KEY, s->setValueWithDefault(Constants::STOP_BEFORE_BUILD_SETTINGS_KEY,
int(dd->m_projectExplorerSettings.stopBeforeBuild), int(dd->m_projectExplorerSettings.stopBeforeBuild),
int(defaultSettings.stopBeforeBuild)); int(defaultSettings.stopBeforeBuild));
s->setValueWithDefault(Constants::APP_ENV_CHANGES_SETTINGS_KEY,
EnvironmentItem::toStringList(dd->m_projectExplorerSettings.appEnvChanges));
buildPropertiesSettings().writeSettings(); // FIXME: Should not be needed. buildPropertiesSettings().writeSettings(); // FIXME: Should not be needed.

View File

@@ -11,6 +11,7 @@
#include <coreplugin/coreconstants.h> #include <coreplugin/coreconstants.h>
#include <coreplugin/documentmanager.h> #include <coreplugin/documentmanager.h>
#include <utils/environmentdialog.h>
#include <utils/layoutbuilder.h> #include <utils/layoutbuilder.h>
#include <utils/hostosinfo.h> #include <utils/hostosinfo.h>
#include <utils/pathchooser.h> #include <utils/pathchooser.h>
@@ -20,6 +21,7 @@
#include <QComboBox> #include <QComboBox>
#include <QCoreApplication> #include <QCoreApplication>
#include <QLabel> #include <QLabel>
#include <QPushButton>
#include <QRadioButton> #include <QRadioButton>
using namespace Core; using namespace Core;
@@ -52,8 +54,10 @@ public:
private: private:
void slotDirectoryButtonGroupChanged(); void slotDirectoryButtonGroupChanged();
void updateAppEnvChangesLabel();
mutable ProjectExplorerSettings m_settings; mutable ProjectExplorerSettings m_settings;
Utils::EnvironmentItems m_appEnvChanges;
QRadioButton *m_currentDirectoryRadioButton; QRadioButton *m_currentDirectoryRadioButton;
QRadioButton *m_directoryRadioButton; QRadioButton *m_directoryRadioButton;
PathChooser *m_projectsDirectoryPathChooser; PathChooser *m_projectsDirectoryPathChooser;
@@ -70,6 +74,7 @@ private:
QComboBox *m_stopBeforeBuildComboBox; QComboBox *m_stopBeforeBuildComboBox;
QComboBox *m_terminalModeComboBox; QComboBox *m_terminalModeComboBox;
QCheckBox *m_jomCheckbox; QCheckBox *m_jomCheckbox;
Utils::ElidingLabel *m_appEnvLabel;
QButtonGroup *m_directoryButtonGroup; QButtonGroup *m_directoryButtonGroup;
}; };
@@ -122,6 +127,25 @@ ProjectExplorerSettingsWidget::ProjectExplorerSettingsWidget()
"Disable it if you experience problems with your builds."); "Disable it if you experience problems with your builds.");
jomLabel->setWordWrap(true); jomLabel->setWordWrap(true);
const QString appEnvToolTip = Tr::tr("Environment changes to apply to run configurations, "
"but not build configurations.");
const auto appEnvDescriptionLabel = new QLabel(Tr::tr("Application environment:"));
appEnvDescriptionLabel->setToolTip(appEnvToolTip);
m_appEnvLabel = new Utils::ElidingLabel;
m_appEnvLabel->setElideMode(Qt::ElideRight);
m_appEnvLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
const auto appEnvButton = new QPushButton(Tr::tr("Change..."));
appEnvButton->setSizePolicy(QSizePolicy::Fixed, appEnvButton->sizePolicy().verticalPolicy());
appEnvButton->setToolTip(appEnvToolTip);
connect(appEnvButton, &QPushButton::clicked, this, [appEnvButton, this] {
std::optional<EnvironmentItems> changes
= EnvironmentDialog::getEnvironmentItems(appEnvButton, m_appEnvChanges);
if (!changes)
return;
m_appEnvChanges = *changes;
updateAppEnvChangesLabel();
});
using namespace Layouting; using namespace Layouting;
Column { Column {
Group { Group {
@@ -149,6 +173,7 @@ ProjectExplorerSettingsWidget::ProjectExplorerSettingsWidget()
m_abortBuildAllOnErrorCheckBox, m_abortBuildAllOnErrorCheckBox,
m_lowBuildPriorityCheckBox, m_lowBuildPriorityCheckBox,
Form { Form {
appEnvDescriptionLabel, Row{m_appEnvLabel, appEnvButton, st}, br,
Tr::tr("Build before deploying:"), m_buildBeforeDeployComboBox, br, Tr::tr("Build before deploying:"), m_buildBeforeDeployComboBox, br,
Tr::tr("Stop applications before building:"), m_stopBeforeBuildComboBox, br, Tr::tr("Stop applications before building:"), m_stopBeforeBuildComboBox, br,
Tr::tr("Default for \"Run in terminal\":"), m_terminalModeComboBox, br, Tr::tr("Default for \"Run in terminal\":"), m_terminalModeComboBox, br,
@@ -174,6 +199,7 @@ ProjectExplorerSettingsWidget::ProjectExplorerSettingsWidget()
setSettings(ProjectExplorerPlugin::projectExplorerSettings()); setSettings(ProjectExplorerPlugin::projectExplorerSettings());
setProjectsDirectory(DocumentManager::projectsDirectory()); setProjectsDirectory(DocumentManager::projectsDirectory());
setUseProjectsDirectory(DocumentManager::useProjectsDirectory()); setUseProjectsDirectory(DocumentManager::useProjectsDirectory());
updateAppEnvChangesLabel();
} }
ProjectExplorerSettings ProjectExplorerSettingsWidget::settings() const ProjectExplorerSettings ProjectExplorerSettingsWidget::settings() const
@@ -193,12 +219,14 @@ ProjectExplorerSettings ProjectExplorerSettingsWidget::settings() const
m_settings.clearIssuesOnRebuild = m_clearIssuesCheckBox->isChecked(); m_settings.clearIssuesOnRebuild = m_clearIssuesCheckBox->isChecked();
m_settings.abortBuildAllOnError = m_abortBuildAllOnErrorCheckBox->isChecked(); m_settings.abortBuildAllOnError = m_abortBuildAllOnErrorCheckBox->isChecked();
m_settings.lowBuildPriority = m_lowBuildPriorityCheckBox->isChecked(); m_settings.lowBuildPriority = m_lowBuildPriorityCheckBox->isChecked();
m_settings.appEnvChanges = m_appEnvChanges;
return m_settings; return m_settings;
} }
void ProjectExplorerSettingsWidget::setSettings(const ProjectExplorerSettings &pes) void ProjectExplorerSettingsWidget::setSettings(const ProjectExplorerSettings &pes)
{ {
m_settings = pes; m_settings = pes;
m_appEnvChanges = pes.appEnvChanges;
m_buildBeforeDeployComboBox->setCurrentIndex( m_buildBeforeDeployComboBox->setCurrentIndex(
m_buildBeforeDeployComboBox->findData(int(m_settings.buildBeforeDeploy))); m_buildBeforeDeployComboBox->findData(int(m_settings.buildBeforeDeploy)));
m_deployProjectBeforeRunCheckBox->setChecked(m_settings.deployBeforeRun); m_deployProjectBeforeRunCheckBox->setChecked(m_settings.deployBeforeRun);
@@ -245,6 +273,13 @@ void ProjectExplorerSettingsWidget::slotDirectoryButtonGroupChanged()
m_projectsDirectoryPathChooser->setEnabled(enable); m_projectsDirectoryPathChooser->setEnabled(enable);
} }
void ProjectExplorerSettingsWidget::updateAppEnvChangesLabel()
{
const QString shortSummary = EnvironmentItem::toStringList(m_appEnvChanges).join("; ");
m_appEnvLabel->setText(shortSummary.isEmpty() ? Tr::tr("No changes to apply.")
: shortSummary);
}
// ProjectExplorerSettingsPage // ProjectExplorerSettingsPage
ProjectExplorerSettingsPage::ProjectExplorerSettingsPage() ProjectExplorerSettingsPage::ProjectExplorerSettingsPage()

View File

@@ -6,6 +6,7 @@
#include <coreplugin/coreconstants.h> #include <coreplugin/coreconstants.h>
#include <coreplugin/dialogs/ioptionspage.h> #include <coreplugin/dialogs/ioptionspage.h>
#include <utils/environment.h>
#include <utils/hostosinfo.h> #include <utils/hostosinfo.h>
#include <QUuid> #include <QUuid>
@@ -34,6 +35,7 @@ public:
&& p1.closeSourceFilesWithProject == p2.closeSourceFilesWithProject && p1.closeSourceFilesWithProject == p2.closeSourceFilesWithProject
&& p1.clearIssuesOnRebuild == p2.clearIssuesOnRebuild && p1.clearIssuesOnRebuild == p2.clearIssuesOnRebuild
&& p1.abortBuildAllOnError == p2.abortBuildAllOnError && p1.abortBuildAllOnError == p2.abortBuildAllOnError
&& p1.appEnvChanges == p2.appEnvChanges
&& p1.lowBuildPriority == p2.lowBuildPriority; && p1.lowBuildPriority == p2.lowBuildPriority;
} }
@@ -52,6 +54,7 @@ public:
? StopBeforeBuild::SameProject ? StopBeforeBuild::SameProject
: StopBeforeBuild::None; : StopBeforeBuild::None;
TerminalMode terminalMode = TerminalMode::Off; TerminalMode terminalMode = TerminalMode::Off;
Utils::EnvironmentItems appEnvChanges;
// Add a UUid which is used to identify the development environment. // Add a UUid which is used to identify the development environment.
// This is used to warn the user when he is trying to open a .user file that was created // This is used to warn the user when he is trying to open a .user file that was created