forked from qt-creator/qt-creator
Fix error handling for custom executables.
Prevent dialog showing "No executable" when canceling the prompt for the executable when pressing 'Run' / 'Debug' on a library project. Introduce new LocalApplicationRunControl::ensureConfigured() to ensure the configuration is complete and detect cancel via empty/non-null strings. Change-Id: I9bd4a296e7c995d26d6ad265519e7ebd3f98d6fe Reviewed-by: Tobias Hunger <tobias.hunger@digia.com> Reviewed-by: Daniel Teske <daniel.teske@digia.com>
This commit is contained in:
committed by
Daniel Teske
parent
1035224774
commit
fe2dd584fc
@@ -478,6 +478,8 @@ static DebuggerStartParameters localStartParameters(RunConfiguration *runConfigu
|
|||||||
LocalApplicationRunConfiguration *rc =
|
LocalApplicationRunConfiguration *rc =
|
||||||
qobject_cast<LocalApplicationRunConfiguration *>(runConfiguration);
|
qobject_cast<LocalApplicationRunConfiguration *>(runConfiguration);
|
||||||
QTC_ASSERT(rc, return sp);
|
QTC_ASSERT(rc, return sp);
|
||||||
|
if (!rc->ensureConfigured(errorMessage))
|
||||||
|
return sp;
|
||||||
|
|
||||||
Target *target = runConfiguration->target();
|
Target *target = runConfiguration->target();
|
||||||
Kit *kit = target ? target->kit() : KitManager::instance()->defaultKit();
|
Kit *kit = target ? target->kit() : KitManager::instance()->defaultKit();
|
||||||
@@ -541,7 +543,6 @@ static DebuggerStartParameters localStartParameters(RunConfiguration *runConfigu
|
|||||||
RunControl *DebuggerRunControlFactory::create
|
RunControl *DebuggerRunControlFactory::create
|
||||||
(RunConfiguration *runConfiguration, RunMode mode, QString *errorMessage)
|
(RunConfiguration *runConfiguration, RunMode mode, QString *errorMessage)
|
||||||
{
|
{
|
||||||
Q_UNUSED(errorMessage)
|
|
||||||
QTC_ASSERT(mode == DebugRunMode || mode == DebugRunModeWithBreakOnMain, return 0);
|
QTC_ASSERT(mode == DebugRunMode || mode == DebugRunModeWithBreakOnMain, return 0);
|
||||||
DebuggerStartParameters sp = localStartParameters(runConfiguration, errorMessage);
|
DebuggerStartParameters sp = localStartParameters(runConfiguration, errorMessage);
|
||||||
if (sp.startMode == NoStartMode)
|
if (sp.startMode == NoStartMode)
|
||||||
@@ -621,6 +622,9 @@ DebuggerRunControl *DebuggerRunControlFactory::createAndScheduleRun
|
|||||||
(const DebuggerStartParameters &sp, RunConfiguration *runConfiguration)
|
(const DebuggerStartParameters &sp, RunConfiguration *runConfiguration)
|
||||||
{
|
{
|
||||||
QString errorMessage;
|
QString errorMessage;
|
||||||
|
if (runConfiguration && !runConfiguration->ensureConfigured(&errorMessage))
|
||||||
|
ProjectExplorer::ProjectExplorerPlugin::showRunErrorMessage(errorMessage);
|
||||||
|
|
||||||
DebuggerRunControl *rc = doCreate(sp, runConfiguration, &errorMessage);
|
DebuggerRunControl *rc = doCreate(sp, runConfiguration, &errorMessage);
|
||||||
if (!rc) {
|
if (!rc) {
|
||||||
ProjectExplorer::ProjectExplorerPlugin::showRunErrorMessage(errorMessage);
|
ProjectExplorer::ProjectExplorerPlugin::showRunErrorMessage(errorMessage);
|
||||||
|
|||||||
@@ -66,11 +66,8 @@ RunControl *LocalApplicationRunControlFactory::create(RunConfiguration *runConfi
|
|||||||
QTC_ASSERT(canRun(runConfiguration, mode), return 0);
|
QTC_ASSERT(canRun(runConfiguration, mode), return 0);
|
||||||
LocalApplicationRunConfiguration *localRunConfiguration = qobject_cast<LocalApplicationRunConfiguration *>(runConfiguration);
|
LocalApplicationRunConfiguration *localRunConfiguration = qobject_cast<LocalApplicationRunConfiguration *>(runConfiguration);
|
||||||
// Force the dialog about executables at this point and fail if there is none
|
// Force the dialog about executables at this point and fail if there is none
|
||||||
if (localRunConfiguration->executable().isEmpty()) {
|
if (!localRunConfiguration->ensureConfigured(errorMessage))
|
||||||
if (errorMessage)
|
|
||||||
*errorMessage = tr("No executable");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
return new LocalApplicationRunControl(localRunConfiguration, mode);
|
return new LocalApplicationRunControl(localRunConfiguration, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1565,10 +1565,14 @@ void ProjectExplorerPlugin::buildStateChanged(Project * pro)
|
|||||||
|
|
||||||
void ProjectExplorerPlugin::executeRunConfiguration(RunConfiguration *runConfiguration, RunMode runMode)
|
void ProjectExplorerPlugin::executeRunConfiguration(RunConfiguration *runConfiguration, RunMode runMode)
|
||||||
{
|
{
|
||||||
|
QString errorMessage;
|
||||||
|
if (!runConfiguration->ensureConfigured(&errorMessage)) {
|
||||||
|
showRunErrorMessage(errorMessage);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (IRunControlFactory *runControlFactory = findRunControlFactory(runConfiguration, runMode)) {
|
if (IRunControlFactory *runControlFactory = findRunControlFactory(runConfiguration, runMode)) {
|
||||||
emit aboutToExecuteProject(runConfiguration->target()->project(), runMode);
|
emit aboutToExecuteProject(runConfiguration->target()->project(), runMode);
|
||||||
|
|
||||||
QString errorMessage;
|
|
||||||
RunControl *control = runControlFactory->create(runConfiguration, runMode, &errorMessage);
|
RunControl *control = runControlFactory->create(runConfiguration, runMode, &errorMessage);
|
||||||
if (!control) {
|
if (!control) {
|
||||||
showRunErrorMessage(errorMessage);
|
showRunErrorMessage(errorMessage);
|
||||||
|
|||||||
@@ -322,6 +322,16 @@ bool RunConfiguration::isConfigured() const
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RunConfiguration::ensureConfigured(QString *errorMessage)
|
||||||
|
{
|
||||||
|
if (isConfigured())
|
||||||
|
return true;
|
||||||
|
if (errorMessage)
|
||||||
|
*errorMessage = tr("Unknown error.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\fn virtual QWidget *ProjectExplorer::RunConfiguration::createConfigurationWidget()
|
\fn virtual QWidget *ProjectExplorer::RunConfiguration::createConfigurationWidget()
|
||||||
|
|
||||||
|
|||||||
@@ -151,6 +151,8 @@ public:
|
|||||||
virtual QString disabledReason() const;
|
virtual QString disabledReason() const;
|
||||||
virtual QWidget *createConfigurationWidget() = 0;
|
virtual QWidget *createConfigurationWidget() = 0;
|
||||||
virtual bool isConfigured() const;
|
virtual bool isConfigured() const;
|
||||||
|
// Pop up configuration dialog in case for example the executable is missing.
|
||||||
|
virtual bool ensureConfigured(QString *errorMessage = 0);
|
||||||
|
|
||||||
Target *target() const;
|
Target *target() const;
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,7 @@
|
|||||||
|
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include <QDialogButtonBox>
|
#include <QDialogButtonBox>
|
||||||
|
#include <QPushButton>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
@@ -119,51 +120,106 @@ void CustomExecutableRunConfiguration::activeBuildConfigurationChanged()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString CustomExecutableRunConfiguration::executable() const
|
// Dialog embedding the CustomExecutableConfigurationWidget
|
||||||
|
// prompting the user to complete the configuration.
|
||||||
|
class CustomExecutableDialog : public QDialog
|
||||||
{
|
{
|
||||||
Utils::Environment env = environment();
|
Q_OBJECT
|
||||||
QString exec = env.searchInPath(Utils::expandMacros(m_executable, macroExpander()),
|
public:
|
||||||
QStringList() << workingDirectory());
|
explicit CustomExecutableDialog(CustomExecutableRunConfiguration *rc, QWidget *parent = 0);
|
||||||
|
|
||||||
if (exec.isEmpty() || !QFileInfo(exec).exists()) {
|
private slots:
|
||||||
// Oh the executable doesn't exists, ask the user.
|
void changed()
|
||||||
CustomExecutableRunConfiguration *that = const_cast<CustomExecutableRunConfiguration *>(this);
|
{
|
||||||
QWidget *confWidget = that->createConfigurationWidget();
|
setOkButtonEnabled(m_runConfiguration->isConfigured());
|
||||||
confWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
|
}
|
||||||
QDialog dialog(Core::ICore::mainWindow());
|
|
||||||
dialog.setWindowTitle(displayName());
|
private:
|
||||||
dialog.setWindowFlags(dialog.windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
inline void setOkButtonEnabled(bool e)
|
||||||
dialog.setLayout(new QVBoxLayout());
|
{
|
||||||
|
m_dialogButtonBox->button(QDialogButtonBox::Ok)->setEnabled(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
QDialogButtonBox *m_dialogButtonBox;
|
||||||
|
CustomExecutableRunConfiguration *m_runConfiguration;
|
||||||
|
};
|
||||||
|
|
||||||
|
CustomExecutableDialog::CustomExecutableDialog(CustomExecutableRunConfiguration *rc, QWidget *parent)
|
||||||
|
: QDialog(parent)
|
||||||
|
, m_dialogButtonBox(new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel))
|
||||||
|
, m_runConfiguration(rc)
|
||||||
|
{
|
||||||
|
connect(rc, SIGNAL(changed()), this, SLOT(changed()));
|
||||||
|
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||||
|
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||||
QLabel *label = new QLabel(tr("Could not find the executable, please specify one."));
|
QLabel *label = new QLabel(tr("Could not find the executable, please specify one."));
|
||||||
label->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
|
label->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
|
||||||
dialog.layout()->addWidget(label);
|
layout->addWidget(label);
|
||||||
dialog.layout()->addWidget(confWidget);
|
QWidget *configWidget = rc->createConfigurationWidget();
|
||||||
QDialogButtonBox *dbb = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
configWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
|
||||||
connect(dbb, SIGNAL(accepted()), &dialog, SLOT(accept()));
|
layout->addWidget(configWidget);
|
||||||
connect(dbb, SIGNAL(rejected()), &dialog, SLOT(reject()));
|
setOkButtonEnabled(false);
|
||||||
dialog.layout()->addWidget(dbb);
|
connect(m_dialogButtonBox, SIGNAL(accepted()), this, SLOT(accept()));
|
||||||
dialog.layout()->setSizeConstraint(QLayout::SetMinAndMaxSize);
|
connect(m_dialogButtonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
||||||
|
layout->addWidget(m_dialogButtonBox);
|
||||||
|
layout->setSizeConstraint(QLayout::SetMinAndMaxSize);
|
||||||
|
}
|
||||||
|
|
||||||
QString oldExecutable = m_executable;
|
bool CustomExecutableRunConfiguration::ensureConfigured(QString *errorMessage)
|
||||||
QString oldWorkingDirectory = m_workingDirectory;
|
{
|
||||||
QString oldCmdArguments = m_cmdArguments;
|
if (isConfigured())
|
||||||
|
return validateExecutable(0, errorMessage);
|
||||||
if (dialog.exec() == QDialog::Accepted) {
|
CustomExecutableDialog dialog(this, Core::ICore::mainWindow());
|
||||||
return executable();
|
dialog.setWindowTitle(displayName());
|
||||||
} else {
|
const QString oldExecutable = m_executable;
|
||||||
|
const QString oldWorkingDirectory = m_workingDirectory;
|
||||||
|
const QString oldCmdArguments = m_cmdArguments;
|
||||||
|
if (dialog.exec() == QDialog::Accepted)
|
||||||
|
return validateExecutable(0, errorMessage);
|
||||||
|
// User canceled: Hack: Silence the error dialog.
|
||||||
|
if (errorMessage)
|
||||||
|
*errorMessage = QLatin1String("");
|
||||||
// Restore values changed by the configuration widget.
|
// Restore values changed by the configuration widget.
|
||||||
if (that->m_executable != oldExecutable
|
if (m_executable != oldExecutable
|
||||||
|| that->m_workingDirectory != oldWorkingDirectory
|
|| m_workingDirectory != oldWorkingDirectory
|
||||||
|| that->m_cmdArguments != oldCmdArguments) {
|
|| m_cmdArguments != oldCmdArguments) {
|
||||||
that->m_executable = oldExecutable;
|
m_executable = oldExecutable;
|
||||||
that->m_workingDirectory = oldWorkingDirectory;
|
m_workingDirectory = oldWorkingDirectory;
|
||||||
that->m_cmdArguments = oldCmdArguments;
|
m_cmdArguments = oldCmdArguments;
|
||||||
emit that->changed();
|
emit changed();
|
||||||
}
|
}
|
||||||
return QString();
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
}
|
}
|
||||||
return QDir::cleanPath(exec);
|
const Utils::Environment env = environment();
|
||||||
|
const QString exec = env.searchInPath(Utils::expandMacros(m_executable, macroExpander()),
|
||||||
|
QStringList(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 = QDir::cleanPath(exec);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CustomExecutableRunConfiguration::executable() const
|
||||||
|
{
|
||||||
|
QString result;
|
||||||
|
validateExecutable(&result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString CustomExecutableRunConfiguration::rawExecutable() const
|
QString CustomExecutableRunConfiguration::rawExecutable() const
|
||||||
@@ -426,3 +482,5 @@ QString CustomExecutableRunConfigurationFactory::displayNameForId(const Core::Id
|
|||||||
return tr("Custom Executable");
|
return tr("Custom Executable");
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "customexecutablerunconfiguration.moc"
|
||||||
|
|||||||
@@ -80,6 +80,8 @@ public:
|
|||||||
|
|
||||||
QVariantMap toMap() const;
|
QVariantMap toMap() const;
|
||||||
|
|
||||||
|
bool ensureConfigured(QString *errorMessage);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void changed();
|
void changed();
|
||||||
|
|
||||||
@@ -116,6 +118,7 @@ private:
|
|||||||
QString baseWorkingDirectory() const;
|
QString baseWorkingDirectory() const;
|
||||||
void setUserName(const QString &name);
|
void setUserName(const QString &name);
|
||||||
void setRunMode(ProjectExplorer::LocalApplicationRunConfiguration::RunMode runMode);
|
void setRunMode(ProjectExplorer::LocalApplicationRunConfiguration::RunMode runMode);
|
||||||
|
bool validateExecutable(QString *executable = 0, QString *errorMessage = 0) const;
|
||||||
|
|
||||||
QString m_executable;
|
QString m_executable;
|
||||||
QString m_workingDirectory;
|
QString m_workingDirectory;
|
||||||
|
|||||||
Reference in New Issue
Block a user