diff options
author | hjk <hjk@qt.io> | 2018-04-24 16:00:53 +0200 |
---|---|---|
committer | hjk <hjk@qt.io> | 2018-04-26 13:58:00 +0000 |
commit | 98b026f9a97d3a2311eb6ec5e88b20dbd76f3e26 (patch) | |
tree | c0e48c11322a5028d5a8035ceba16d0c3f0eaaf8 /src/plugins/projectexplorer/customexecutablerunconfiguration.cpp | |
parent | 219e23332e5e21d3e4e1a9334bf3f5ef1d485b59 (diff) |
ProjectExplorer: Rework CustomExecutableRunConfiguration
Split the run config widget according to the two use cases
(direct apply, delayed apply). As basically most data members
and important logic was not shared, the double-use made
the CustomExecutableRunConfiguration implementation needlessly
complicated.
Change-Id: If92ba22bae31378bae29049e0d27095b2bbd6090
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
Diffstat (limited to 'src/plugins/projectexplorer/customexecutablerunconfiguration.cpp')
-rw-r--r-- | src/plugins/projectexplorer/customexecutablerunconfiguration.cpp | 271 |
1 files changed, 139 insertions, 132 deletions
diff --git a/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp b/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp index 655aa7ee30..da6e50df4b 100644 --- a/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp +++ b/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp @@ -27,110 +27,125 @@ #include "abi.h" #include "buildconfiguration.h" -#include "customexecutableconfigurationwidget.h" #include "devicesupport/devicemanager.h" +#include "environmentaspect.h" #include "localenvironmentaspect.h" #include "project.h" #include "runconfigurationaspects.h" #include "target.h" #include <coreplugin/icore.h> +#include <coreplugin/variablechooser.h> -#include <utils/qtcprocess.h> +#include <utils/detailswidget.h> +#include <utils/pathchooser.h> #include <utils/stringutils.h> #include <QDialog> #include <QDialogButtonBox> #include <QDir> +#include <QFormLayout> #include <QKeyEvent> #include <QLabel> +#include <QLineEdit> #include <QPushButton> #include <QVBoxLayout> -using namespace ProjectExplorer::Internal; +using namespace Utils; namespace ProjectExplorer { const char CUSTOM_EXECUTABLE_ID[] = "ProjectExplorer.CustomExecutableRunConfiguration"; -const char EXECUTABLE_KEY[] = "ProjectExplorer.CustomExecutableRunConfiguration.Executable"; -// Dialog embedding the CustomExecutableConfigurationWidget -// prompting the user to complete the configuration. +// Dialog prompting the user to complete the configuration. + class CustomExecutableDialog : public QDialog { - Q_OBJECT public: - explicit CustomExecutableDialog(CustomExecutableRunConfiguration *rc, QWidget *parent = 0); - - void accept(); + explicit CustomExecutableDialog(RunConfiguration *rc); - bool event(QEvent *event); + void accept() override; + bool event(QEvent *event) override; private: - void changed() - { - setOkButtonEnabled(m_widget->isValid()); - } - - inline void setOkButtonEnabled(bool e) - { - m_dialogButtonBox->button(QDialogButtonBox::Ok)->setEnabled(e); + void changed() { + bool isValid = !m_executableChooser->rawPath().isEmpty(); + m_dialogButtonBox->button(QDialogButtonBox::Ok)->setEnabled(isValid); } - QDialogButtonBox *m_dialogButtonBox; - CustomExecutableConfigurationWidget *m_widget; +private: + void environmentWasChanged(); + + QDialogButtonBox *m_dialogButtonBox = nullptr; + RunConfiguration *m_rc = nullptr; + ArgumentsAspect m_arguments; + WorkingDirectoryAspect m_workingDirectory; + TerminalAspect m_terminal; + PathChooser *m_executableChooser = nullptr; }; -CustomExecutableRunConfiguration::CustomExecutableRunConfiguration(Target *target, Core::Id id) - : RunConfiguration(target, id) +CustomExecutableDialog::CustomExecutableDialog(RunConfiguration *rc) + : QDialog(Core::ICore::dialogParent()), + m_rc(rc), + m_arguments(rc, rc->extraAspect<ArgumentsAspect>()->settingsKey()), + m_workingDirectory(rc, rc->extraAspect<WorkingDirectoryAspect>()->settingsKey()), + m_terminal(rc, rc->extraAspect<TerminalAspect>()->settingsKey()) { - addExtraAspect(new LocalEnvironmentAspect(this, LocalEnvironmentAspect::BaseEnvironmentModifier())); - addExtraAspect(new ArgumentsAspect(this, "ProjectExplorer.CustomExecutableRunConfiguration.Arguments")); - addExtraAspect(new TerminalAspect(this, "ProjectExplorer.CustomExecutableRunConfiguration.UseTerminal")); - addExtraAspect(new WorkingDirectoryAspect(this, "ProjectExplorer.CustomExecutableRunConfiguration.WorkingDirectory")); - setDefaultDisplayName(defaultDisplayName()); -} + auto vbox = new QVBoxLayout(this); + vbox->addWidget(new QLabel(tr("Could not find the executable, please specify one."))); -CustomExecutableRunConfiguration::CustomExecutableRunConfiguration(Target *target) - : CustomExecutableRunConfiguration(target, CUSTOM_EXECUTABLE_ID) -{ -} + auto layout = new QFormLayout; + layout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow); + layout->setMargin(0); -// Note: Qt4Project deletes all empty customexecrunconfigs for which isConfigured() == false. -CustomExecutableRunConfiguration::~CustomExecutableRunConfiguration() -{ - if (m_dialog) { - emit configurationFinished(); - disconnect(m_dialog, &QDialog::finished, - this, &CustomExecutableRunConfiguration::configurationDialogFinished); - } - delete m_dialog; -} + auto detailsContainer = new DetailsWidget(this); + detailsContainer->setState(DetailsWidget::NoSummary); + vbox->addWidget(detailsContainer); -CustomExecutableDialog::CustomExecutableDialog(CustomExecutableRunConfiguration *rc, QWidget *parent) - : QDialog(parent) - , m_dialogButtonBox(new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel)) -{ - setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); - QVBoxLayout *layout = new QVBoxLayout(this); - QLabel *label = new QLabel(tr("Could not find the executable, please specify one.")); - label->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); - layout->addWidget(label); - m_widget = new CustomExecutableConfigurationWidget(rc, CustomExecutableConfigurationWidget::DelayedApply); - m_widget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); - connect(m_widget, &CustomExecutableConfigurationWidget::validChanged, - this, &CustomExecutableDialog::changed); - layout->addWidget(m_widget); - setOkButtonEnabled(false); + m_dialogButtonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + m_dialogButtonBox->button(QDialogButtonBox::Ok)->setEnabled(false); connect(m_dialogButtonBox, &QDialogButtonBox::accepted, this, &CustomExecutableDialog::accept); connect(m_dialogButtonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); - layout->addWidget(m_dialogButtonBox); - layout->setSizeConstraint(QLayout::SetMinAndMaxSize); + vbox->addWidget(m_dialogButtonBox); + vbox->setSizeConstraint(QLayout::SetMinAndMaxSize); + + auto detailsWidget = new QWidget(detailsContainer); + detailsContainer->setWidget(detailsWidget); + detailsWidget->setLayout(layout); + + m_executableChooser = new PathChooser(this); + m_executableChooser->setHistoryCompleter("Qt.CustomExecutable.History"); + m_executableChooser->setExpectedKind(PathChooser::ExistingCommand); + m_executableChooser->setPath(rc->extraAspect<ExecutableAspect>()->executable().toString()); + layout->addRow(tr("Executable:"), m_executableChooser); + connect(m_executableChooser, &PathChooser::rawPathChanged, + this, &CustomExecutableDialog::changed); + + m_arguments.copyFrom(rc->extraAspect<ArgumentsAspect>()); + m_arguments.addToConfigurationLayout(layout); + + m_workingDirectory.copyFrom(rc->extraAspect<WorkingDirectoryAspect>()); + m_workingDirectory.addToConfigurationLayout(layout); + + m_terminal.copyFrom(rc->extraAspect<TerminalAspect>()); + m_terminal.addToConfigurationLayout(layout); + + auto enviromentAspect = rc->extraAspect<EnvironmentAspect>(); + connect(enviromentAspect, &EnvironmentAspect::environmentChanged, + this, &CustomExecutableDialog::environmentWasChanged); + environmentWasChanged(); + + Core::VariableChooser::addSupportForChildWidgets(this, m_rc->macroExpander()); } void CustomExecutableDialog::accept() { - m_widget->apply(); + auto executable = FileName::fromString(m_executableChooser->path()); + m_rc->extraAspect<ExecutableAspect>()->setExecutable(executable); + m_rc->extraAspect<WorkingDirectoryAspect>()->copyFrom(&m_workingDirectory); + m_rc->extraAspect<ArgumentsAspect>()->copyFrom(&m_arguments); + m_rc->extraAspect<TerminalAspect>()->copyFrom(&m_terminal); + QDialog::accept(); } @@ -146,8 +161,55 @@ bool CustomExecutableDialog::event(QEvent *event) return QDialog::event(event); } +void CustomExecutableDialog::environmentWasChanged() +{ + auto aspect = m_rc->extraAspect<EnvironmentAspect>(); + QTC_ASSERT(aspect, return); + m_executableChooser->setEnvironment(aspect->environment()); +} + + // CustomExecutableRunConfiguration +CustomExecutableRunConfiguration::CustomExecutableRunConfiguration(Target *target) + : CustomExecutableRunConfiguration(target, CUSTOM_EXECUTABLE_ID) +{} + +CustomExecutableRunConfiguration::CustomExecutableRunConfiguration(Target *target, Core::Id id) + : RunConfiguration(target, id) +{ + auto envAspect = new LocalEnvironmentAspect(this, LocalEnvironmentAspect::BaseEnvironmentModifier()); + addExtraAspect(envAspect); + + auto exeAspect = new ExecutableAspect(this); + exeAspect->setSettingsKey("ProjectExplorer.CustomExecutableRunConfiguration.Executable"); + exeAspect->setDisplayStyle(BaseStringAspect::PathChooserDisplay); + exeAspect->setHistoryCompleter("Qt.CustomExecutable.History"); + exeAspect->setExpectedKind(PathChooser::ExistingCommand); + exeAspect->setEnvironment(envAspect->environment()); + addExtraAspect(exeAspect); + + addExtraAspect(new ArgumentsAspect(this, "ProjectExplorer.CustomExecutableRunConfiguration.Arguments")); + addExtraAspect(new TerminalAspect(this, "ProjectExplorer.CustomExecutableRunConfiguration.UseTerminal")); + addExtraAspect(new WorkingDirectoryAspect(this, "ProjectExplorer.CustomExecutableRunConfiguration.WorkingDirectory")); + + connect(envAspect, &EnvironmentAspect::environmentChanged, + this, [exeAspect, envAspect] { exeAspect->setEnvironment(envAspect->environment()); }); + + setDefaultDisplayName(defaultDisplayName()); +} + +// Note: Qt4Project deletes all empty customexecrunconfigs for which isConfigured() == false. +CustomExecutableRunConfiguration::~CustomExecutableRunConfiguration() +{ + if (m_dialog) { + emit configurationFinished(); + disconnect(m_dialog, &QDialog::finished, + this, &CustomExecutableRunConfiguration::configurationDialogFinished); + } + delete m_dialog; +} + RunConfiguration::ConfigurationState CustomExecutableRunConfiguration::ensureConfigured(QString *errorMessage) { if (m_dialog) {// uhm already shown @@ -157,7 +219,7 @@ RunConfiguration::ConfigurationState CustomExecutableRunConfiguration::ensureCon return UnConfigured; } - m_dialog = new CustomExecutableDialog(this, Core::ICore::mainWindow()); + m_dialog = new CustomExecutableDialog(this); connect(m_dialog, &QDialog::finished, this, &CustomExecutableRunConfiguration::configurationDialogFinished); m_dialog->setWindowTitle(displayName()); // pretty pointless @@ -174,95 +236,42 @@ void CustomExecutableRunConfiguration::configurationDialogFinished() emit configurationFinished(); } -// Search the executable in the path. -bool CustomExecutableRunConfiguration::validateExecutable(QString *executable, QString *errorMessage) const -{ - if (executable) - executable->clear(); - if (m_executable.isEmpty()) { - if (errorMessage) - *errorMessage = tr("No executable."); - return false; - } - Utils::Environment env; - EnvironmentAspect *aspect = extraAspect<EnvironmentAspect>(); - if (aspect) - env = aspect->environment(); - const Utils::FileName exec = env.searchInPath(macroExpander()->expand(m_executable), - {extraAspect<WorkingDirectoryAspect>()->workingDirectory()}); - if (exec.isEmpty()) { - if (errorMessage) - *errorMessage = tr("The executable\n%1\ncannot be found in the path."). - arg(QDir::toNativeSeparators(m_executable)); - return false; - } - if (executable) - *executable = exec.toString(); - return true; -} - -QString CustomExecutableRunConfiguration::executable() const -{ - QString result; - validateExecutable(&result); - return result; -} - QString CustomExecutableRunConfiguration::rawExecutable() const { - return m_executable; + return extraAspect<ExecutableAspect>()->executable().toString(); } bool CustomExecutableRunConfiguration::isConfigured() const { - return !m_executable.isEmpty(); + return !rawExecutable().isEmpty(); } Runnable CustomExecutableRunConfiguration::runnable() const { + FileName workingDirectory = extraAspect<WorkingDirectoryAspect>()->workingDirectory(); + StandardRunnable r; - r.executable = executable(); + r.executable = extraAspect<ExecutableAspect>()->executable().toString(); r.commandLineArguments = extraAspect<ArgumentsAspect>()->arguments(); - r.environment = extraAspect<LocalEnvironmentAspect>()->environment(); + r.environment = extraAspect<EnvironmentAspect>()->environment(); r.runMode = extraAspect<TerminalAspect>()->runMode(); + r.workingDirectory = workingDirectory.toString(); r.device = DeviceManager::instance()->defaultDevice(Constants::DESKTOP_DEVICE_TYPE); + + if (!r.executable.isEmpty()) { + QString expanded = macroExpander()->expand(r.executable); + r.executable = r.environment.searchInPath(expanded, {workingDirectory}).toString(); + } + return r; } QString CustomExecutableRunConfiguration::defaultDisplayName() const { - if (m_executable.isEmpty()) + if (rawExecutable().isEmpty()) return tr("Custom Executable"); else - return tr("Run %1").arg(QDir::toNativeSeparators(m_executable)); -} - -QVariantMap CustomExecutableRunConfiguration::toMap() const -{ - QVariantMap map(RunConfiguration::toMap()); - map.insert(QLatin1String(EXECUTABLE_KEY), m_executable); - return map; -} - -bool CustomExecutableRunConfiguration::fromMap(const QVariantMap &map) -{ - m_executable = map.value(QLatin1String(EXECUTABLE_KEY)).toString(); - setDefaultDisplayName(defaultDisplayName()); - return RunConfiguration::fromMap(map); -} - -void CustomExecutableRunConfiguration::setExecutable(const QString &executable) -{ - if (executable == m_executable) - return; - m_executable = executable; - setDefaultDisplayName(defaultDisplayName()); - emit changed(); -} - -QWidget *CustomExecutableRunConfiguration::createConfigurationWidget() -{ - return new CustomExecutableConfigurationWidget(this, CustomExecutableConfigurationWidget::InstantApply); + return tr("Run %1").arg(QDir::toNativeSeparators(rawExecutable())); } Abi CustomExecutableRunConfiguration::abi() const @@ -279,5 +288,3 @@ CustomExecutableRunConfigurationFactory::CustomExecutableRunConfigurationFactory } } // namespace ProjectExplorer - -#include "customexecutablerunconfiguration.moc" |