forked from qt-creator/qt-creator
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>
This commit is contained in:
@@ -1,171 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
**
|
|
||||||
** Copyright (C) 2016 The Qt Company Ltd.
|
|
||||||
** Contact: https://www.qt.io/licensing/
|
|
||||||
**
|
|
||||||
** This file is part of Qt Creator.
|
|
||||||
**
|
|
||||||
** Commercial License Usage
|
|
||||||
** Licensees holding valid commercial Qt licenses may use this file in
|
|
||||||
** accordance with the commercial license agreement provided with the
|
|
||||||
** Software or, alternatively, in accordance with the terms contained in
|
|
||||||
** a written agreement between you and The Qt Company. For licensing terms
|
|
||||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
||||||
** information use the contact form at https://www.qt.io/contact-us.
|
|
||||||
**
|
|
||||||
** GNU General Public License Usage
|
|
||||||
** Alternatively, this file may be used under the terms of the GNU
|
|
||||||
** General Public License version 3 as published by the Free Software
|
|
||||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
|
||||||
** included in the packaging of this file. Please review the following
|
|
||||||
** information to ensure the GNU General Public License requirements will
|
|
||||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
|
||||||
**
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#include "customexecutableconfigurationwidget.h"
|
|
||||||
|
|
||||||
#include "customexecutablerunconfiguration.h"
|
|
||||||
#include "environmentaspect.h"
|
|
||||||
#include "project.h"
|
|
||||||
#include "runconfigurationaspects.h"
|
|
||||||
#include "target.h"
|
|
||||||
|
|
||||||
#include <coreplugin/variablechooser.h>
|
|
||||||
#include <utils/detailswidget.h>
|
|
||||||
#include <utils/pathchooser.h>
|
|
||||||
|
|
||||||
#include <QCheckBox>
|
|
||||||
#include <QComboBox>
|
|
||||||
#include <QFormLayout>
|
|
||||||
#include <QHBoxLayout>
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QLineEdit>
|
|
||||||
|
|
||||||
using namespace Utils;
|
|
||||||
|
|
||||||
namespace ProjectExplorer {
|
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
CustomExecutableConfigurationWidget::CustomExecutableConfigurationWidget(CustomExecutableRunConfiguration *rc, ApplyMode mode)
|
|
||||||
: m_runConfiguration(rc)
|
|
||||||
{
|
|
||||||
auto layout = new QFormLayout;
|
|
||||||
layout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
|
|
||||||
layout->setMargin(0);
|
|
||||||
|
|
||||||
m_executableChooser = new PathChooser(this);
|
|
||||||
m_executableChooser->setHistoryCompleter(QLatin1String("Qt.CustomExecutable.History"));
|
|
||||||
m_executableChooser->setExpectedKind(PathChooser::ExistingCommand);
|
|
||||||
layout->addRow(tr("Executable:"), m_executableChooser);
|
|
||||||
|
|
||||||
auto argumentsAspect = rc->extraAspect<ArgumentsAspect>();
|
|
||||||
auto workingDirectoryAspect = rc->extraAspect<WorkingDirectoryAspect>();
|
|
||||||
auto terminalAspect = rc->extraAspect<TerminalAspect>();
|
|
||||||
if (mode == InstantApply) {
|
|
||||||
argumentsAspect->addToConfigurationLayout(layout);
|
|
||||||
workingDirectoryAspect->addToConfigurationLayout(layout);
|
|
||||||
terminalAspect->addToConfigurationLayout(layout);
|
|
||||||
} else {
|
|
||||||
m_temporaryArgumentsAspect = new ArgumentsAspect(rc, QString());
|
|
||||||
m_temporaryArgumentsAspect->copyFrom(argumentsAspect);
|
|
||||||
m_temporaryArgumentsAspect->addToConfigurationLayout(layout);
|
|
||||||
connect(m_temporaryArgumentsAspect, &ArgumentsAspect::argumentsChanged,
|
|
||||||
this, &CustomExecutableConfigurationWidget::validChanged);
|
|
||||||
|
|
||||||
m_temporaryWorkingDirectoryAspect = new WorkingDirectoryAspect(rc, QString());
|
|
||||||
m_temporaryWorkingDirectoryAspect->copyFrom(workingDirectoryAspect);
|
|
||||||
m_temporaryArgumentsAspect->addToConfigurationLayout(layout);
|
|
||||||
|
|
||||||
m_temporaryTerminalAspect = new TerminalAspect(rc, QString());
|
|
||||||
m_temporaryTerminalAspect->copyFrom(terminalAspect);
|
|
||||||
m_temporaryTerminalAspect->addToConfigurationLayout(layout);
|
|
||||||
connect(m_temporaryTerminalAspect, &TerminalAspect::useTerminalChanged,
|
|
||||||
this, &CustomExecutableConfigurationWidget::validChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto vbox = new QVBoxLayout(this);
|
|
||||||
vbox->setMargin(0);
|
|
||||||
|
|
||||||
m_detailsContainer = new DetailsWidget(this);
|
|
||||||
m_detailsContainer->setState(DetailsWidget::NoSummary);
|
|
||||||
vbox->addWidget(m_detailsContainer);
|
|
||||||
|
|
||||||
auto detailsWidget = new QWidget(m_detailsContainer);
|
|
||||||
m_detailsContainer->setWidget(detailsWidget);
|
|
||||||
detailsWidget->setLayout(layout);
|
|
||||||
|
|
||||||
changed();
|
|
||||||
|
|
||||||
if (mode == InstantApply) {
|
|
||||||
connect(m_executableChooser, &PathChooser::rawPathChanged,
|
|
||||||
this, &CustomExecutableConfigurationWidget::executableEdited);
|
|
||||||
} else {
|
|
||||||
connect(m_executableChooser, &PathChooser::rawPathChanged,
|
|
||||||
this, &CustomExecutableConfigurationWidget::validChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto enviromentAspect = rc->extraAspect<EnvironmentAspect>();
|
|
||||||
connect(enviromentAspect, &EnvironmentAspect::environmentChanged,
|
|
||||||
this, &CustomExecutableConfigurationWidget::environmentWasChanged);
|
|
||||||
environmentWasChanged();
|
|
||||||
|
|
||||||
// If we are in InstantApply mode, we keep us in sync with the rc
|
|
||||||
// otherwise we ignore changes to the rc and override them on apply,
|
|
||||||
// or keep them on cancel
|
|
||||||
if (mode == InstantApply) {
|
|
||||||
connect(m_runConfiguration, &CustomExecutableRunConfiguration::changed,
|
|
||||||
this, &CustomExecutableConfigurationWidget::changed);
|
|
||||||
}
|
|
||||||
|
|
||||||
Core::VariableChooser::addSupportForChildWidgets(this, m_runConfiguration->macroExpander());
|
|
||||||
}
|
|
||||||
|
|
||||||
CustomExecutableConfigurationWidget::~CustomExecutableConfigurationWidget()
|
|
||||||
{
|
|
||||||
delete m_temporaryArgumentsAspect;
|
|
||||||
delete m_temporaryTerminalAspect;
|
|
||||||
delete m_temporaryWorkingDirectoryAspect;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CustomExecutableConfigurationWidget::environmentWasChanged()
|
|
||||||
{
|
|
||||||
auto aspect = m_runConfiguration->extraAspect<EnvironmentAspect>();
|
|
||||||
QTC_ASSERT(aspect, return);
|
|
||||||
m_executableChooser->setEnvironment(aspect->environment());
|
|
||||||
}
|
|
||||||
|
|
||||||
void CustomExecutableConfigurationWidget::executableEdited()
|
|
||||||
{
|
|
||||||
m_ignoreChange = true;
|
|
||||||
m_runConfiguration->setExecutable(m_executableChooser->rawPath());
|
|
||||||
m_ignoreChange = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CustomExecutableConfigurationWidget::changed()
|
|
||||||
{
|
|
||||||
// We triggered the change, don't update us
|
|
||||||
if (m_ignoreChange)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_executableChooser->setPath(m_runConfiguration->rawExecutable());
|
|
||||||
}
|
|
||||||
|
|
||||||
void CustomExecutableConfigurationWidget::apply()
|
|
||||||
{
|
|
||||||
m_ignoreChange = true;
|
|
||||||
m_runConfiguration->setExecutable(m_executableChooser->rawPath());
|
|
||||||
m_runConfiguration->extraAspect<WorkingDirectoryAspect>()
|
|
||||||
->copyFrom(m_temporaryWorkingDirectoryAspect);
|
|
||||||
m_runConfiguration->extraAspect<ArgumentsAspect>()->copyFrom(m_temporaryArgumentsAspect);
|
|
||||||
m_runConfiguration->extraAspect<TerminalAspect>()->copyFrom(m_temporaryTerminalAspect);
|
|
||||||
m_ignoreChange = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CustomExecutableConfigurationWidget::isValid() const
|
|
||||||
{
|
|
||||||
return !m_executableChooser->rawPath().isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Internal
|
|
||||||
} // namespace ProjectExplorer
|
|
@@ -1,82 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
**
|
|
||||||
** Copyright (C) 2016 The Qt Company Ltd.
|
|
||||||
** Contact: https://www.qt.io/licensing/
|
|
||||||
**
|
|
||||||
** This file is part of Qt Creator.
|
|
||||||
**
|
|
||||||
** Commercial License Usage
|
|
||||||
** Licensees holding valid commercial Qt licenses may use this file in
|
|
||||||
** accordance with the commercial license agreement provided with the
|
|
||||||
** Software or, alternatively, in accordance with the terms contained in
|
|
||||||
** a written agreement between you and The Qt Company. For licensing terms
|
|
||||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
||||||
** information use the contact form at https://www.qt.io/contact-us.
|
|
||||||
**
|
|
||||||
** GNU General Public License Usage
|
|
||||||
** Alternatively, this file may be used under the terms of the GNU
|
|
||||||
** General Public License version 3 as published by the Free Software
|
|
||||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
|
||||||
** included in the packaging of this file. Please review the following
|
|
||||||
** information to ensure the GNU General Public License requirements will
|
|
||||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
|
||||||
**
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
|
||||||
class QCheckBox;
|
|
||||||
class QLineEdit;
|
|
||||||
class QComboBox;
|
|
||||||
class QLabel;
|
|
||||||
class QAbstractButton;
|
|
||||||
QT_END_NAMESPACE
|
|
||||||
|
|
||||||
namespace Utils {
|
|
||||||
class DetailsWidget;
|
|
||||||
class PathChooser;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace ProjectExplorer {
|
|
||||||
|
|
||||||
class ArgumentsAspect;
|
|
||||||
class TerminalAspect;
|
|
||||||
class WorkingDirectoryAspect;
|
|
||||||
class CustomExecutableRunConfiguration;
|
|
||||||
|
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
class CustomExecutableConfigurationWidget : public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
enum ApplyMode { InstantApply, DelayedApply};
|
|
||||||
CustomExecutableConfigurationWidget(CustomExecutableRunConfiguration *rc, ApplyMode mode);
|
|
||||||
~CustomExecutableConfigurationWidget();
|
|
||||||
|
|
||||||
void apply(); // only used for DelayedApply
|
|
||||||
bool isValid() const;
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void validChanged();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void changed();
|
|
||||||
void executableEdited();
|
|
||||||
void environmentWasChanged();
|
|
||||||
|
|
||||||
bool m_ignoreChange = false;
|
|
||||||
CustomExecutableRunConfiguration *m_runConfiguration = 0;
|
|
||||||
ProjectExplorer::ArgumentsAspect *m_temporaryArgumentsAspect = 0;
|
|
||||||
ProjectExplorer::TerminalAspect *m_temporaryTerminalAspect = 0;
|
|
||||||
ProjectExplorer::WorkingDirectoryAspect *m_temporaryWorkingDirectoryAspect = 0;
|
|
||||||
Utils::PathChooser *m_executableChooser = 0;
|
|
||||||
Utils::DetailsWidget *m_detailsContainer = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Internal
|
|
||||||
} // namespace ProjectExplorer
|
|
@@ -27,110 +27,125 @@
|
|||||||
|
|
||||||
#include "abi.h"
|
#include "abi.h"
|
||||||
#include "buildconfiguration.h"
|
#include "buildconfiguration.h"
|
||||||
#include "customexecutableconfigurationwidget.h"
|
|
||||||
#include "devicesupport/devicemanager.h"
|
#include "devicesupport/devicemanager.h"
|
||||||
|
#include "environmentaspect.h"
|
||||||
#include "localenvironmentaspect.h"
|
#include "localenvironmentaspect.h"
|
||||||
#include "project.h"
|
#include "project.h"
|
||||||
#include "runconfigurationaspects.h"
|
#include "runconfigurationaspects.h"
|
||||||
#include "target.h"
|
#include "target.h"
|
||||||
|
|
||||||
#include <coreplugin/icore.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 <utils/stringutils.h>
|
||||||
|
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include <QDialogButtonBox>
|
#include <QDialogButtonBox>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
#include <QFormLayout>
|
||||||
#include <QKeyEvent>
|
#include <QKeyEvent>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
|
#include <QLineEdit>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
using namespace ProjectExplorer::Internal;
|
using namespace Utils;
|
||||||
|
|
||||||
namespace ProjectExplorer {
|
namespace ProjectExplorer {
|
||||||
|
|
||||||
const char CUSTOM_EXECUTABLE_ID[] = "ProjectExplorer.CustomExecutableRunConfiguration";
|
const char CUSTOM_EXECUTABLE_ID[] = "ProjectExplorer.CustomExecutableRunConfiguration";
|
||||||
const char EXECUTABLE_KEY[] = "ProjectExplorer.CustomExecutableRunConfiguration.Executable";
|
|
||||||
|
|
||||||
// Dialog embedding the CustomExecutableConfigurationWidget
|
// Dialog prompting the user to complete the configuration.
|
||||||
// prompting the user to complete the configuration.
|
|
||||||
class CustomExecutableDialog : public QDialog
|
class CustomExecutableDialog : public QDialog
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
|
||||||
public:
|
public:
|
||||||
explicit CustomExecutableDialog(CustomExecutableRunConfiguration *rc, QWidget *parent = 0);
|
explicit CustomExecutableDialog(RunConfiguration *rc);
|
||||||
|
|
||||||
void accept();
|
void accept() override;
|
||||||
|
bool event(QEvent *event) override;
|
||||||
bool event(QEvent *event);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void changed()
|
void changed() {
|
||||||
{
|
bool isValid = !m_executableChooser->rawPath().isEmpty();
|
||||||
setOkButtonEnabled(m_widget->isValid());
|
m_dialogButtonBox->button(QDialogButtonBox::Ok)->setEnabled(isValid);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void setOkButtonEnabled(bool e)
|
private:
|
||||||
{
|
void environmentWasChanged();
|
||||||
m_dialogButtonBox->button(QDialogButtonBox::Ok)->setEnabled(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
QDialogButtonBox *m_dialogButtonBox;
|
QDialogButtonBox *m_dialogButtonBox = nullptr;
|
||||||
CustomExecutableConfigurationWidget *m_widget;
|
RunConfiguration *m_rc = nullptr;
|
||||||
|
ArgumentsAspect m_arguments;
|
||||||
|
WorkingDirectoryAspect m_workingDirectory;
|
||||||
|
TerminalAspect m_terminal;
|
||||||
|
PathChooser *m_executableChooser = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
CustomExecutableRunConfiguration::CustomExecutableRunConfiguration(Target *target, Core::Id id)
|
CustomExecutableDialog::CustomExecutableDialog(RunConfiguration *rc)
|
||||||
: RunConfiguration(target, id)
|
: 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()));
|
auto vbox = new QVBoxLayout(this);
|
||||||
addExtraAspect(new ArgumentsAspect(this, "ProjectExplorer.CustomExecutableRunConfiguration.Arguments"));
|
vbox->addWidget(new QLabel(tr("Could not find the executable, please specify one.")));
|
||||||
addExtraAspect(new TerminalAspect(this, "ProjectExplorer.CustomExecutableRunConfiguration.UseTerminal"));
|
|
||||||
addExtraAspect(new WorkingDirectoryAspect(this, "ProjectExplorer.CustomExecutableRunConfiguration.WorkingDirectory"));
|
|
||||||
setDefaultDisplayName(defaultDisplayName());
|
|
||||||
}
|
|
||||||
|
|
||||||
CustomExecutableRunConfiguration::CustomExecutableRunConfiguration(Target *target)
|
auto layout = new QFormLayout;
|
||||||
: CustomExecutableRunConfiguration(target, CUSTOM_EXECUTABLE_ID)
|
layout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
|
||||||
{
|
layout->setMargin(0);
|
||||||
}
|
|
||||||
|
|
||||||
// Note: Qt4Project deletes all empty customexecrunconfigs for which isConfigured() == false.
|
auto detailsContainer = new DetailsWidget(this);
|
||||||
CustomExecutableRunConfiguration::~CustomExecutableRunConfiguration()
|
detailsContainer->setState(DetailsWidget::NoSummary);
|
||||||
{
|
vbox->addWidget(detailsContainer);
|
||||||
if (m_dialog) {
|
|
||||||
emit configurationFinished();
|
|
||||||
disconnect(m_dialog, &QDialog::finished,
|
|
||||||
this, &CustomExecutableRunConfiguration::configurationDialogFinished);
|
|
||||||
}
|
|
||||||
delete m_dialog;
|
|
||||||
}
|
|
||||||
|
|
||||||
CustomExecutableDialog::CustomExecutableDialog(CustomExecutableRunConfiguration *rc, QWidget *parent)
|
m_dialogButtonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||||
: QDialog(parent)
|
m_dialogButtonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
|
||||||
, 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);
|
|
||||||
connect(m_dialogButtonBox, &QDialogButtonBox::accepted, this, &CustomExecutableDialog::accept);
|
connect(m_dialogButtonBox, &QDialogButtonBox::accepted, this, &CustomExecutableDialog::accept);
|
||||||
connect(m_dialogButtonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
connect(m_dialogButtonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||||
layout->addWidget(m_dialogButtonBox);
|
vbox->addWidget(m_dialogButtonBox);
|
||||||
layout->setSizeConstraint(QLayout::SetMinAndMaxSize);
|
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()
|
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();
|
QDialog::accept();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,8 +161,55 @@ bool CustomExecutableDialog::event(QEvent *event)
|
|||||||
return QDialog::event(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::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)
|
RunConfiguration::ConfigurationState CustomExecutableRunConfiguration::ensureConfigured(QString *errorMessage)
|
||||||
{
|
{
|
||||||
if (m_dialog) {// uhm already shown
|
if (m_dialog) {// uhm already shown
|
||||||
@@ -157,7 +219,7 @@ RunConfiguration::ConfigurationState CustomExecutableRunConfiguration::ensureCon
|
|||||||
return UnConfigured;
|
return UnConfigured;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_dialog = new CustomExecutableDialog(this, Core::ICore::mainWindow());
|
m_dialog = new CustomExecutableDialog(this);
|
||||||
connect(m_dialog, &QDialog::finished,
|
connect(m_dialog, &QDialog::finished,
|
||||||
this, &CustomExecutableRunConfiguration::configurationDialogFinished);
|
this, &CustomExecutableRunConfiguration::configurationDialogFinished);
|
||||||
m_dialog->setWindowTitle(displayName()); // pretty pointless
|
m_dialog->setWindowTitle(displayName()); // pretty pointless
|
||||||
@@ -174,95 +236,42 @@ void CustomExecutableRunConfiguration::configurationDialogFinished()
|
|||||||
emit configurationFinished();
|
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
|
QString CustomExecutableRunConfiguration::rawExecutable() const
|
||||||
{
|
{
|
||||||
return m_executable;
|
return extraAspect<ExecutableAspect>()->executable().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CustomExecutableRunConfiguration::isConfigured() const
|
bool CustomExecutableRunConfiguration::isConfigured() const
|
||||||
{
|
{
|
||||||
return !m_executable.isEmpty();
|
return !rawExecutable().isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
Runnable CustomExecutableRunConfiguration::runnable() const
|
Runnable CustomExecutableRunConfiguration::runnable() const
|
||||||
{
|
{
|
||||||
|
FileName workingDirectory = extraAspect<WorkingDirectoryAspect>()->workingDirectory();
|
||||||
|
|
||||||
StandardRunnable r;
|
StandardRunnable r;
|
||||||
r.executable = executable();
|
r.executable = extraAspect<ExecutableAspect>()->executable().toString();
|
||||||
r.commandLineArguments = extraAspect<ArgumentsAspect>()->arguments();
|
r.commandLineArguments = extraAspect<ArgumentsAspect>()->arguments();
|
||||||
r.environment = extraAspect<LocalEnvironmentAspect>()->environment();
|
r.environment = extraAspect<EnvironmentAspect>()->environment();
|
||||||
r.runMode = extraAspect<TerminalAspect>()->runMode();
|
r.runMode = extraAspect<TerminalAspect>()->runMode();
|
||||||
|
r.workingDirectory = workingDirectory.toString();
|
||||||
r.device = DeviceManager::instance()->defaultDevice(Constants::DESKTOP_DEVICE_TYPE);
|
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;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString CustomExecutableRunConfiguration::defaultDisplayName() const
|
QString CustomExecutableRunConfiguration::defaultDisplayName() const
|
||||||
{
|
{
|
||||||
if (m_executable.isEmpty())
|
if (rawExecutable().isEmpty())
|
||||||
return tr("Custom Executable");
|
return tr("Custom Executable");
|
||||||
else
|
else
|
||||||
return tr("Run %1").arg(QDir::toNativeSeparators(m_executable));
|
return tr("Run %1").arg(QDir::toNativeSeparators(rawExecutable()));
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Abi CustomExecutableRunConfiguration::abi() const
|
Abi CustomExecutableRunConfiguration::abi() const
|
||||||
@@ -279,5 +288,3 @@ CustomExecutableRunConfigurationFactory::CustomExecutableRunConfigurationFactory
|
|||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ProjectExplorer
|
} // namespace ProjectExplorer
|
||||||
|
|
||||||
#include "customexecutablerunconfiguration.moc"
|
|
||||||
|
@@ -27,57 +27,35 @@
|
|||||||
|
|
||||||
#include "projectexplorer_global.h"
|
#include "projectexplorer_global.h"
|
||||||
|
|
||||||
|
#include "projectexplorer/runconfigurationaspects.h"
|
||||||
#include "projectexplorer/runnables.h"
|
#include "projectexplorer/runnables.h"
|
||||||
|
|
||||||
namespace ProjectExplorer {
|
namespace ProjectExplorer {
|
||||||
|
|
||||||
class CustomExecutableDialog;
|
|
||||||
|
|
||||||
namespace Internal { class CustomExecutableConfigurationWidget; }
|
|
||||||
|
|
||||||
class PROJECTEXPLORER_EXPORT CustomExecutableRunConfiguration : public RunConfiguration
|
class PROJECTEXPLORER_EXPORT CustomExecutableRunConfiguration : public RunConfiguration
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
// the configuration widget needs to setExecutable setWorkingDirectory and setCommandLineArguments
|
|
||||||
friend class Internal::CustomExecutableConfigurationWidget;
|
|
||||||
friend class ProjectExplorer::RunConfigurationFactory;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit CustomExecutableRunConfiguration(Target *target, Core::Id id);
|
CustomExecutableRunConfiguration(Target *target, Core::Id id);
|
||||||
explicit CustomExecutableRunConfiguration(Target *target);
|
explicit CustomExecutableRunConfiguration(Target *target);
|
||||||
~CustomExecutableRunConfiguration() override;
|
~CustomExecutableRunConfiguration() override;
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the executable, looks in the environment for it and might even
|
|
||||||
* ask the user if none is specified
|
|
||||||
*/
|
|
||||||
QString executable() const;
|
|
||||||
Runnable runnable() const override;
|
Runnable runnable() const override;
|
||||||
|
|
||||||
/** Returns whether this runconfiguration ever was configured with an executable
|
/** Returns whether this runconfiguration ever was configured with an executable
|
||||||
*/
|
*/
|
||||||
bool isConfigured() const override;
|
bool isConfigured() const override;
|
||||||
QWidget *createConfigurationWidget() override;
|
|
||||||
Abi abi() const override;
|
Abi abi() const override;
|
||||||
QVariantMap toMap() const override;
|
|
||||||
ConfigurationState ensureConfigured(QString *errorMessage) override;
|
ConfigurationState ensureConfigured(QString *errorMessage) override;
|
||||||
|
|
||||||
signals:
|
|
||||||
void changed();
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool fromMap(const QVariantMap &map) override;
|
|
||||||
QString defaultDisplayName() const;
|
QString defaultDisplayName() const;
|
||||||
|
|
||||||
|
private:
|
||||||
void configurationDialogFinished();
|
void configurationDialogFinished();
|
||||||
void setExecutable(const QString &executable);
|
|
||||||
QString rawExecutable() const;
|
QString rawExecutable() const;
|
||||||
void setUserName(const QString &name);
|
|
||||||
bool validateExecutable(QString *executable = 0, QString *errorMessage = 0) const;
|
|
||||||
|
|
||||||
QString m_executable;
|
class CustomExecutableDialog *m_dialog = nullptr;
|
||||||
QString m_workingDirectory;
|
|
||||||
CustomExecutableDialog *m_dialog = nullptr;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class CustomExecutableRunConfigurationFactory : public FixedRunConfigurationFactory
|
class CustomExecutableRunConfigurationFactory : public FixedRunConfigurationFactory
|
||||||
|
@@ -149,7 +149,6 @@ HEADERS += projectexplorer.h \
|
|||||||
projectexplorericons.h \
|
projectexplorericons.h \
|
||||||
projectexplorer_global.h \
|
projectexplorer_global.h \
|
||||||
extracompiler.h \
|
extracompiler.h \
|
||||||
customexecutableconfigurationwidget.h \
|
|
||||||
customexecutablerunconfiguration.h \
|
customexecutablerunconfiguration.h \
|
||||||
projectmacro.h
|
projectmacro.h
|
||||||
|
|
||||||
@@ -286,7 +285,6 @@ SOURCES += projectexplorer.cpp \
|
|||||||
waitforstopdialog.cpp \
|
waitforstopdialog.cpp \
|
||||||
projectexplorericons.cpp \
|
projectexplorericons.cpp \
|
||||||
extracompiler.cpp \
|
extracompiler.cpp \
|
||||||
customexecutableconfigurationwidget.cpp \
|
|
||||||
customexecutablerunconfiguration.cpp \
|
customexecutablerunconfiguration.cpp \
|
||||||
projectmacro.cpp
|
projectmacro.cpp
|
||||||
|
|
||||||
|
@@ -44,7 +44,6 @@ Project {
|
|||||||
"copytaskhandler.cpp", "copytaskhandler.h",
|
"copytaskhandler.cpp", "copytaskhandler.h",
|
||||||
"currentprojectfilter.cpp", "currentprojectfilter.h",
|
"currentprojectfilter.cpp", "currentprojectfilter.h",
|
||||||
"currentprojectfind.cpp", "currentprojectfind.h",
|
"currentprojectfind.cpp", "currentprojectfind.h",
|
||||||
"customexecutableconfigurationwidget.cpp", "customexecutableconfigurationwidget.h",
|
|
||||||
"customexecutablerunconfiguration.cpp", "customexecutablerunconfiguration.h",
|
"customexecutablerunconfiguration.cpp", "customexecutablerunconfiguration.h",
|
||||||
"customparser.cpp", "customparser.h",
|
"customparser.cpp", "customparser.h",
|
||||||
"customparserconfigdialog.cpp", "customparserconfigdialog.h", "customparserconfigdialog.ui",
|
"customparserconfigdialog.cpp", "customparserconfigdialog.h", "customparserconfigdialog.ui",
|
||||||
|
@@ -80,6 +80,9 @@ void TerminalAspect::fromMap(const QVariantMap &map)
|
|||||||
} else {
|
} else {
|
||||||
m_userSet = false;
|
m_userSet = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_checkBox)
|
||||||
|
m_checkBox->setChecked(m_useTerminal);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerminalAspect::toMap(QVariantMap &data) const
|
void TerminalAspect::toMap(QVariantMap &data) const
|
||||||
@@ -182,6 +185,9 @@ void WorkingDirectoryAspect::fromMap(const QVariantMap &map)
|
|||||||
|
|
||||||
if (m_workingDirectory.isEmpty())
|
if (m_workingDirectory.isEmpty())
|
||||||
m_workingDirectory = m_defaultWorkingDirectory;
|
m_workingDirectory = m_defaultWorkingDirectory;
|
||||||
|
|
||||||
|
if (m_chooser)
|
||||||
|
m_chooser->setFileName(m_workingDirectory.isEmpty() ? m_defaultWorkingDirectory : m_workingDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorkingDirectoryAspect::toMap(QVariantMap &data) const
|
void WorkingDirectoryAspect::toMap(QVariantMap &data) const
|
||||||
@@ -275,6 +281,9 @@ void ArgumentsAspect::fromMap(const QVariantMap &map)
|
|||||||
m_arguments = QtcProcess::joinArgs(args.toStringList(), OsTypeLinux);
|
m_arguments = QtcProcess::joinArgs(args.toStringList(), OsTypeLinux);
|
||||||
else
|
else
|
||||||
m_arguments = args.toString();
|
m_arguments = args.toString();
|
||||||
|
|
||||||
|
if (m_chooser)
|
||||||
|
m_chooser->setText(m_arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArgumentsAspect::toMap(QVariantMap &map) const
|
void ArgumentsAspect::toMap(QVariantMap &map) const
|
||||||
|
Reference in New Issue
Block a user