diff --git a/src/plugins/debugger/attachcoredialog.ui b/src/plugins/debugger/attachcoredialog.ui index 6fa4f764d94610df9332d85f594c9cfa9728ff2d..7a0dae8167461321ca92918a2f699497cfcfa920 100644 --- a/src/plugins/debugger/attachcoredialog.ui +++ b/src/plugins/debugger/attachcoredialog.ui @@ -2,14 +2,6 @@ <ui version="4.0"> <class>AttachCoreDialog</class> <widget class="QDialog" name="AttachCoreDialog"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>567</width> - <height>126</height> - </rect> - </property> <property name="windowTitle"> <string>Start Debugger</string> </property> @@ -21,32 +13,54 @@ <number>9</number> </property> <item> - <layout class="QGridLayout"> - <property name="margin"> - <number>0</number> + <layout class="QFormLayout" name="formLayout"> + <property name="horizontalSpacing"> + <number>6</number> </property> - <property name="spacing"> + <property name="verticalSpacing"> <number>6</number> </property> + <property name="margin"> + <number>0</number> + </property> <item row="0" column="0"> <widget class="QLabel" name="execLabel"> <property name="text"> - <string>Executable:</string> + <string>&Executable:</string> + </property> + <property name="buddy"> + <cstring>execFileName</cstring> </property> </widget> </item> + <item row="0" column="1"> + <widget class="Utils::PathChooser" name="execFileName"/> + </item> <item row="1" column="0"> <widget class="QLabel" name="coreLabel"> <property name="text"> - <string>Core file:</string> + <string>&Core file:</string> + </property> + <property name="buddy"> + <cstring>coreFileName</cstring> </property> </widget> </item> - <item row="0" column="1"> - <widget class="Utils::PathChooser" name="execFileName" native="true"/> - </item> <item row="1" column="1"> - <widget class="Utils::PathChooser" name="coreFileName" native="true"/> + <widget class="Utils::PathChooser" name="coreFileName"/> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="toolchainLabel"> + <property name="text"> + <string>&Toolchain:</string> + </property> + <property name="buddy"> + <cstring>toolchainComboBox</cstring> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="Debugger::Internal::DebuggerToolChainComboBox" name="toolchainComboBox"/> </item> </layout> </item> @@ -57,8 +71,8 @@ </property> <property name="sizeHint" stdset="0"> <size> - <width>407</width> - <height>16</height> + <width>0</width> + <height>0</height> </size> </property> </spacer> @@ -89,6 +103,11 @@ <header location="global">utils/pathchooser.h</header> <container>1</container> </customwidget> + <customwidget> + <class>DebuggerToolChainComboBox</class> + <extends>QComboBox</extends> + <header>debuggertoolchaincombobox.h</header> + </customwidget> </customwidgets> <resources/> <connections/> diff --git a/src/plugins/debugger/attachexternaldialog.ui b/src/plugins/debugger/attachexternaldialog.ui index 5e157a2f3ceffb0fc645c320c4843035173ae0bc..b68122cabe2d0f114c84c555eb0333dd3ee506d0 100644 --- a/src/plugins/debugger/attachexternaldialog.ui +++ b/src/plugins/debugger/attachexternaldialog.ui @@ -28,16 +28,32 @@ <item row="0" column="0"> <widget class="QLabel" name="pidLabel"> <property name="text"> - <string>Attach to process ID:</string> + <string>Attach to &process ID:</string> + </property> + <property name="buddy"> + <cstring>pidLineEdit</cstring> </property> </widget> </item> <item row="0" column="1"> <widget class="QLineEdit" name="pidLineEdit"/> </item> - <item row="1" column="0" colspan="2"> + <item row="2" column="0" colspan="2"> <widget class="Utils::FilterLineEdit" name="filterWidget"/> </item> + <item row="1" column="0"> + <widget class="QLabel" name="toolchainLabel"> + <property name="text"> + <string>&Toolchain:</string> + </property> + <property name="buddy"> + <cstring>toolchainComboBox</cstring> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="Debugger::Internal::DebuggerToolChainComboBox" name="toolchainComboBox"/> + </item> </layout> </item> <item> @@ -77,6 +93,11 @@ <extends>Utils::FancyLineEdit</extends> <header location="global">utils/filterlineedit.h</header> </customwidget> + <customwidget> + <class>Debugger::Internal::DebuggerToolChainComboBox</class> + <extends>QComboBox</extends> + <header>debuggertoolchaincombobox.h</header> + </customwidget> </customwidgets> <resources/> <connections/> diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp index 1538dc191c840e07c2408b1048dc9fd4ec3e02d0..771bf6f65c26a99ad32d166fbeef588f24781f37 100644 --- a/src/plugins/debugger/cdb/cdbengine.cpp +++ b/src/plugins/debugger/cdb/cdbengine.cpp @@ -59,6 +59,7 @@ #include <coreplugin/icore.h> #include <texteditor/itexteditor.h> #include <projectexplorer/toolchain.h> +#include <projectexplorer/projectexplorerconstants.h> #include <utils/synchronousprocess.h> #include <utils/winutils.h> @@ -299,24 +300,14 @@ static inline bool validMode(DebuggerStartMode sm) return true; } -static inline QString msgCdbDisabled(const Abi &abi) -{ - return CdbEngine::tr("The CDB debug engine required for %1 is currently disabled."). - arg(abi.toString()); -} - // Accessed by RunControlFactory DebuggerEngine *createCdbEngine(const DebuggerStartParameters &sp, DebuggerEngine *masterEngine, QString *errorMessage) { #ifdef Q_OS_WIN CdbOptionsPage *op = CdbOptionsPage::instance(); - if (!op || !op->options()->isValid()) { - *errorMessage = msgCdbDisabled(sp.toolChainAbi); - return 0; - } - if (!validMode(sp.startMode)) { - *errorMessage = CdbEngine::tr("The CDB debug engine does not support start mode %1.").arg(sp.startMode); + if (!op || !op->options()->isValid() || !validMode(sp.startMode)) { + *errorMessage = QLatin1String("Internal error: Invalid start parameters passed for thre CDB engine."); return 0; } return new CdbEngine(sp, masterEngine, op->options()); @@ -337,21 +328,45 @@ bool isCdbEngineEnabled() #endif } -ConfigurationCheck checkCdbConfiguration(const Abi &abi) +static inline QString msgNoCdbBinaryForToolChain(const ProjectExplorer::Abi &tc) { - ConfigurationCheck check; - if (abi.binaryFormat() == Abi::PEFormat - && abi.osFlavor() != Abi::WindowsMSysFlavor) { - if (!isCdbEngineEnabled()) { - check.errorMessage = msgCdbDisabled(abi); - check.settingsPage = CdbOptionsPage::settingsId(); - } - } else { - check.errorMessage = CdbEngine::tr("The CDB debug engine does not support the %1 ABI."). - arg(abi.toString()); - check.settingsPage = CdbOptionsPage::settingsId(); + return CdbEngine::tr("There is no CDB binary available for binaries in format '%1'").arg(tc.toString()); +} + +bool checkCdbConfiguration(const DebuggerStartParameters &sp, ConfigurationCheck *check) +{ +#ifdef Q_OS_WIN + if (!isCdbEngineEnabled()) { + check->errorMessage = CdbEngine::tr("The CDB debug engine required for %1 is currently disabled."). + arg(sp.toolChainAbi.toString()); + check->settingsCategory = QLatin1String(Debugger::Constants::DEBUGGER_SETTINGS_CATEGORY); + check->settingsPage = CdbOptionsPage::settingsId(); + return false; } - return check; + + if (debuggerCore()->debuggerForAbi(sp.toolChainAbi, CdbEngineType).isEmpty()) { + check->errorMessage = msgNoCdbBinaryForToolChain(sp.toolChainAbi); + check->settingsCategory = QLatin1String(ProjectExplorer::Constants::TOOLCHAIN_SETTINGS_CATEGORY); + check->settingsPage = QLatin1String(ProjectExplorer::Constants::TOOLCHAIN_SETTINGS_CATEGORY); + return false; + } + + if (!validMode(sp.startMode)) { + check->errorMessage = CdbEngine::tr("The CDB engine does not support start mode %1.").arg(sp.startMode); + return false; + } + + if (sp.toolChainAbi.binaryFormat() != Abi::PEFormat || sp.toolChainAbi.os() != Abi::WindowsOS) { + check->errorMessage = CdbEngine::tr("The CDB debug engine does not support the %1 ABI."). + arg(sp.toolChainAbi.toString()); + return false; + } + return true; +#else + Q_UNUSED(sp); + check->errorMessage = QString::fromLatin1("Unsupported debug mode"); + return false; +#endif } void addCdbOptionPages(QList<Core::IOptionsPage *> *opts) @@ -637,12 +652,7 @@ bool CdbEngine::launchCDB(const DebuggerStartParameters &sp, QString *errorMessa // Determine binary (force MSVC), extension lib name and path to use // The extension is passed as relative name with the path variable set //(does not work with absolute path names) - Abi abi = sp.toolChainAbi; - if (abi.osFlavor() == Abi::UnknownFlavor - || abi.osFlavor() == Abi::WindowsMSysFlavor) - abi = Abi(abi.architecture(), abi.os(), Abi::WindowsMsvcFlavor, - abi.binaryFormat(), abi.wordWidth()); - const QString executable = debuggerCore()->debuggerForAbi(abi); + const QString executable = debuggerCore()->debuggerForAbi(sp.toolChainAbi, CdbEngineType); if (executable.isEmpty()) { *errorMessage = tr("There is no CDB executable specified."); return false; diff --git a/src/plugins/debugger/debugger.pro b/src/plugins/debugger/debugger.pro index f58c1eee987d3aa5dc6ee7cdabb57de2f5807e6f..6e0100065fa0164330142db554e73064401f73e9 100644 --- a/src/plugins/debugger/debugger.pro +++ b/src/plugins/debugger/debugger.pro @@ -62,7 +62,8 @@ HEADERS += breakhandler.h \ threadshandler.h \ watchdelegatewidgets.h \ debuggerruncontrolfactory.h \ - debuggertooltipmanager.h + debuggertooltipmanager.h \ + debuggertoolchaincombobox.h SOURCES += breakhandler.cpp \ breakpoint.cpp \ @@ -104,7 +105,8 @@ SOURCES += breakhandler.cpp \ watchwindow.cpp \ stackframe.cpp \ watchdelegatewidgets.cpp \ - debuggertooltipmanager.cpp + debuggertooltipmanager.cpp \ + debuggertoolchaincombobox.cpp FORMS += attachexternaldialog.ui \ attachcoredialog.ui \ diff --git a/src/plugins/debugger/debuggercore.h b/src/plugins/debugger/debuggercore.h index caa23bb381ed636bf5d27f47570104ce8855b51f..3cbd1b79078654575b46e31af9b42073344679fe 100644 --- a/src/plugins/debugger/debuggercore.h +++ b/src/plugins/debugger/debuggercore.h @@ -98,12 +98,13 @@ public: virtual void runControlFinished(DebuggerEngine *engine) = 0; virtual void displayDebugger(DebuggerEngine *engine, bool updateEngine) = 0; virtual DebuggerLanguages activeLanguages() const = 0; + virtual unsigned enabledEngines() const = 0; virtual void synchronizeBreakpoints() = 0; virtual bool initialize(const QStringList &arguments, QString *errorMessage) = 0; virtual QWidget *mainWindow() const = 0; virtual bool isDockVisible(const QString &objectName) const = 0; - virtual QString debuggerForAbi(const ProjectExplorer::Abi &abi) const = 0; + virtual QString debuggerForAbi(const ProjectExplorer::Abi &abi, DebuggerEngineType et = NoEngineType) const = 0; virtual void showModuleSymbols(const QString &moduleName, const QVector<Symbol> &symbols) = 0; virtual void openMemoryEditor() = 0; diff --git a/src/plugins/debugger/debuggerdialogs.cpp b/src/plugins/debugger/debuggerdialogs.cpp index 164d4f4617b380d500e3a352322d9d14feaa96f5..51c1de66526dae61a7ecccc5f4e2fda02e2cb3da 100644 --- a/src/plugins/debugger/debuggerdialogs.cpp +++ b/src/plugins/debugger/debuggerdialogs.cpp @@ -48,6 +48,7 @@ #endif #include <coreplugin/icore.h> +#include <projectexplorer/abi.h> #include <utils/synchronousprocess.h> #include <utils/historycompleter.h> #include <utils/qtcassert.h> @@ -180,7 +181,9 @@ void ProcessListFilterModel::populate AttachCoreDialog::AttachCoreDialog(QWidget *parent) : QDialog(parent), m_ui(new Ui::AttachCoreDialog) { + setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); m_ui->setupUi(this); + m_ui->toolchainComboBox->init(false); m_ui->execFileName->setExpectedKind(PathChooser::File); m_ui->execFileName->setPromptDialogTitle(tr("Select Executable")); @@ -192,6 +195,9 @@ AttachCoreDialog::AttachCoreDialog(QWidget *parent) connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept())); connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject())); + connect(m_ui->coreFileName, SIGNAL(changed(QString)), this, SLOT(changed())); + connect(m_ui->execFileName, SIGNAL(changed(QString)), this, SLOT(changed())); + changed(); } AttachCoreDialog::~AttachCoreDialog() @@ -207,6 +213,7 @@ QString AttachCoreDialog::executableFile() const void AttachCoreDialog::setExecutableFile(const QString &fileName) { m_ui->execFileName->setPath(fileName); + changed(); } QString AttachCoreDialog::coreFile() const @@ -217,8 +224,29 @@ QString AttachCoreDialog::coreFile() const void AttachCoreDialog::setCoreFile(const QString &fileName) { m_ui->coreFileName->setPath(fileName); + changed(); +} + +ProjectExplorer::Abi AttachCoreDialog::abi() const +{ + return m_ui->toolchainComboBox->abi(); } +void AttachCoreDialog::setAbi(const ProjectExplorer::Abi &abi) +{ + m_ui->toolchainComboBox->setAbi(abi); +} + +bool AttachCoreDialog::isValid() const +{ + return m_ui->toolchainComboBox->currentIndex() >= 0 && + !coreFile().isEmpty(); +} + +void AttachCoreDialog::changed() +{ + m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(isValid()); +} /////////////////////////////////////////////////////////////////////// // @@ -333,7 +361,9 @@ AttachExternalDialog::AttachExternalDialog(QWidget *parent) m_ui(new Ui::AttachExternalDialog), m_model(new ProcessListFilterModel(this)) { + setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); m_ui->setupUi(this); + m_ui->toolchainComboBox->init(true); okButton()->setDefault(true); okButton()->setEnabled(false); @@ -429,9 +459,20 @@ QString AttachExternalDialog::executable() const return m_model->executableForPid(attachPIDText()); } +ProjectExplorer::Abi AttachExternalDialog::abi() const +{ + return m_ui->toolchainComboBox->abi(); +} + +void AttachExternalDialog::setAbi(const ProjectExplorer::Abi &abi) +{ + m_ui->toolchainComboBox->setAbi(abi); +} + void AttachExternalDialog::pidChanged(const QString &pid) { - bool enabled = !pid.isEmpty() && pid != QLatin1String("0") && pid != m_selfPid; + const bool enabled = !pid.isEmpty() && pid != QLatin1String("0") && pid != m_selfPid + && m_ui->toolchainComboBox->currentIndex() >= 0; okButton()->setEnabled(enabled); } @@ -460,14 +501,15 @@ AttachTcfDialog::AttachTcfDialog(QWidget *parent) : QDialog(parent), m_ui(new Ui::AttachTcfDialog) { + setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); m_ui->setupUi(this); m_ui->buttonBox->button(QDialogButtonBox::Ok)->setDefault(true); m_ui->serverStartScript->setExpectedKind(PathChooser::File); m_ui->serverStartScript->setPromptDialogTitle(tr("Select Executable")); - connect(m_ui->useServerStartScriptCheckBox, SIGNAL(toggled(bool)), + connect(m_ui->useServerStartScriptCheckBox, SIGNAL(toggled(bool)), this, SLOT(updateState())); - + connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept())); connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject())); @@ -548,27 +590,25 @@ void AttachTcfDialog::updateState() StartExternalDialog::StartExternalDialog(QWidget *parent) : QDialog(parent), m_ui(new Ui::StartExternalDialog) { + setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); m_ui->setupUi(this); + m_ui->toolChainComboBox->init(true); m_ui->execFile->setExpectedKind(PathChooser::File); m_ui->execFile->setPromptDialogTitle(tr("Select Executable")); m_ui->execFile->lineEdit()->setCompleter( new HistoryCompleter(m_ui->execFile->lineEdit())); + connect(m_ui->execFile, SIGNAL(changed(QString)), this, SLOT(changed())); m_ui->buttonBox->button(QDialogButtonBox::Ok)->setDefault(true); m_ui->workingDirectory->setExpectedKind(PathChooser::ExistingDirectory); m_ui->workingDirectory->setPromptDialogTitle(tr("Select Working Directory")); m_ui->workingDirectory->lineEdit()->setCompleter( new HistoryCompleter(m_ui->workingDirectory->lineEdit())); - //execLabel->setHidden(false); - //execEdit->setHidden(false); - //browseButton->setHidden(false); - - m_ui->execLabel->setText(tr("Executable:")); - m_ui->argsLabel->setText(tr("Arguments:")); m_ui->argsEdit->setCompleter(new HistoryCompleter(m_ui->argsEdit)); connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept())); connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject())); + changed(); } StartExternalDialog::~StartExternalDialog() @@ -579,6 +619,7 @@ StartExternalDialog::~StartExternalDialog() void StartExternalDialog::setExecutableFile(const QString &str) { m_ui->execFile->setPath(str); + changed(); } QString StartExternalDialog::executableFile() const @@ -611,6 +652,27 @@ bool StartExternalDialog::breakAtMain() const return m_ui->checkBoxBreakAtMain->isChecked(); } +ProjectExplorer::Abi StartExternalDialog::abi() const +{ + return m_ui->toolChainComboBox->abi(); +} + +void StartExternalDialog::setAbi(const ProjectExplorer::Abi &abi) +{ + m_ui->toolChainComboBox->setAbi(abi); +} + +bool StartExternalDialog::isValid() const +{ + return m_ui->toolChainComboBox->currentIndex() >= 0 + && !executableFile().isEmpty(); +} + +void StartExternalDialog::changed() +{ + m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(isValid()); +} + /////////////////////////////////////////////////////////////////////// // // StartRemoteDialog @@ -621,6 +683,7 @@ StartRemoteDialog::StartRemoteDialog(QWidget *parent) : QDialog(parent), m_ui(new Ui::StartRemoteDialog) { + setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); m_ui->setupUi(this); m_ui->buttonBox->button(QDialogButtonBox::Ok)->setDefault(true); m_ui->debuggerPathChooser->setExpectedKind(PathChooser::File); @@ -912,13 +975,14 @@ StartRemoteEngineDialog::StartRemoteEngineDialog(QWidget *parent) : QDialog(parent) , m_ui(new Ui::StartRemoteEngineDialog) { - m_ui->setupUi(this); - m_ui->host->setCompleter(new HistoryCompleter(m_ui->host)); - m_ui->username->setCompleter(new HistoryCompleter(m_ui->username)); - m_ui->enginepath->setCompleter(new HistoryCompleter(m_ui->enginepath)); - m_ui->inferiorpath->setCompleter(new HistoryCompleter(m_ui->inferiorpath)); - connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept())); - connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject())); + setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); + m_ui->setupUi(this); + m_ui->host->setCompleter(new HistoryCompleter(m_ui->host)); + m_ui->username->setCompleter(new HistoryCompleter(m_ui->username)); + m_ui->enginepath->setCompleter(new HistoryCompleter(m_ui->enginepath)); + m_ui->inferiorpath->setCompleter(new HistoryCompleter(m_ui->inferiorpath)); + connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept())); + connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject())); } StartRemoteEngineDialog::~StartRemoteEngineDialog() @@ -950,6 +1014,5 @@ QString StartRemoteEngineDialog::enginePath() const return m_ui->enginepath->text(); } - } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/debuggerdialogs.h b/src/plugins/debugger/debuggerdialogs.h index a0d468049f550d2cb19a7d3cf5cf7e3276b38870..cf489defc527d00375de082e5d726f31ffb4679f 100644 --- a/src/plugins/debugger/debuggerdialogs.h +++ b/src/plugins/debugger/debuggerdialogs.h @@ -54,6 +54,9 @@ class StartRemoteEngineDialog; QT_END_NAMESPACE +namespace ProjectExplorer { +class Abi; +} namespace Debugger { namespace Internal { @@ -82,7 +85,15 @@ public: QString executableFile() const; QString coreFile() const; + ProjectExplorer::Abi abi() const; + void setAbi(const ProjectExplorer::Abi &); + +private slots: + void changed(); + private: + bool isValid() const; + Ui::AttachCoreDialog *m_ui; }; @@ -97,6 +108,9 @@ public: qint64 attachPID() const; QString executable() const; + ProjectExplorer::Abi abi() const; + void setAbi(const ProjectExplorer::Abi &); + virtual void accept(); private slots: @@ -159,8 +173,16 @@ public: QString workingDirectory() const; void setWorkingDirectory(const QString &str); + ProjectExplorer::Abi abi() const; + void setAbi(const ProjectExplorer::Abi &); + bool breakAtMain() const; + bool isValid() const; + +private slots: + void changed(); + private: Ui::StartExternalDialog *m_ui; }; diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index 86f111d37d0dd94e365e20612566b483f6fae58f..9371f8f659361d2421f34f85a5a914ca0b5d5a20 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -94,6 +94,7 @@ #include <projectexplorer/toolchainmanager.h> #include <projectexplorer/session.h> #include <projectexplorer/target.h> +#include <projectexplorer/abi.h> #include <qt4projectmanager/qt4projectmanagerconstants.h> @@ -695,10 +696,11 @@ public slots: void startRemoteApplication(); void startRemoteEngine(); void attachExternalApplication(); - void attachExternalApplication(qint64 pid, const QString &binary); + void attachExternalApplication(qint64 pid, const QString &binary, + const ProjectExplorer::Abi &abi = ProjectExplorer::Abi()); void runScheduled(); void attachCore(); - void attachCore(const QString &core, const QString &exeFileName); + void attachCore(const QString &core, const QString &exeFileName, const ProjectExplorer::Abi &abi = ProjectExplorer::Abi()); void attachRemote(const QString &spec); void attachRemoteTcf(); @@ -720,7 +722,8 @@ public slots: void runControlStarted(DebuggerEngine *engine); void runControlFinished(DebuggerEngine *engine); DebuggerLanguages activeLanguages() const; - QString debuggerForAbi(const Abi &abi) const; + unsigned enabledEngines() const { return m_cmdLineEnabledEngines; } + QString debuggerForAbi(const Abi &abi, DebuggerEngineType et = NoEngineType) const; void remoteCommand(const QStringList &options, const QStringList &); bool isReverseDebugging() const; @@ -1339,6 +1342,10 @@ void DebuggerPluginPrivate::startExternalApplication() configValue(_("LastExternalExecutableArguments")).toString()); dlg.setWorkingDirectory( configValue(_("LastExternalWorkingDirectory")).toString()); + const QString abiString = configValue(_("LastExternalAbi")).toString(); + if (!abiString.isEmpty()) + dlg.setAbi(ProjectExplorer::Abi(abiString)); + if (dlg.exec() != QDialog::Accepted) return; @@ -1348,9 +1355,12 @@ void DebuggerPluginPrivate::startExternalApplication() dlg.executableArguments()); setConfigValue(_("LastExternalWorkingDirectory"), dlg.workingDirectory()); + setConfigValue(_("LastExternalAbi"), + dlg.abi().toString()); + sp.executable = dlg.executableFile(); sp.startMode = StartExternal; - sp.toolChainAbi = abiOfBinary(sp.executable); + sp.toolChainAbi = dlg.abi(); sp.workingDirectory = dlg.workingDirectory(); if (!dlg.executableArguments().isEmpty()) sp.processArgs = dlg.executableArguments(); @@ -1375,12 +1385,20 @@ void DebuggerPluginPrivate::startExternalApplication() void DebuggerPluginPrivate::attachExternalApplication() { AttachExternalDialog dlg(mainWindow()); - if (dlg.exec() == QDialog::Accepted) - attachExternalApplication(dlg.attachPID(), dlg.executable()); + + const QString abiString = configValue(_("LastAttachExternalAbi")).toString(); + if (!abiString.isEmpty()) + dlg.setAbi(ProjectExplorer::Abi(abiString)); + + if (dlg.exec() != QDialog::Accepted) + return; + + setConfigValue(_("LastAttachExternalAbi"), dlg.abi().toString()); + attachExternalApplication(dlg.attachPID(), dlg.executable(), dlg.abi()); } void DebuggerPluginPrivate::attachExternalApplication - (qint64 pid, const QString &binary) + (qint64 pid, const QString &binary, const ProjectExplorer::Abi &abi) { if (pid == 0) { QMessageBox::warning(mainWindow(), tr("Warning"), @@ -1392,7 +1410,7 @@ void DebuggerPluginPrivate::attachExternalApplication sp.displayName = tr("Process %1").arg(pid); sp.executable = binary; sp.startMode = AttachExternal; - sp.toolChainAbi = abiOfBinary(sp.executable); + sp.toolChainAbi = abi.isValid() ? abi : abiOfBinary(sp.executable); if (DebuggerRunControl *rc = createDebugger(sp)) startDebugger(rc); } @@ -1402,21 +1420,27 @@ void DebuggerPluginPrivate::attachCore() AttachCoreDialog dlg(mainWindow()); dlg.setExecutableFile(configValue(_("LastExternalExecutableFile")).toString()); dlg.setCoreFile(configValue(_("LastExternalCoreFile")).toString()); + const QString abiString = configValue(_("LastExternalCoreAbi")).toString(); + if (!abiString.isEmpty()) + dlg.setAbi(ProjectExplorer::Abi(abiString)); + if (dlg.exec() != QDialog::Accepted) return; + setConfigValue(_("LastExternalExecutableFile"), dlg.executableFile()); setConfigValue(_("LastExternalCoreFile"), dlg.coreFile()); - attachCore(dlg.coreFile(), dlg.executableFile()); + setConfigValue(_("LastExternalCoreAbi"), dlg.abi().toString()); + attachCore(dlg.coreFile(), dlg.executableFile(), dlg.abi()); } -void DebuggerPluginPrivate::attachCore(const QString &core, const QString &exe) +void DebuggerPluginPrivate::attachCore(const QString &core, const QString &exe, const ProjectExplorer::Abi &abi) { DebuggerStartParameters sp; sp.executable = exe; sp.coreFile = core; sp.displayName = tr("Core file \"%1\"").arg(core); sp.startMode = AttachCore; - sp.toolChainAbi = abiOfBinary(sp.coreFile); + sp.toolChainAbi = abi.isValid() ? abi : abiOfBinary(sp.coreFile); if (DebuggerRunControl *rc = createDebugger(sp)) startDebugger(rc); } @@ -2368,9 +2392,26 @@ void DebuggerPluginPrivate::remoteCommand(const QStringList &options, runScheduled(); } -QString DebuggerPluginPrivate::debuggerForAbi(const Abi &abi) const +QString DebuggerPluginPrivate::debuggerForAbi(const Abi &abi, DebuggerEngineType et) const { - foreach (const ToolChain *tc, ToolChainManager::instance()->findToolChains(abi)) { + Abi searchAbi = abi; + // Pick the right toolchain in case cdb/gdb were started with other toolchains. + // Also, lldb should be preferred over gdb. + if (searchAbi.os() == ProjectExplorer::Abi::WindowsOS) { + switch (et) { + case CdbEngineType: + searchAbi = Abi(abi.architecture(), abi.os(), Abi::WindowsMsvcFlavor, + abi.binaryFormat(), abi.wordWidth()); + break; + case GdbEngineType: + searchAbi = Abi(abi.architecture(), abi.os(), Abi::WindowsMSysFlavor, + abi.binaryFormat(), abi.wordWidth()); + break; + default: + break; + } + } + foreach (const ToolChain *tc, ToolChainManager::instance()->findToolChains(searchAbi)) { const QString debugger = tc->debuggerCommand(); if (!debugger.isEmpty()) return debugger; @@ -2680,11 +2721,6 @@ void DebuggerPluginPrivate::extensionsInitialized() cmd->setAttribute(Command::CA_Hide); mstart->addAction(cmd, CC::G_DEFAULT_ONE); - cmd = am->registerAction(m_startRemoteLldbAction, - Constants::STARTREMOTELLDB, globalcontext); - cmd->setAttribute(Command::CA_Hide); - mstart->addAction(cmd, CC::G_DEFAULT_ONE); - cmd = am->registerAction(m_attachExternalAction, Constants::ATTACHEXTERNAL, globalcontext); cmd->setAttribute(Command::CA_Hide); @@ -2705,6 +2741,11 @@ void DebuggerPluginPrivate::extensionsInitialized() cmd->setAttribute(Command::CA_Hide); mstart->addAction(cmd, CC::G_DEFAULT_ONE); + cmd = am->registerAction(m_startRemoteLldbAction, + Constants::STARTREMOTELLDB, globalcontext); + cmd->setAttribute(Command::CA_Hide); + mstart->addAction(cmd, CC::G_DEFAULT_ONE); + if (m_startRemoteCdbAction) { cmd = am->registerAction(m_startRemoteCdbAction, Constants::ATTACHREMOTECDB, globalcontext); diff --git a/src/plugins/debugger/debuggerruncontrolfactory.h b/src/plugins/debugger/debuggerruncontrolfactory.h index 0cccd1a7075e3f7c1e2a2bf6643040e6c5bffbbd..5ef663cbff35973249b0b1566d0cafa93f9b4619 100644 --- a/src/plugins/debugger/debuggerruncontrolfactory.h +++ b/src/plugins/debugger/debuggerruncontrolfactory.h @@ -37,6 +37,7 @@ #include <projectexplorer/runconfiguration.h> namespace Debugger { +class DebuggerEngine; namespace Internal { class DebuggerRunControlFactory @@ -57,6 +58,11 @@ public: RunControl *create(RunConfiguration *runConfiguration, const QString &mode); bool canRun(RunConfiguration *runConfiguration, const QString &mode) const; + static DebuggerEngine *createEngine(DebuggerEngineType et, + const DebuggerStartParameters &sp, + DebuggerEngine *masterEngine, + QString *errorMessage); + private: QString displayName() const; QWidget *createConfigurationWidget(RunConfiguration *runConfiguration); diff --git a/src/plugins/debugger/debuggerrunner.cpp b/src/plugins/debugger/debuggerrunner.cpp index ecf74e14a2a995aa9b2ca539f7aa306fadad08f7..27919378834500da80b18284a27781f4b4ef050d 100644 --- a/src/plugins/debugger/debuggerrunner.cpp +++ b/src/plugins/debugger/debuggerrunner.cpp @@ -74,7 +74,7 @@ namespace Debugger { namespace Internal { bool isCdbEngineEnabled(); // Check the configuration page -ConfigurationCheck checkCdbConfiguration(const Abi &abi); +bool checkCdbConfiguration(const DebuggerStartParameters &sp, ConfigurationCheck *check); DebuggerEngine *createCdbEngine(const DebuggerStartParameters &sp, DebuggerEngine *masterEngine, QString *error); @@ -85,17 +85,50 @@ DebuggerEngine *createPdbEngine(const DebuggerStartParameters &sp); DebuggerEngine *createTcfEngine(const DebuggerStartParameters &sp); QmlEngine *createQmlEngine(const DebuggerStartParameters &sp, DebuggerEngine *masterEngine); -DebuggerEngine *createQmlCppEngine(const DebuggerStartParameters &sp); +DebuggerEngine *createQmlCppEngine(const DebuggerStartParameters &sp, + DebuggerEngineType slaveEngineType, + QString *errorMessage); DebuggerEngine *createLldbEngine(const DebuggerStartParameters &sp); extern QString msgNoBinaryForToolChain(const Abi &abi); +static const char *engineTypeName(DebuggerEngineType et) +{ + switch (et) { + case Debugger::NoEngineType: + break; + case Debugger::GdbEngineType: + return "Gdb"; + case Debugger::ScriptEngineType: + return "Script engine"; + case Debugger::CdbEngineType: + return "Cdb engine"; + case Debugger::PdbEngineType: + return "Pdb engine"; case Debugger::TcfEngineType: + return "Tcf engine"; + case Debugger::QmlEngineType: + return "QML engine"; + case Debugger::QmlCppEngineType: + return "QML C++ engine"; + case Debugger::LldbEngineType: + return "LLDB engine"; + case Debugger::AllEngineTypes: + break; + } + return "No engine"; +} + static QString msgEngineNotAvailable(const char *engine) { return DebuggerPlugin::tr("The application requires the debugger engine '%1', " "which is disabled.").arg(_(engine)); } +static inline QString msgEngineNotAvailable(DebuggerEngineType et) +{ + return msgEngineNotAvailable(engineTypeName(et)); +} + //////////////////////////////////////////////////////////////////////// // // DebuggerRunControlPrivate @@ -105,8 +138,8 @@ static QString msgEngineNotAvailable(const char *engine) class DebuggerRunControlPrivate { public: - DebuggerRunControlPrivate(DebuggerRunControl *parent, - RunConfiguration *runConfiguration); + explicit DebuggerRunControlPrivate(DebuggerRunControl *parent, + RunConfiguration *runConfiguration); DebuggerEngineType engineForExecutable(unsigned enabledEngineTypes, const QString &executable); @@ -118,12 +151,10 @@ public: DebuggerEngine *m_engine; const QWeakPointer<RunConfiguration> m_myRunConfiguration; bool m_running; - QString m_errorMessage; - QString m_settingsIdHint; }; DebuggerRunControlPrivate::DebuggerRunControlPrivate(DebuggerRunControl *parent, - RunConfiguration *runConfiguration) + RunConfiguration *runConfiguration) : q(parent) , m_engine(0) , m_myRunConfiguration(runConfiguration) @@ -131,222 +162,27 @@ DebuggerRunControlPrivate::DebuggerRunControlPrivate(DebuggerRunControl *parent, { } -// Figure out the debugger type of an executable. Analyze executable -// unless the toolchain provides a hint. -DebuggerEngineType DebuggerRunControlPrivate::engineForExecutable - (unsigned enabledEngineTypes, const QString &executable) -{ - if (executable.endsWith(_(".js"))) { - if (enabledEngineTypes & ScriptEngineType) - return ScriptEngineType; - m_errorMessage = msgEngineNotAvailable("Script Engine"); - } - - if (executable.endsWith(_(".py"))) { - if (enabledEngineTypes & PdbEngineType) - return PdbEngineType; - m_errorMessage = msgEngineNotAvailable("Pdb Engine"); - } - -#ifdef Q_OS_WIN - // A remote executable? - if (!executable.endsWith(_(".exe"))) - return GdbEngineType; - - // If a file has PDB files, it has been compiled by VS. - QStringList pdbFiles; - if (!getPDBFiles(executable, &pdbFiles, &m_errorMessage)) { - qWarning("Cannot determine type of executable %s: %s", - qPrintable(executable), qPrintable(m_errorMessage)); - return NoEngineType; - } - if (pdbFiles.empty()) - return GdbEngineType; - - // We need the CDB debugger in order to be able to debug VS - // executables. - Abi hostAbi = Abi::hostAbi(); - ConfigurationCheck check = checkDebugConfiguration(Abi(hostAbi.architecture(), - Abi::WindowsOS, - hostAbi.osFlavor(), - Abi::PEFormat, - hostAbi.wordWidth())); - if (!check) { - m_errorMessage = check.errorMessage; - m_settingsIdHint = check.settingsPage; - if (enabledEngineTypes & CdbEngineType) - return CdbEngineType; - m_errorMessage = msgEngineNotAvailable("Cdb Engine"); - return NoEngineType; - } -#else - if (enabledEngineTypes & GdbEngineType) - return GdbEngineType; - m_errorMessage = msgEngineNotAvailable("Gdb Engine"); -#endif - - return NoEngineType; -} - -// Debugger type for mode. -DebuggerEngineType DebuggerRunControlPrivate::engineForMode - (unsigned enabledEngineTypes, DebuggerStartMode startMode) -{ - if (startMode == AttachTcf) - return TcfEngineType; - -#ifdef Q_OS_WIN - // Preferably Windows debugger for attaching locally. - if (startMode != AttachToRemote && (enabledEngineTypes & CdbEngineType)) - return CdbEngineType; - if (startMode == AttachCrashedExternal) { - m_errorMessage = DebuggerRunControl::tr("There is no debugging engine available for post-mortem debugging."); - return NoEngineType; - } - return GdbEngineType; -#else - Q_UNUSED(startMode) - Q_UNUSED(enabledEngineTypes) - // >m_errorMessage = msgEngineNotAvailable("Gdb Engine"); - return GdbEngineType; -#endif -} - } // namespace Internal - -//////////////////////////////////////////////////////////////////////// -// -// DebuggerRunControl -// -//////////////////////////////////////////////////////////////////////// - -static DebuggerEngineType engineForToolChain(const Abi &toolChain) -{ - switch (toolChain.binaryFormat()) { - case Abi::ElfFormat: - case Abi::MachOFormat: -#ifdef WITH_LLDB - // lldb override - if (Core::ICore::instance()->settings()->value("LLDB/enabled").toBool()) - return LldbEngineType; -#endif - return GdbEngineType; - case Abi::PEFormat: - if (toolChain.osFlavor() == Abi::WindowsMSysFlavor) - return GdbEngineType; - return CdbEngineType; - default: - break; - } - return NoEngineType; -} - - -unsigned filterEngines(unsigned enabledEngineTypes) -{ -#ifdef CDB_ENABLED - if (!isCdbEngineEnabled() && !Cdb::isCdbEngineEnabled()) - enabledEngineTypes &= ~CdbEngineType; -#endif - return enabledEngineTypes; -} - DebuggerRunControl::DebuggerRunControl(RunConfiguration *runConfiguration, - const DebuggerStartParameters &startParams) + const DebuggerStartParameters &sp, + const QPair<DebuggerEngineType, DebuggerEngineType> &masterSlaveEngineTypes) : RunControl(runConfiguration, Constants::DEBUGMODE), d(new DebuggerRunControlPrivate(this, runConfiguration)) { connect(this, SIGNAL(finished()), SLOT(handleFinished())); - - // Figure out engine according to toolchain, executable, attach or default. - DebuggerEngineType engineType = NoEngineType; - DebuggerLanguages activeLangs = debuggerCore()->activeLanguages(); - DebuggerStartParameters sp = startParams; - unsigned enabledEngineTypes = filterEngines(sp.enabledEngines); - - if (sp.executable.endsWith(_(".js"))) - engineType = ScriptEngineType; - else if (sp.executable.endsWith(_(".py"))) - engineType = PdbEngineType; - else { - engineType = engineForToolChain(sp.toolChainAbi); - if (engineType == CdbEngineType && !(enabledEngineTypes & CdbEngineType)) { - d->m_errorMessage = msgEngineNotAvailable("Cdb Engine"); - engineType = NoEngineType; - } - } - - // FIXME: Unclean ipc override. Someone please have a better idea. - if (sp.startMode == StartRemoteEngine) - // For now thats the only supported IPC engine. - engineType = LldbEngineType; - - // FIXME: 1 of 3 testing hacks. - if (sp.processArgs.startsWith(__("@tcf@ "))) - engineType = GdbEngineType; - - // Override CDB by gdb if no PDB sections are found in executable - // (pending proper MinGW/MSys detection). - if ((engineType == NoEngineType || engineType == CdbEngineType) - && sp.startMode != AttachToRemote && !sp.executable.isEmpty()) - engineType = d->engineForExecutable(enabledEngineTypes, sp.executable); - - if (engineType == NoEngineType) - engineType = d->engineForMode(enabledEngineTypes, sp.startMode); - - if ((engineType != QmlEngineType && engineType != NoEngineType) - && (activeLangs & QmlLanguage)) { - if (activeLangs & CppLanguage) { - sp.cppEngineType = engineType; - engineType = QmlCppEngineType; - } else { - engineType = QmlEngineType; - } - } - - // qDebug() << "USING ENGINE : " << engineType; - - switch (engineType) { - case GdbEngineType: - d->m_engine = createGdbEngine(sp, 0); - break; - case ScriptEngineType: - d->m_engine = createScriptEngine(sp); - break; - case CdbEngineType: - d->m_engine = createCdbEngine(sp, 0, &d->m_errorMessage); - break; - case PdbEngineType: - d->m_engine = createPdbEngine(sp); - break; - case TcfEngineType: - d->m_engine = createTcfEngine(sp); - break; - case QmlEngineType: - d->m_engine = createQmlEngine(sp, 0); - break; - case QmlCppEngineType: - d->m_engine = createQmlCppEngine(sp); - break; - case LldbEngineType: - d->m_engine = createLldbEngine(sp); - case NoEngineType: - case AllEngineTypes: - break; - } - + // Create the engine. Could arguably be moved to the factory, but + // we still have a derived S60DebugControl. Should rarely fail, though. + QString errorMessage; + d->m_engine = masterSlaveEngineTypes.first == QmlCppEngineType ? + createQmlCppEngine(sp, masterSlaveEngineTypes.second, &errorMessage) : + DebuggerRunControlFactory::createEngine(masterSlaveEngineTypes.first, sp, + 0, &errorMessage); if (d->m_engine) { DebuggerToolTipManager::instance()->registerEngine(d->m_engine); } else { - // Could not find anything suitable. debuggingFinished(); - // Create Message box with possibility to go to settings. - const QString msg = tr("Cannot debug '%1' (binary format: '%2'): %3") - .arg(sp.executable, sp.toolChainAbi.toString(), d->m_errorMessage); - Core::ICore::instance()->showWarningWithOptions(tr("Warning"), - msg, QString(), _(Constants::DEBUGGER_SETTINGS_CATEGORY), - d->m_settingsIdHint); + Core::ICore::instance()->showWarningWithOptions(DebuggerRunControl::tr("Debugger"), errorMessage); } } @@ -378,40 +214,6 @@ void DebuggerRunControl::setCustomEnvironment(Utils::Environment env) d->m_engine->startParameters().environment = env; } -ConfigurationCheck checkDebugConfiguration(const Abi &abi) -{ - ConfigurationCheck result; - - if (!(debuggerCore()->activeLanguages() & CppLanguage)) - return result; - - if (abi.binaryFormat() == Abi::ElfFormat || - abi.binaryFormat() == Abi::MachOFormat || - (abi.binaryFormat() == Abi::PEFormat && abi.osFlavor() == Abi::WindowsMSysFlavor)) { - if (debuggerCore()->debuggerForAbi(abi).isEmpty()) { - result.errorMessage = msgNoBinaryForToolChain(abi); - if (!result.errorMessage.isEmpty()) - result.errorMessage += QLatin1Char('\n'); - result.errorMessage += QLatin1Char(' ') + msgEngineNotAvailable("Gdb"); - result.settingsPage = _(Constants::DEBUGGER_COMMON_SETTINGS_ID); - } - } else if (abi.binaryFormat() == Abi::PEFormat - && abi.osFlavor() != Abi::WindowsMSysFlavor) { - result = checkCdbConfiguration(abi); - if (!result) { - if (!result.errorMessage.isEmpty()) - result.errorMessage += QLatin1Char('\n'); - result.errorMessage += msgEngineNotAvailable("Cdb"); - result.settingsPage = _("Cdb"); - } - } - - if (!result && !result.settingsPage.isEmpty()) - result.settingsCategory = _(Constants::DEBUGGER_SETTINGS_CATEGORY); - - return result; -} - void DebuggerRunControl::start() { QTC_ASSERT(d->m_engine, return); @@ -503,6 +305,266 @@ RunConfiguration *DebuggerRunControl::runConfiguration() const return d->m_myRunConfiguration.data(); } +//////////////////////////////////////////////////////////////////////// +// +// Engine detection logic: Detection functions depending on toolchain, binary, +// etc. Return a list of possible engines (order of prefererence) without +// consideration of configuration, etc. +// +//////////////////////////////////////////////////////////////////////// + +static QList<DebuggerEngineType> enginesForToolChain(const Abi &toolChain) +{ + QList<DebuggerEngineType> result; + switch (toolChain.binaryFormat()) { + case Abi::ElfFormat: + case Abi::MachOFormat: + result.push_back(LldbEngineType); + result.push_back(GdbEngineType); + break; + case Abi::PEFormat: + if (toolChain.osFlavor() == Abi::WindowsMSysFlavor) { + result.push_back(GdbEngineType); + result.push_back(CdbEngineType); + } else { + result.push_back(CdbEngineType); + result.push_back(GdbEngineType); + } + break; + case Abi::RuntimeQmlFormat: + result.push_back(QmlEngineType); + break; + default: + break; + } + return result; +} + +static inline QList<DebuggerEngineType> enginesForScriptExecutables(const QString &executable) +{ + QList<DebuggerEngineType> result; + if (executable.endsWith(_(".js"))) { + result.push_back(ScriptEngineType); + } else if (executable.endsWith(_(".py"))) { + result.push_back(PdbEngineType); + } + return result; +} + +static QList<DebuggerEngineType> enginesForExecutable(const QString &executable) +{ + QList<DebuggerEngineType> result = enginesForScriptExecutables(executable); + if (!result.isEmpty()) + return result; +#ifdef Q_OS_WIN + // A remote executable? + if (!executable.endsWith(_(".exe"), Qt::CaseInsensitive)) { + result.push_back(GdbEngineType); + return result; + } + + // If a file has PDB files, it has been compiled by VS. + QStringList pdbFiles; + QString errorMessage; + if (getPDBFiles(executable, &pdbFiles, &errorMessage) && !pdbFiles.isEmpty()) { + result.push_back(CdbEngineType); + result.push_back(GdbEngineType); + return result; + } + // Fixme: Gdb should only be preferred if MinGW can positively be detected. + result.push_back(GdbEngineType); + result.push_back(CdbEngineType); +#else + result.push_back(LldbEngineType); + result.push_back(GdbEngineType); +#endif + return result; +} + +// Debugger type for mode. +static QList<DebuggerEngineType> enginesForMode(DebuggerStartMode startMode, + bool hardConstraintsOnly) +{ + QList<DebuggerEngineType> result; + switch (startMode) { + case Debugger::NoStartMode: + break; + case Debugger::StartInternal: + case Debugger::StartExternal: + case AttachExternal: + if (!hardConstraintsOnly) { +#ifdef Q_OS_WIN + result.push_back(CdbEngineType); // Preferably Windows debugger for attaching locally. +#endif + result.push_back(GdbEngineType); + } + break; + case Debugger::AttachCore: + case Debugger::StartRemoteGdb: + result.push_back(GdbEngineType); + break; + case Debugger::AttachToRemote: + if (!hardConstraintsOnly) { +#ifdef Q_OS_WIN + result.push_back(CdbEngineType); +#endif + result.push_back(GdbEngineType); + } + break; + case AttachTcf: + result.push_back(TcfEngineType); + break; + case AttachCrashedExternal: + result.push_back(CdbEngineType); // Only CDB can do this + break; + case StartRemoteEngine: + // FIXME: Unclear IPC override. Someone please have a better idea. + // For now thats the only supported IPC engine. + result.push_back(LldbEngineType); + break; + } + return result; +} + +// Engine detection logic: Call all detection functions in order. + +static QList<DebuggerEngineType> engineTypes(const DebuggerStartParameters &sp) +{ + // Script executables and certain start modes are 'hard constraints'. + QList<DebuggerEngineType> result = enginesForScriptExecutables(sp.executable); + if (!result.isEmpty()) + return result; + + result = enginesForMode(sp.startMode, true); + if (!result.isEmpty()) + return result; + + // 'hard constraints' done (with the exception of QML ABI checked here), + // further try to restrict available engines. + if (sp.toolChainAbi.isValid()) { + result = enginesForToolChain(sp.toolChainAbi); + if (!result.isEmpty()) + return result; + } + + // FIXME: 1 of 3 testing hacks. + if (sp.processArgs.startsWith(__("@tcf@ "))) { + result.push_back(GdbEngineType); + return result; + } + + if (sp.startMode != AttachToRemote && !sp.executable.isEmpty()) + result = enginesForExecutable(sp.executable); + if (!result.isEmpty()) + return result; + + result = enginesForMode(sp.startMode, false); + return result; +} + +// Engine detection logic: Configuration checks. + +QString msgNoBinaryForToolChain(const ProjectExplorer::Abi &tc, DebuggerEngineType et) +{ + return DebuggerPlugin::tr("There is no binary available for debugging binaries of type '%1' using the engine '%2'"). + arg(tc.toString(), QLatin1String(engineTypeName(et))); +} + +static inline bool engineConfigurationCheck(const DebuggerStartParameters &sp, + DebuggerEngineType et, + ConfigurationCheck *check) +{ + switch (et) { + case Debugger::CdbEngineType: + return checkCdbConfiguration(sp, check); + case Debugger::GdbEngineType: + if (debuggerCore()->debuggerForAbi(sp.toolChainAbi, et).isEmpty()) { + check->errorMessage = msgNoBinaryForToolChain(sp.toolChainAbi, et); + check->settingsCategory = QLatin1String(ProjectExplorer::Constants::TOOLCHAIN_SETTINGS_CATEGORY); + check->settingsPage = QLatin1String(ProjectExplorer::Constants::TOOLCHAIN_SETTINGS_CATEGORY); + return false; + } + default: + break; + } + return true; +} + +// Engine detection logic: ConfigurationCheck. +ConfigurationCheck::ConfigurationCheck() : + masterSlaveEngineTypes(NoEngineType, NoEngineType) +{ +} + +ConfigurationCheck::operator bool() const +{ + return errorMessage.isEmpty() && masterSlaveEngineTypes.first != NoEngineType; +} + +/*! + \fn ConfigurationCheck checkDebugConfiguration(unsigned cmdLineEnabledEngines, + const DebuggerStartParameters &sp) + + This is the master engine detection function that returns the + engine types for a given set of start parameters and checks their + configuration. +*/ + +DEBUGGER_EXPORT ConfigurationCheck checkDebugConfiguration(const DebuggerStartParameters &sp) +{ + ConfigurationCheck result; + const unsigned activeLangs = debuggerCore()->activeLanguages(); + const bool qmlLanguage = activeLangs & QmlLanguage; + const bool cppLanguage = activeLangs & CppLanguage; + // Get all applicable types. + QList<DebuggerEngineType> requiredTypes; + if (qmlLanguage && !cppLanguage) { + requiredTypes.push_back(QmlEngineType); + } else { + requiredTypes = engineTypes(sp); + } + if (requiredTypes.isEmpty()) { + result.errorMessage = DebuggerPlugin::tr("Internal error: Unable to determine debugger engine type for this configuration"); + return result; + } + // Filter out disables types, command line + current settings. + unsigned cmdLineEnabledEngines = debuggerCore()->enabledEngines(); +#ifdef CDB_ENABLED + if (!isCdbEngineEnabled() && !Cdb::isCdbEngineEnabled()) + cmdLineEnabledEngines &= ~CdbEngineType; +#endif +#ifdef WITH_LLDB + if (!Core::ICore::instance()->settings()->value(QLatin1String("LLDB/enabled")).toBool()) + cmdLineEnabledEngines &= ~LldbEngineType; +#else + cmdLineEnabledEngines &= ~LldbEngineType; +#endif + QList<DebuggerEngineType> usableTypes; + foreach (DebuggerEngineType et, requiredTypes) + if (et & cmdLineEnabledEngines) + usableTypes.push_back(et); + if (usableTypes.isEmpty()) { + result.errorMessage = DebuggerPlugin::tr("This configuration requires the debugger engine %1, which is disabled."). + arg(QLatin1String(engineTypeName(usableTypes.front()))); + return result; + } + // Configuration check: Strip off non-configured engines. + while (!usableTypes.isEmpty() && !engineConfigurationCheck(sp, usableTypes.front(), &result)) + usableTypes.pop_front(); + if (usableTypes.isEmpty()) { + result.errorMessage = DebuggerPlugin::tr("The debugger engine required for this configuration is not correctly configured:\n%1") + .arg(result.errorMessage); + return result; + } + // Anything left: Happy. + if (qmlLanguage && cppLanguage) { + result.masterSlaveEngineTypes.first = QmlCppEngineType; + result.masterSlaveEngineTypes.second = usableTypes.front(); + } else { + result.masterSlaveEngineTypes.first = usableTypes.front(); + } + return result; +} //////////////////////////////////////////////////////////////////////// // @@ -621,11 +683,9 @@ QWidget *DebuggerRunControlFactory::createConfigurationWidget } DebuggerRunControl *DebuggerRunControlFactory::create - (const DebuggerStartParameters &sp0, RunConfiguration *runConfiguration) + (const DebuggerStartParameters &sp, RunConfiguration *runConfiguration) { - DebuggerStartParameters sp = sp0; - sp.enabledEngines = m_enabledEngines; - ConfigurationCheck check = checkDebugConfiguration(sp.toolChainAbi); + const ConfigurationCheck check = checkDebugConfiguration(sp); if (!check) { //appendMessage(errorMessage, true); @@ -634,12 +694,41 @@ DebuggerRunControl *DebuggerRunControlFactory::create return 0; } - DebuggerRunControl *runControl = - new DebuggerRunControl(runConfiguration, sp); - if (runControl->d->m_engine) - return runControl; - delete runControl; + return new DebuggerRunControl(runConfiguration, sp, check.masterSlaveEngineTypes); +} + +DebuggerEngine * + DebuggerRunControlFactory::createEngine(DebuggerEngineType et, + const DebuggerStartParameters &sp, + DebuggerEngine *masterEngine, + QString *errorMessage) +{ + switch (et) { + case GdbEngineType: + return createGdbEngine(sp, masterEngine); + case ScriptEngineType: + return createScriptEngine(sp); + case CdbEngineType: + return createCdbEngine(sp, masterEngine, errorMessage); + break; + case PdbEngineType: + return createPdbEngine(sp); + break; + case TcfEngineType: + return createTcfEngine(sp); + break; + case QmlEngineType: + return createQmlEngine(sp, masterEngine); + break; + case LldbEngineType: + return createLldbEngine(sp); + default: + break; + } + *errorMessage = DebuggerRunControl::tr("Unable to create a debugger engine of the type '%1'"). + arg(_(engineTypeName(et))); return 0; } + } // namespace Debugger diff --git a/src/plugins/debugger/debuggerrunner.h b/src/plugins/debugger/debuggerrunner.h index 1da943d02a241ee0b48acf0c550cdb296ec24100..0a864a1ad67a720eeaf91bd013efbf968f91fe2a 100644 --- a/src/plugins/debugger/debuggerrunner.h +++ b/src/plugins/debugger/debuggerrunner.h @@ -35,11 +35,13 @@ #define DEBUGGERRUNNER_H #include "debugger_global.h" +#include "debuggerconstants.h" #include <projectexplorer/abi.h> #include <projectexplorer/runconfiguration.h> #include <QtCore/QScopedPointer> +#include <QtCore/QPair> namespace Utils { class Environment; @@ -59,16 +61,16 @@ class DebuggerRunControlFactory; class DEBUGGER_EXPORT ConfigurationCheck { public: - ConfigurationCheck() {} - operator bool() const { return errorMessage.isEmpty(); } + ConfigurationCheck(); + operator bool() const; -public: QString errorMessage; QString settingsCategory; QString settingsPage; + QPair<DebuggerEngineType, DebuggerEngineType> masterSlaveEngineTypes; }; -DEBUGGER_EXPORT ConfigurationCheck checkDebugConfiguration(const ProjectExplorer::Abi &abi); +DEBUGGER_EXPORT ConfigurationCheck checkDebugConfiguration(const DebuggerStartParameters &sp); // This is a job description containing all data "local" to the jobs, including // the models of the individual debugger views. @@ -79,8 +81,10 @@ class DEBUGGER_EXPORT DebuggerRunControl public: typedef ProjectExplorer::RunConfiguration RunConfiguration; - DebuggerRunControl(RunConfiguration *runConfiguration, - const DebuggerStartParameters &sp); + explicit DebuggerRunControl(RunConfiguration *runConfiguration, + const DebuggerStartParameters &sp, + const QPair<DebuggerEngineType, DebuggerEngineType> &masterSlaveEngineTypes); + ~DebuggerRunControl(); // ProjectExplorer::RunControl diff --git a/src/plugins/debugger/debuggerstartparameters.h b/src/plugins/debugger/debuggerstartparameters.h index 1d9c4a78a082d8877e75ed1d6c0847c8fb987dca..64f0199ee018b72bb8e108f239adb883962ea4f3 100644 --- a/src/plugins/debugger/debuggerstartparameters.h +++ b/src/plugins/debugger/debuggerstartparameters.h @@ -65,7 +65,6 @@ public: : isSnapshot(false), attachPID(-1), useTerminal(false), - enabledEngines(AllEngineTypes), qmlServerAddress(QLatin1String("127.0.0.1")), qmlServerPort(0), useServerStartScript(false), @@ -87,7 +86,6 @@ public: QString workingDirectory; qint64 attachPID; bool useTerminal; - unsigned enabledEngines; // Used by AttachCrashedExternal. QString crashParameter; diff --git a/src/plugins/debugger/debuggertoolchaincombobox.cpp b/src/plugins/debugger/debuggertoolchaincombobox.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1f2acfe370db50fe4430922b53d32c43c263a712 --- /dev/null +++ b/src/plugins/debugger/debuggertoolchaincombobox.cpp @@ -0,0 +1,90 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#include "debuggertoolchaincombobox.h" + +#include <projectexplorer/toolchainmanager.h> +#include <utils/qtcassert.h> + +#include <QtCore/QFileInfo> + +Q_DECLARE_METATYPE(ProjectExplorer::Abi) + +namespace Debugger { +namespace Internal { + +DebuggerToolChainComboBox::DebuggerToolChainComboBox(QWidget *parent) : + QComboBox(parent) +{ +} + +void DebuggerToolChainComboBox::init(bool hostAbiOnly) +{ + const ProjectExplorer::Abi hostAbi = ProjectExplorer::Abi::hostAbi(); + foreach (const ProjectExplorer::ToolChain *tc, ProjectExplorer::ToolChainManager::instance()->toolChains()) { + if (!hostAbiOnly || hostAbi.isCompatibleWith(tc->targetAbi())) { + const QString debuggerCommand = tc->debuggerCommand(); + if (!debuggerCommand.isEmpty()) { + const QString name = tr("%1 (%2)").arg(tc->displayName(), QFileInfo(debuggerCommand).baseName()); + addItem(name, qVariantFromValue(tc->targetAbi())); + } + } + } + setEnabled(count() > 1); +} + +void DebuggerToolChainComboBox::setAbi(const ProjectExplorer::Abi &abi) +{ + QTC_ASSERT(abi.isValid(), return; ) + const int c = count(); + for (int i = 0; i < c; i++) { + if (abiAt(i) == abi) { + setCurrentIndex(i); + break; + } + } +} + +ProjectExplorer::Abi DebuggerToolChainComboBox::abi() const +{ + return abiAt(currentIndex()); +} + +ProjectExplorer::Abi DebuggerToolChainComboBox::abiAt(int index) const +{ + return index >= 0 ? qvariant_cast<ProjectExplorer::Abi>(itemData(index)) : + ProjectExplorer::Abi(); +} + +} // namespace Debugger +} // namespace Internal diff --git a/src/plugins/debugger/debuggertoolchaincombobox.h b/src/plugins/debugger/debuggertoolchaincombobox.h new file mode 100644 index 0000000000000000000000000000000000000000..bf198da303938fa7f6b3ff3d446d96899ff4fbdb --- /dev/null +++ b/src/plugins/debugger/debuggertoolchaincombobox.h @@ -0,0 +1,65 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#ifndef DEBUGGERTOOLCHAINCOMBOBOX_H +#define DEBUGGERTOOLCHAINCOMBOBOX_H + +#include <QtGui/QComboBox> + +namespace ProjectExplorer { +class Abi; +} + +namespace Debugger { +namespace Internal { + +// Let the user pick a toolchain/ABI associated with a debugger. +class DebuggerToolChainComboBox : public QComboBox +{ + Q_OBJECT +public: + explicit DebuggerToolChainComboBox(QWidget *parent); + + void init(bool hostAbiOnly); + + void setAbi(const ProjectExplorer::Abi &abi); + ProjectExplorer::Abi abi() const; + +private: + ProjectExplorer::Abi abiAt(int index) const; +}; + +} // namespace Debugger +} // namespace Internal + +#endif // DEBUGGERTOOLCHAINCOMBOBOX_H diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index c1198365980433fba459d1067ecb26154bcc115e..2acecec49b564c646fc7e5b73e69cc0cc434a621 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -1804,9 +1804,8 @@ int GdbEngine::currentFrame() const return stackHandler()->currentIndex(); } -QString msgNoBinaryForToolChain(const ProjectExplorer::Abi &tc) +QString msgNoGdbBinaryForToolChain(const ProjectExplorer::Abi &tc) { - using namespace ProjectExplorer; return GdbEngine::tr("There is no gdb binary available for binaries in format '%1'") .arg(tc.toString()); } @@ -4217,22 +4216,13 @@ bool GdbEngine::startGdb(const QStringList &args, const QString &gdb, const DebuggerStartParameters &sp = startParameters(); m_gdb = QString::fromLocal8Bit(qgetenv("QTC_DEBUGGER_PATH")); if (m_gdb.isEmpty() && sp.startMode != StartRemoteGdb) { - // We want the MinGW gdb also in case we got started using - // some compatible ABI. - Abi abi = startParameters().toolChainAbi; - if (abi.os() == Abi::WindowsOS) { - if (abi.osFlavor() == Abi::UnknownFlavor - || abi.osFlavor() == Abi::WindowsMsvcFlavor) - abi = Abi(abi.architecture(), abi.os(), Abi::WindowsMSysFlavor, - abi.binaryFormat(), abi.wordWidth()); - } - m_gdb = debuggerCore()->debuggerForAbi(abi); + m_gdb = debuggerCore()->debuggerForAbi(startParameters().toolChainAbi, GdbEngineType); } if (m_gdb.isEmpty()) m_gdb = gdb; if (m_gdb.isEmpty()) { handleAdapterStartFailed( - msgNoBinaryForToolChain(sp.toolChainAbi), + msgNoGdbBinaryForToolChain(sp.toolChainAbi), _(Constants::DEBUGGER_COMMON_SETTINGS_ID)); return false; } diff --git a/src/plugins/debugger/qml/qmlcppengine.cpp b/src/plugins/debugger/qml/qmlcppengine.cpp index 96d63357bb837d99bb7f1c2ad14e629be7f9a287..9d39a2e5b4ca0681f11577c87b634201eb67fcee 100644 --- a/src/plugins/debugger/qml/qmlcppengine.cpp +++ b/src/plugins/debugger/qml/qmlcppengine.cpp @@ -32,7 +32,7 @@ **************************************************************************/ #include "qmlcppengine.h" - +#include "debuggerruncontrolfactory.h" #include "debuggercore.h" #include "debuggerstartparameters.h" #include "stackhandler.h" @@ -40,7 +40,6 @@ #include <utils/qtcassert.h> - namespace Debugger { namespace Internal { @@ -50,16 +49,14 @@ enum { debug = 0 }; const int ConnectionWaitTimeMs = 5000; -DebuggerEngine *createCdbEngine(const DebuggerStartParameters &, - DebuggerEngine *masterEngine, QString *); -DebuggerEngine *createGdbEngine(const DebuggerStartParameters &, - DebuggerEngine *masterEngine); QmlEngine *createQmlEngine(const DebuggerStartParameters &, DebuggerEngine *masterEngine); -DebuggerEngine *createQmlCppEngine(const DebuggerStartParameters &sp) +DebuggerEngine *createQmlCppEngine(const DebuggerStartParameters &sp, + DebuggerEngineType slaveEngineType, + QString *errorMessage) { - QmlCppEngine *newEngine = new QmlCppEngine(sp); + QmlCppEngine *newEngine = new QmlCppEngine(sp, slaveEngineType, errorMessage); if (newEngine->cppEngine()) return newEngine; delete newEngine; @@ -98,32 +95,10 @@ private: QmlCppEnginePrivate::QmlCppEnginePrivate(QmlCppEngine *parent, const DebuggerStartParameters &sp) - : q(parent) + : q(parent), m_qmlEngine(createQmlEngine(sp, q)), + m_cppEngine(0), m_activeEngine(0) { - m_stackBoundary = 0; - m_cppEngine = 0; - m_activeEngine = 0; - m_qmlEngine = createQmlEngine(sp, q); - - if (sp.cppEngineType == GdbEngineType) { - m_cppEngine = createGdbEngine(sp, q); - } else { - QString errorMessage; - m_cppEngine = createCdbEngine(sp, q, &errorMessage); - if (!m_cppEngine) { - qWarning("%s", qPrintable(errorMessage)); - return; - } - } - - m_activeEngine = m_cppEngine; - - connect(m_cppEngine->stackHandler()->model(), SIGNAL(modelReset()), - SLOT(cppStackChanged()), Qt::QueuedConnection); - connect(m_qmlEngine->stackHandler()->model(), SIGNAL(modelReset()), - SLOT(qmlStackChanged()), Qt::QueuedConnection); - connect(m_cppEngine, SIGNAL(stackFrameCompleted()), q, SIGNAL(stackFrameCompleted())); - connect(m_qmlEngine, SIGNAL(stackFrameCompleted()), q, SIGNAL(stackFrameCompleted())); + setObjectName(QLatin1String("QmlCppEnginePrivate")); } void QmlCppEnginePrivate::cppStackChanged() @@ -158,12 +133,25 @@ void QmlCppEnginePrivate::qmlStackChanged() // //////////////////////////////////////////////////////////////////////// -QmlCppEngine::QmlCppEngine(const DebuggerStartParameters &sp) +QmlCppEngine::QmlCppEngine(const DebuggerStartParameters &sp, + DebuggerEngineType slaveEngineType, + QString *errorMessage) : DebuggerEngine(sp), d(new QmlCppEnginePrivate(this, sp)) { -// setStateDebugging(true); -// d->m_cppEngine->setStateDebugging(true); -// d->m_qmlEngine->setStateDebugging(true); + setObjectName(QLatin1String("QmlCppEngine")); + d->m_cppEngine = DebuggerRunControlFactory::createEngine(slaveEngineType, sp, this, errorMessage); + if (!d->m_cppEngine) { + *errorMessage = tr("The slave debugging engine requires for combined QML/C++-Debugging could not be created:").arg(*errorMessage); + return; + } + d->m_activeEngine = d->m_cppEngine; + + connect(d->m_cppEngine->stackHandler()->model(), SIGNAL(modelReset()), + d.data(), SLOT(cppStackChanged()), Qt::QueuedConnection); + connect(d->m_qmlEngine->stackHandler()->model(), SIGNAL(modelReset()), + d.data(), SLOT(qmlStackChanged()), Qt::QueuedConnection); + connect(d->m_cppEngine, SIGNAL(stackFrameCompleted()), this, SIGNAL(stackFrameCompleted())); + connect(d->m_qmlEngine, SIGNAL(stackFrameCompleted()), this, SIGNAL(stackFrameCompleted())); } QmlCppEngine::~QmlCppEngine() diff --git a/src/plugins/debugger/qml/qmlcppengine.h b/src/plugins/debugger/qml/qmlcppengine.h index c946b2fde317891993bca8084744711c26c51154..822787b51fca7541d3ae0c9697b3548d6030f35d 100644 --- a/src/plugins/debugger/qml/qmlcppengine.h +++ b/src/plugins/debugger/qml/qmlcppengine.h @@ -48,7 +48,9 @@ class DEBUGGER_EXPORT QmlCppEngine : public DebuggerEngine Q_OBJECT public: - explicit QmlCppEngine(const DebuggerStartParameters &sp); + explicit QmlCppEngine(const DebuggerStartParameters &sp, + DebuggerEngineType slaveEngineType, + QString *errorMessage); ~QmlCppEngine(); bool setToolTipExpression(const QPoint &mousePos, diff --git a/src/plugins/debugger/startexternaldialog.ui b/src/plugins/debugger/startexternaldialog.ui index fcde484ce73fad1378277184ec08e6568dd3da38..6e9c94dd95c08a6af742eb210161d7b92e765ad4 100644 --- a/src/plugins/debugger/startexternaldialog.ui +++ b/src/plugins/debugger/startexternaldialog.ui @@ -6,42 +6,45 @@ <rect> <x>0</x> <y>0</y> - <width>425</width> - <height>151</height> + <width>443</width> + <height>213</height> </rect> </property> <property name="windowTitle"> <string>Start Debugger</string> </property> - <layout class="QVBoxLayout"> - <property name="spacing"> - <number>6</number> - </property> - <property name="margin"> - <number>9</number> - </property> + <layout class="QVBoxLayout" name="verticalLayout"> <item> - <layout class="QGridLayout"> - <property name="margin"> - <number>0</number> + <layout class="QFormLayout" name="formLayout"> + <property name="horizontalSpacing"> + <number>6</number> </property> - <property name="spacing"> + <property name="verticalSpacing"> <number>6</number> </property> + <property name="margin"> + <number>0</number> + </property> <item row="0" column="0"> <widget class="QLabel" name="execLabel"> <property name="text"> - <string>Executable:</string> + <string>&Executable:</string> + </property> + <property name="buddy"> + <cstring>execFile</cstring> </property> </widget> </item> <item row="0" column="1"> - <widget class="Utils::PathChooser" name="execFile" native="true"/> + <widget class="Utils::PathChooser" name="execFile"/> </item> <item row="1" column="0"> <widget class="QLabel" name="argsLabel"> <property name="text"> - <string>Arguments:</string> + <string>&Arguments:</string> + </property> + <property name="buddy"> + <cstring>argsEdit</cstring> </property> </widget> </item> @@ -51,24 +54,43 @@ <item row="2" column="0"> <widget class="QLabel" name="workingDirectoryLabel"> <property name="text"> - <string>Working directory:</string> + <string>&Working directory:</string> + </property> + <property name="buddy"> + <cstring>workingDirectory</cstring> </property> </widget> </item> <item row="2" column="1"> - <widget class="Utils::PathChooser" name="workingDirectory" native="true"/> + <widget class="Utils::PathChooser" name="workingDirectory"/> </item> - <item row="3" column="1"> + <item row="4" column="0"> + <widget class="QLabel" name="labelBreakAtMain"> + <property name="text"> + <string>Break at '&main':</string> + </property> + <property name="buddy"> + <cstring>checkBoxBreakAtMain</cstring> + </property> + </widget> + </item> + <item row="4" column="1"> <widget class="QCheckBox" name="checkBoxBreakAtMain"> <property name="text"> <string/> </property> </widget> </item> + <item row="3" column="1"> + <widget class="Debugger::Internal::DebuggerToolChainComboBox" name="toolChainComboBox"/> + </item> <item row="3" column="0"> - <widget class="QLabel" name="labelBreakAtMain"> + <widget class="QLabel" name="toolChainLabel"> <property name="text"> - <string>Break at 'main':</string> + <string>&ToolChain:</string> + </property> + <property name="buddy"> + <cstring>toolChainComboBox</cstring> </property> </widget> </item> @@ -81,8 +103,8 @@ </property> <property name="sizeHint" stdset="0"> <size> - <width>407</width> - <height>16</height> + <width>0</width> + <height>0</height> </size> </property> </spacer> @@ -113,6 +135,11 @@ <header location="global">utils/pathchooser.h</header> <container>1</container> </customwidget> + <customwidget> + <class>Debugger::Internal::DebuggerToolChainComboBox</class> + <extends>QComboBox</extends> + <header>debuggertoolchaincombobox.h</header> + </customwidget> </customwidgets> <resources/> <connections/> diff --git a/src/plugins/debugger/startremotedialog.ui b/src/plugins/debugger/startremotedialog.ui index f02da26c86fa53f4d5eb6237b95bb754bd6d9bfe..8495cc69a47a4b569ab1085cd3b588b69c587262 100644 --- a/src/plugins/debugger/startremotedialog.ui +++ b/src/plugins/debugger/startremotedialog.ui @@ -6,8 +6,8 @@ <rect> <x>0</x> <y>0</y> - <width>446</width> - <height>269</height> + <width>476</width> + <height>294</height> </rect> </property> <property name="windowTitle"> @@ -19,27 +19,36 @@ <item row="0" column="0"> <widget class="QLabel" name="debuggerLabel"> <property name="text"> - <string>Debugger:</string> + <string>&Debugger:</string> + </property> + <property name="buddy"> + <cstring>debuggerPathChooser</cstring> </property> </widget> </item> <item row="0" column="1"> - <widget class="Utils::PathChooser" name="debuggerPathChooser" native="true"/> + <widget class="Utils::PathChooser" name="debuggerPathChooser"/> </item> <item row="1" column="0"> <widget class="QLabel" name="executableLabel"> <property name="text"> - <string>Local executable:</string> + <string>Local &executable:</string> + </property> + <property name="buddy"> + <cstring>executablePathChooser</cstring> </property> </widget> </item> <item row="1" column="1"> - <widget class="Utils::PathChooser" name="executablePathChooser" native="true"/> + <widget class="Utils::PathChooser" name="executablePathChooser"/> </item> <item row="2" column="0"> <widget class="QLabel" name="channelLabel"> <property name="text"> - <string>Host and port:</string> + <string>&Host and port:</string> + </property> + <property name="buddy"> + <cstring>channelLineEdit</cstring> </property> </widget> </item> @@ -53,7 +62,10 @@ <item row="3" column="0"> <widget class="QLabel" name="architectureLabel"> <property name="text"> - <string>Architecture:</string> + <string>&Architecture:</string> + </property> + <property name="buddy"> + <cstring>architectureComboBox</cstring> </property> </widget> </item> @@ -67,7 +79,10 @@ <item row="4" column="0"> <widget class="QLabel" name="gnuTargetLabel"> <property name="text"> - <string>GNU target</string> + <string>&GNU target</string> + </property> + <property name="buddy"> + <cstring>gnuTargetComboBox</cstring> </property> </widget> </item> @@ -81,17 +96,23 @@ <item row="5" column="0"> <widget class="QLabel" name="sysrootLabel"> <property name="text"> - <string>Sysroot:</string> + <string>Sys&root:</string> + </property> + <property name="buddy"> + <cstring>sysrootPathChooser</cstring> </property> </widget> </item> <item row="5" column="1"> - <widget class="Utils::PathChooser" name="sysrootPathChooser" native="true"/> + <widget class="Utils::PathChooser" name="sysrootPathChooser"/> </item> <item row="6" column="0"> <widget class="QLabel" name="useServerStartScriptLabel"> <property name="text"> - <string>Use server start script:</string> + <string>&Use server start script:</string> + </property> + <property name="buddy"> + <cstring>useServerStartScriptCheckBox</cstring> </property> </widget> </item> @@ -101,12 +122,15 @@ <item row="7" column="0"> <widget class="QLabel" name="serverStartScriptLabel"> <property name="text"> - <string>Server start script:</string> + <string>Server st&art script:</string> + </property> + <property name="buddy"> + <cstring>serverStartScript</cstring> </property> </widget> </item> <item row="7" column="1"> - <widget class="Utils::PathChooser" name="serverStartScript" native="true"/> + <widget class="Utils::PathChooser" name="serverStartScript"/> </item> </layout> </item> @@ -127,6 +151,7 @@ <class>Utils::PathChooser</class> <extends>QWidget</extends> <header location="global">utils/pathchooser.h</header> + <container>1</container> </customwidget> </customwidgets> <resources/> diff --git a/src/plugins/debugger/startremoteenginedialog.ui b/src/plugins/debugger/startremoteenginedialog.ui index ff7fc66936076fc956f72a8c4f024668e91ca089..83d647e0fc0e2f2132f4d601d3ca71ab97f14037 100644 --- a/src/plugins/debugger/startremoteenginedialog.ui +++ b/src/plugins/debugger/startremoteenginedialog.ui @@ -6,95 +6,114 @@ <rect> <x>0</x> <y>0</y> - <width>884</width> - <height>601</height> + <width>233</width> + <height>207</height> </rect> </property> <property name="windowTitle"> <string>Start Remote Engine</string> </property> - <layout class="QGridLayout" name="gridLayout"> - <item row="0" column="0"> - <widget class="QLabel" name="channelLabel"> - <property name="text"> - <string>Host:</string> - </property> - </widget> - </item> - <item row="8" column="0" colspan="4"> - <widget class="QDialogButtonBox" name="buttonBox"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="standardButtons"> - <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> - </property> - </widget> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QFormLayout" name="formLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="channelLabel"> + <property name="text"> + <string>&Host:</string> + </property> + <property name="buddy"> + <cstring>host</cstring> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLineEdit" name="host"> + <property name="text"> + <string notr="true"/> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="userLabel"> + <property name="text"> + <string>&Username:</string> + </property> + <property name="buddy"> + <cstring>username</cstring> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLineEdit" name="username"/> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="passwordLabel"> + <property name="text"> + <string>&Password:</string> + </property> + <property name="buddy"> + <cstring>password</cstring> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLineEdit" name="password"> + <property name="echoMode"> + <enum>QLineEdit::Password</enum> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="engineLabel"> + <property name="text"> + <string>&Engine path:</string> + </property> + <property name="buddy"> + <cstring>enginepath</cstring> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QLineEdit" name="enginepath"/> + </item> + <item row="4" column="0"> + <widget class="QLabel" name="inferiorLabel"> + <property name="text"> + <string>&Inferior path:</string> + </property> + <property name="buddy"> + <cstring>inferiorpath</cstring> + </property> + </widget> + </item> + <item row="4" column="1"> + <widget class="QLineEdit" name="inferiorpath"/> + </item> + </layout> </item> - <item row="3" column="0"> - <widget class="QLabel" name="label"> - <property name="text"> - <string>Engine path:</string> - </property> - </widget> - </item> - <item row="4" column="0"> - <widget class="QLabel" name="label_2"> - <property name="text"> - <string>Inferior path:</string> - </property> - </widget> - </item> - <item row="4" column="2"> - <widget class="QLineEdit" name="inferiorpath"/> - </item> - <item row="3" column="2"> - <widget class="QLineEdit" name="enginepath"/> - </item> - <item row="0" column="2"> - <widget class="QLineEdit" name="host"> - <property name="text"> - <string notr="true"/> - </property> - </widget> - </item> - <item row="2" column="2"> - <widget class="QLineEdit" name="password"> - <property name="echoMode"> - <enum>QLineEdit::Password</enum> - </property> - </widget> - </item> - <item row="1" column="2"> - <widget class="QLineEdit" name="username"/> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="label_3"> - <property name="text"> - <string>Username:</string> - </property> - </widget> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="label_4"> - <property name="text"> - <string>Password:</string> - </property> - </widget> - </item> - <item row="6" column="1" colspan="2"> + <item> <spacer name="verticalSpacer"> <property name="orientation"> <enum>Qt::Vertical</enum> </property> <property name="sizeHint" stdset="0"> <size> - <width>20</width> - <height>40</height> + <width>0</width> + <height>0</height> </size> </property> </spacer> </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> </layout> </widget> <tabstops> diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp index 69fe327193dbf9d2fc156068387f14b6f8472653..44c7c564d246d90a124b9efb694434d3bd8d5440 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp @@ -468,7 +468,6 @@ static Debugger::DebuggerStartParameters s60DebuggerStartParams(const S60DeviceR sp.toolChainAbi = rc->abi(); sp.executable = debugFileName; sp.executableUid = rc->executableUid(); - sp.enabledEngines = Debugger::GdbEngineType; sp.serverAddress = activeDeployConf->deviceAddress(); sp.serverPort = activeDeployConf->devicePort().toInt(); @@ -489,8 +488,9 @@ static Debugger::DebuggerStartParameters s60DebuggerStartParams(const S60DeviceR } S60DeviceDebugRunControl::S60DeviceDebugRunControl(S60DeviceRunConfiguration *rc, - const QString &) : - Debugger::DebuggerRunControl(rc, s60DebuggerStartParams(rc)) + const Debugger::DebuggerStartParameters &sp, + const QPair<Debugger::DebuggerEngineType, Debugger::DebuggerEngineType> &masterSlaveEngineTypes) : + Debugger::DebuggerRunControl(rc, sp, masterSlaveEngineTypes) { if (startParameters().symbolFileName.isEmpty()) { const QString msg = tr("Warning: Cannot locate the symbol file belonging to %1."). @@ -501,23 +501,47 @@ S60DeviceDebugRunControl::S60DeviceDebugRunControl(S60DeviceRunConfiguration *rc void S60DeviceDebugRunControl::start() { - Debugger::ConfigurationCheck check = - Debugger::checkDebugConfiguration(startParameters().toolChainAbi); + appendMessage(tr("Launching debugger..."), NormalMessageFormat); + Debugger::DebuggerRunControl::start(); +} + +bool S60DeviceDebugRunControl::promptToStop(bool *) const +{ + // We override the settings prompt + return Debugger::DebuggerRunControl::promptToStop(0); +} + +S60DeviceDebugRunControlFactory::S60DeviceDebugRunControlFactory(QObject *parent) : + IRunControlFactory(parent) +{ +} + +bool S60DeviceDebugRunControlFactory::canRun(ProjectExplorer::RunConfiguration *runConfiguration, const QString &mode) const +{ + return mode == QLatin1String(Debugger::Constants::DEBUGMODE) + && qobject_cast<S60DeviceRunConfiguration *>(runConfiguration) != 0; +} +ProjectExplorer::RunControl* S60DeviceDebugRunControlFactory::create(ProjectExplorer::RunConfiguration *runConfiguration, const QString &mode) +{ + S60DeviceRunConfiguration *rc = qobject_cast<S60DeviceRunConfiguration *>(runConfiguration); + QTC_ASSERT(rc && mode == QLatin1String(Debugger::Constants::DEBUGMODE), return 0); + const Debugger::DebuggerStartParameters startParameters = s60DebuggerStartParams(rc); + const Debugger::ConfigurationCheck check = Debugger::checkDebugConfiguration(startParameters); if (!check) { - appendMessage(check.errorMessage, ErrorMessageFormat); - emit finished(); Core::ICore::instance()->showWarningWithOptions(tr("Debugger for Symbian Platform"), check.errorMessage, QString(), check.settingsCategory, check.settingsPage); - return; + return 0; } + return new S60DeviceDebugRunControl(rc, startParameters, check.masterSlaveEngineTypes); +} - appendMessage(tr("Launching debugger..."), NormalMessageFormat); - Debugger::DebuggerRunControl::start(); +QString S60DeviceDebugRunControlFactory::displayName() const +{ + return tr("Debug on Device"); } -bool S60DeviceDebugRunControl::promptToStop(bool *) const +QWidget *S60DeviceDebugRunControlFactory::createConfigurationWidget(ProjectExplorer::RunConfiguration * /*runConfiguration */) { - // We override the settings prompt - return Debugger::DebuggerRunControl::promptToStop(0); + return 0; } diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h index 71de1644c0e412cc3932e16bed53bdd9aef649a1..4998c1bf633f0f962c9042eecfb2430b40d60812 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h +++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h @@ -136,11 +136,23 @@ class S60DeviceDebugRunControl : public Debugger::DebuggerRunControl Q_OBJECT public: explicit S60DeviceDebugRunControl(S60DeviceRunConfiguration *runConfiguration, - const QString &mode); + const Debugger::DebuggerStartParameters &sp, + const QPair<Debugger::DebuggerEngineType, Debugger::DebuggerEngineType> &masterSlaveEngineTypes); virtual void start(); virtual bool promptToStop(bool *optionalPrompt = 0) const; }; +class S60DeviceDebugRunControlFactory : public ProjectExplorer::IRunControlFactory +{ +public: + explicit S60DeviceDebugRunControlFactory(QObject *parent = 0); + bool canRun(ProjectExplorer::RunConfiguration *runConfiguration, const QString &mode) const; + + ProjectExplorer::RunControl* create(ProjectExplorer::RunConfiguration *runConfiguration, const QString &mode); + QString displayName() const; + QWidget *createConfigurationWidget(ProjectExplorer::RunConfiguration * /*runConfiguration */); +}; + } // namespace Internal } // namespace Qt4ProjectManager diff --git a/src/plugins/qt4projectmanager/qt-s60/s60manager.cpp b/src/plugins/qt4projectmanager/qt-s60/s60manager.cpp index 2b10720bfdb1639d08dd3a39fc8a6074ac80b018..0fc522a3a71242d204105339ee159f11c6822ade 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60manager.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60manager.cpp @@ -131,9 +131,7 @@ S60Manager::S60Manager(QObject *parent) addAutoReleasedObject(new S60CreatePackageStepFactory); addAutoReleasedObject(new S60DeployStepFactory); - addAutoReleasedObject(new RunControlFactory<S60DeviceDebugRunControl, S60DeviceRunConfiguration> - (QLatin1String(Debugger::Constants::DEBUGMODE), - tr("Debug on Device"), parent)); + addAutoReleasedObject(new S60DeviceDebugRunControlFactory); addAutoReleasedObject(new Qt4SymbianTargetFactory); updateQtVersions();