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 =
|
||||
qobject_cast<LocalApplicationRunConfiguration *>(runConfiguration);
|
||||
QTC_ASSERT(rc, return sp);
|
||||
if (!rc->ensureConfigured(errorMessage))
|
||||
return sp;
|
||||
|
||||
Target *target = runConfiguration->target();
|
||||
Kit *kit = target ? target->kit() : KitManager::instance()->defaultKit();
|
||||
@@ -541,7 +543,6 @@ static DebuggerStartParameters localStartParameters(RunConfiguration *runConfigu
|
||||
RunControl *DebuggerRunControlFactory::create
|
||||
(RunConfiguration *runConfiguration, RunMode mode, QString *errorMessage)
|
||||
{
|
||||
Q_UNUSED(errorMessage)
|
||||
QTC_ASSERT(mode == DebugRunMode || mode == DebugRunModeWithBreakOnMain, return 0);
|
||||
DebuggerStartParameters sp = localStartParameters(runConfiguration, errorMessage);
|
||||
if (sp.startMode == NoStartMode)
|
||||
@@ -621,6 +622,9 @@ DebuggerRunControl *DebuggerRunControlFactory::createAndScheduleRun
|
||||
(const DebuggerStartParameters &sp, RunConfiguration *runConfiguration)
|
||||
{
|
||||
QString errorMessage;
|
||||
if (runConfiguration && !runConfiguration->ensureConfigured(&errorMessage))
|
||||
ProjectExplorer::ProjectExplorerPlugin::showRunErrorMessage(errorMessage);
|
||||
|
||||
DebuggerRunControl *rc = doCreate(sp, runConfiguration, &errorMessage);
|
||||
if (!rc) {
|
||||
ProjectExplorer::ProjectExplorerPlugin::showRunErrorMessage(errorMessage);
|
||||
|
||||
@@ -66,11 +66,8 @@ RunControl *LocalApplicationRunControlFactory::create(RunConfiguration *runConfi
|
||||
QTC_ASSERT(canRun(runConfiguration, mode), return 0);
|
||||
LocalApplicationRunConfiguration *localRunConfiguration = qobject_cast<LocalApplicationRunConfiguration *>(runConfiguration);
|
||||
// Force the dialog about executables at this point and fail if there is none
|
||||
if (localRunConfiguration->executable().isEmpty()) {
|
||||
if (errorMessage)
|
||||
*errorMessage = tr("No executable");
|
||||
if (!localRunConfiguration->ensureConfigured(errorMessage))
|
||||
return 0;
|
||||
}
|
||||
return new LocalApplicationRunControl(localRunConfiguration, mode);
|
||||
}
|
||||
|
||||
|
||||
@@ -1565,10 +1565,14 @@ void ProjectExplorerPlugin::buildStateChanged(Project * pro)
|
||||
|
||||
void ProjectExplorerPlugin::executeRunConfiguration(RunConfiguration *runConfiguration, RunMode runMode)
|
||||
{
|
||||
QString errorMessage;
|
||||
if (!runConfiguration->ensureConfigured(&errorMessage)) {
|
||||
showRunErrorMessage(errorMessage);
|
||||
return;
|
||||
}
|
||||
if (IRunControlFactory *runControlFactory = findRunControlFactory(runConfiguration, runMode)) {
|
||||
emit aboutToExecuteProject(runConfiguration->target()->project(), runMode);
|
||||
|
||||
QString errorMessage;
|
||||
RunControl *control = runControlFactory->create(runConfiguration, runMode, &errorMessage);
|
||||
if (!control) {
|
||||
showRunErrorMessage(errorMessage);
|
||||
|
||||
@@ -322,6 +322,16 @@ bool RunConfiguration::isConfigured() const
|
||||
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()
|
||||
|
||||
|
||||
@@ -151,6 +151,8 @@ public:
|
||||
virtual QString disabledReason() const;
|
||||
virtual QWidget *createConfigurationWidget() = 0;
|
||||
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;
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
|
||||
#include <QDialog>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QPushButton>
|
||||
#include <QLabel>
|
||||
#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();
|
||||
QString exec = env.searchInPath(Utils::expandMacros(m_executable, macroExpander()),
|
||||
QStringList() << workingDirectory());
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit CustomExecutableDialog(CustomExecutableRunConfiguration *rc, QWidget *parent = 0);
|
||||
|
||||
if (exec.isEmpty() || !QFileInfo(exec).exists()) {
|
||||
// Oh the executable doesn't exists, ask the user.
|
||||
CustomExecutableRunConfiguration *that = const_cast<CustomExecutableRunConfiguration *>(this);
|
||||
QWidget *confWidget = that->createConfigurationWidget();
|
||||
confWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
|
||||
QDialog dialog(Core::ICore::mainWindow());
|
||||
dialog.setWindowTitle(displayName());
|
||||
dialog.setWindowFlags(dialog.windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
dialog.setLayout(new QVBoxLayout());
|
||||
private slots:
|
||||
void changed()
|
||||
{
|
||||
setOkButtonEnabled(m_runConfiguration->isConfigured());
|
||||
}
|
||||
|
||||
private:
|
||||
inline void setOkButtonEnabled(bool e)
|
||||
{
|
||||
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."));
|
||||
label->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
|
||||
dialog.layout()->addWidget(label);
|
||||
dialog.layout()->addWidget(confWidget);
|
||||
QDialogButtonBox *dbb = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
connect(dbb, SIGNAL(accepted()), &dialog, SLOT(accept()));
|
||||
connect(dbb, SIGNAL(rejected()), &dialog, SLOT(reject()));
|
||||
dialog.layout()->addWidget(dbb);
|
||||
dialog.layout()->setSizeConstraint(QLayout::SetMinAndMaxSize);
|
||||
layout->addWidget(label);
|
||||
QWidget *configWidget = rc->createConfigurationWidget();
|
||||
configWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
|
||||
layout->addWidget(configWidget);
|
||||
setOkButtonEnabled(false);
|
||||
connect(m_dialogButtonBox, SIGNAL(accepted()), this, SLOT(accept()));
|
||||
connect(m_dialogButtonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
||||
layout->addWidget(m_dialogButtonBox);
|
||||
layout->setSizeConstraint(QLayout::SetMinAndMaxSize);
|
||||
}
|
||||
|
||||
QString oldExecutable = m_executable;
|
||||
QString oldWorkingDirectory = m_workingDirectory;
|
||||
QString oldCmdArguments = m_cmdArguments;
|
||||
|
||||
if (dialog.exec() == QDialog::Accepted) {
|
||||
return executable();
|
||||
} else {
|
||||
bool CustomExecutableRunConfiguration::ensureConfigured(QString *errorMessage)
|
||||
{
|
||||
if (isConfigured())
|
||||
return validateExecutable(0, errorMessage);
|
||||
CustomExecutableDialog dialog(this, Core::ICore::mainWindow());
|
||||
dialog.setWindowTitle(displayName());
|
||||
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.
|
||||
if (that->m_executable != oldExecutable
|
||||
|| that->m_workingDirectory != oldWorkingDirectory
|
||||
|| that->m_cmdArguments != oldCmdArguments) {
|
||||
that->m_executable = oldExecutable;
|
||||
that->m_workingDirectory = oldWorkingDirectory;
|
||||
that->m_cmdArguments = oldCmdArguments;
|
||||
emit that->changed();
|
||||
if (m_executable != oldExecutable
|
||||
|| m_workingDirectory != oldWorkingDirectory
|
||||
|| m_cmdArguments != oldCmdArguments) {
|
||||
m_executable = oldExecutable;
|
||||
m_workingDirectory = oldWorkingDirectory;
|
||||
m_cmdArguments = oldCmdArguments;
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
return QDir::cleanPath(exec);
|
||||
if (executable)
|
||||
*executable = QDir::cleanPath(exec);
|
||||
return true;
|
||||
}
|
||||
|
||||
QString CustomExecutableRunConfiguration::executable() const
|
||||
{
|
||||
QString result;
|
||||
validateExecutable(&result);
|
||||
return result;
|
||||
}
|
||||
|
||||
QString CustomExecutableRunConfiguration::rawExecutable() const
|
||||
@@ -426,3 +482,5 @@ QString CustomExecutableRunConfigurationFactory::displayNameForId(const Core::Id
|
||||
return tr("Custom Executable");
|
||||
return QString();
|
||||
}
|
||||
|
||||
#include "customexecutablerunconfiguration.moc"
|
||||
|
||||
@@ -80,6 +80,8 @@ public:
|
||||
|
||||
QVariantMap toMap() const;
|
||||
|
||||
bool ensureConfigured(QString *errorMessage);
|
||||
|
||||
signals:
|
||||
void changed();
|
||||
|
||||
@@ -116,6 +118,7 @@ private:
|
||||
QString baseWorkingDirectory() const;
|
||||
void setUserName(const QString &name);
|
||||
void setRunMode(ProjectExplorer::LocalApplicationRunConfiguration::RunMode runMode);
|
||||
bool validateExecutable(QString *executable = 0, QString *errorMessage = 0) const;
|
||||
|
||||
QString m_executable;
|
||||
QString m_workingDirectory;
|
||||
|
||||
Reference in New Issue
Block a user