diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp index 754c990fe4464357a59d6ea79169412b4dfec661..05a659b5246b67f9c29099a887ca8d4cfbe4d6e6 100644 --- a/src/plugins/debugger/debuggerengine.cpp +++ b/src/plugins/debugger/debuggerengine.cpp @@ -520,6 +520,8 @@ void DebuggerEngine::startDebugger(DebuggerRunControl *runControl) d->m_inferiorPid = d->m_startParameters.attachPID > 0 ? d->m_startParameters.attachPID : 0; + if (d->m_inferiorPid) + d->m_runControl->setApplicationProcessHandle(ProcessHandle(d->m_inferiorPid)); if (!d->m_startParameters.environment.size()) d->m_startParameters.environment = Utils::Environment(); @@ -1174,6 +1176,7 @@ void DebuggerEngine::notifyInferiorPid(qint64 pid) return; d->m_inferiorPid = pid; if (pid) { + d->m_runControl->setApplicationProcessHandle(ProcessHandle(pid)); showMessage(tr("Taking notice of pid %1").arg(pid)); if (d->m_startParameters.startMode == StartInternal || d->m_startParameters.startMode == StartExternal diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index d0c315377f209d8844965ade1cb06537bcf62bb7..aecdd665c774d8ac6ea99acb5dc694a5f5470154 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -688,9 +688,10 @@ public slots: void startRemoteApplication(); void startRemoteEngine(); void attachExternalApplication(); + Q_SLOT void attachExternalApplication(ProjectExplorer::RunControl *rc); void attachExternalApplication(qint64 pid, const QString &binary, - const ProjectExplorer::Abi &abi = ProjectExplorer::Abi(), - const QString &debuggerCommand = QString()); + const ProjectExplorer::Abi &abi, + const QString &debuggerCommand); void runScheduled(); void attachCore(); void attachCore(const QString &core, const QString &exeFileName, @@ -1065,6 +1066,7 @@ DebuggerPluginPrivate::DebuggerPluginPrivate(DebuggerPlugin *plugin) : m_dummyEngine(0), m_globalDebuggerOptions(new GlobalDebuggerOptions) { + setObjectName("DebuggerCore"); qRegisterMetaType("WatchData"); qRegisterMetaType("ContextData"); qRegisterMetaType("DebuggerStartParameters"); @@ -1434,6 +1436,18 @@ void DebuggerPluginPrivate::attachExternalApplication(qint64 pid, const QString startDebugger(rc); } +void DebuggerPluginPrivate::attachExternalApplication(ProjectExplorer::RunControl *rc) +{ + DebuggerStartParameters sp; + sp.attachPID = rc->applicationProcessHandle().pid(); + sp.displayName = tr("Debugger attached to %1").arg(rc->displayName()); + sp.startMode = AttachExternal; + //sp.toolChainAbi = abiOfBinary(sp.executable); + sp.toolChainAbi = ProjectExplorer::Abi::hostAbi(); // FIXME: Extract from RunControl? + if (DebuggerRunControl *rc = createDebugger(sp)) + startDebugger(rc); +} + void DebuggerPluginPrivate::attachCore() { AttachCoreDialog dlg(mainWindow()); @@ -2538,6 +2552,8 @@ void DebuggerPluginPrivate::extensionsInitialized() Core::ActionManager *am = core->actionManager(); QTC_ASSERT(am, return); + m_plugin->addObject(this); + const Context globalcontext(CC::C_GLOBAL); const Context cppDebuggercontext(C_CPPDEBUGGER); const Context qmlDebuggerContext(C_QMLDEBUGGER); @@ -3128,6 +3144,7 @@ void DebuggerPluginPrivate::showModuleSymbols(const QString &moduleName, void DebuggerPluginPrivate::aboutToShutdown() { + m_plugin->removeObject(this); disconnect(sessionManager(), SIGNAL(startupProjectChanged(ProjectExplorer::Project*)), this, 0); diff --git a/src/plugins/projectexplorer/appoutputpane.cpp b/src/plugins/projectexplorer/appoutputpane.cpp index 67171f20b58dfe262e88fa1cc06e7f470a20c9d7..61b500b03aa13c5cf364f59e6187829c63f870cb 100644 --- a/src/plugins/projectexplorer/appoutputpane.cpp +++ b/src/plugins/projectexplorer/appoutputpane.cpp @@ -46,6 +46,8 @@ #include #include #include +#include +#include #include #include @@ -62,6 +64,11 @@ enum { debug = 0 }; using namespace ProjectExplorer; using namespace ProjectExplorer::Internal; +static QObject *debuggerCore() +{ + return ExtensionSystem::PluginManager::instance()->getObjectByName("DebuggerCore"); +} + AppOutputPane::RunControlTab::RunControlTab(RunControl *rc, Core::OutputWindow *w) : runControl(rc), window(w), asyncClosing(false) { @@ -72,7 +79,8 @@ AppOutputPane::AppOutputPane() : m_tabWidget(new QTabWidget), m_stopAction(new QAction(QIcon(QLatin1String(Constants::ICON_STOP)), tr("Stop"), this)), m_reRunButton(new QToolButton), - m_stopButton(new QToolButton) + m_stopButton(new QToolButton), + m_attachButton(new QToolButton) { // Rerun m_reRunButton->setIcon(QIcon(ProjectExplorer::Constants::ICON_RUN_SMALL)); @@ -97,6 +105,15 @@ AppOutputPane::AppOutputPane() : connect(m_stopAction, SIGNAL(triggered()), this, SLOT(stopRunControl())); + // Attach + m_attachButton->setToolTip(tr("Attach debugger to this process")); + m_attachButton->setEnabled(false); + m_attachButton->setIcon(QIcon(ProjectExplorer::Constants::ICON_DEBUG_SMALL)); + m_attachButton->setAutoRaise(true); + + connect(m_attachButton, SIGNAL(clicked()), + this, SLOT(attachToRunControl())); + // Spacer (?) QVBoxLayout *layout = new QVBoxLayout; @@ -185,7 +202,7 @@ QWidget *AppOutputPane::outputWidget(QWidget *) QList AppOutputPane::toolBarWidgets() const { - return QList() << m_reRunButton << m_stopButton; + return QList() << m_reRunButton << m_stopButton << m_attachButton; } QString AppOutputPane::displayName() const @@ -313,6 +330,15 @@ void AppOutputPane::reRunRunControl() tab.runControl->start(); } +void AppOutputPane::attachToRunControl() +{ + const int index = currentIndex(); + QTC_ASSERT(index != -1, return); + ProjectExplorer::RunControl *rc = m_runControlTabs.at(index).runControl; + QTC_ASSERT(rc->isRunning(), return); + ExtensionSystem::Invoker(debuggerCore(), "attachExternalApplication", rc); +} + void AppOutputPane::stopRunControl() { const int index = currentIndex(); @@ -399,6 +425,7 @@ void AppOutputPane::tabChanged(int i) if (i == -1) { m_stopAction->setEnabled(false); m_reRunButton->setEnabled(false); + m_attachButton->setEnabled(false); } else { const int index = indexOf(m_tabWidget->widget(i)); QTC_ASSERT(index != -1, return; ) @@ -407,6 +434,7 @@ void AppOutputPane::tabChanged(int i) m_stopAction->setEnabled(rc->isRunning()); m_reRunButton->setEnabled(!rc->isRunning()); m_reRunButton->setIcon(rc->icon()); + m_attachButton->setEnabled(debuggerCore()); } } @@ -416,6 +444,7 @@ void AppOutputPane::runControlStarted() if (current && current == sender()) { m_reRunButton->setEnabled(false); m_stopAction->setEnabled(true); + m_attachButton->setEnabled(debuggerCore()); m_reRunButton->setIcon(current->icon()); } } @@ -437,6 +466,7 @@ void AppOutputPane::runControlFinished() if (current && current == sender()) { m_reRunButton->setEnabled(true); m_stopAction->setEnabled(false); + m_attachButton->setEnabled(false); m_reRunButton->setIcon(current->icon()); } // Check for asynchronous close. Close the tab. diff --git a/src/plugins/projectexplorer/appoutputpane.h b/src/plugins/projectexplorer/appoutputpane.h index bf36b41c6981cd6dd6b4e4f35e3f8a63667d23ba..f16c866fce20b7b3af0f996cc3ea548df195438b 100644 --- a/src/plugins/projectexplorer/appoutputpane.h +++ b/src/plugins/projectexplorer/appoutputpane.h @@ -97,6 +97,7 @@ public slots: private slots: void reRunRunControl(); void stopRunControl(); + void attachToRunControl(); bool closeTab(int index); void tabChanged(int); void runControlStarted(); @@ -132,6 +133,7 @@ private: QAction *m_stopAction; QToolButton *m_reRunButton; QToolButton *m_stopButton; + QToolButton *m_attachButton; }; } // namespace Internal diff --git a/src/plugins/projectexplorer/localapplicationruncontrol.cpp b/src/plugins/projectexplorer/localapplicationruncontrol.cpp index 153bb168ef86beaaedc62c329bc4da81ff4342af..dffb39f204fa093da0bd7cdaf23def035a2f4037 100644 --- a/src/plugins/projectexplorer/localapplicationruncontrol.cpp +++ b/src/plugins/projectexplorer/localapplicationruncontrol.cpp @@ -109,6 +109,7 @@ void LocalApplicationRunControl::start() emit finished(); } else { m_applicationLauncher.start(m_runMode, m_executable, m_commandLineArguments); + setApplicationProcessHandle(ProcessHandle(m_applicationLauncher.applicationPID())); QString msg = tr("Starting %1...\n").arg(QDir::toNativeSeparators(m_executable)); appendMessage(msg, Utils::NormalMessageFormat); } diff --git a/src/plugins/projectexplorer/localapplicationruncontrol.h b/src/plugins/projectexplorer/localapplicationruncontrol.h index 8397f0fd3afd170fd4a8559ebff5a44e094221d0..e8a9f05ed73e8e18034f744ef36632bc3436288c 100644 --- a/src/plugins/projectexplorer/localapplicationruncontrol.h +++ b/src/plugins/projectexplorer/localapplicationruncontrol.h @@ -71,6 +71,7 @@ private: QString m_executable; QString m_commandLineArguments; ProjectExplorer::ApplicationLauncher::Mode m_runMode; + ProcessHandle m_applicationProcessHandle; }; } // namespace Internal diff --git a/src/plugins/projectexplorer/runconfiguration.cpp b/src/plugins/projectexplorer/runconfiguration.cpp index c4f1f2cd7e96ed9a2274f7d2896f89dc0e5d7e62..42bb2bc277e44fed645d7424fd308d2870347c8d 100644 --- a/src/plugins/projectexplorer/runconfiguration.cpp +++ b/src/plugins/projectexplorer/runconfiguration.cpp @@ -150,6 +150,12 @@ IRunConfigurationFactory *findRunConfigurationFactory(RunConfigurationFactoryMat } // namespace +/*! + \class ProjectExplorer::ProcessHandle + \brief Helper class to describe a process. + +*/ + /*! \class ProjectExplorer::RunConfiguration \brief Base class for a run configuration. A run configuration specifies how a @@ -351,6 +357,7 @@ Utils::OutputFormatter *RunConfiguration::createOutputFormatter() const return new Utils::OutputFormatter(); } + /*! \class ProjectExplorer::IRunConfigurationFactory @@ -492,6 +499,16 @@ QString RunControl::displayName() const return m_displayName; } +ProcessHandle RunControl::applicationProcessHandle() const +{ + return m_applicationProcessHandle; +} + +void RunControl::setApplicationProcessHandle(const ProcessHandle &handle) +{ + m_applicationProcessHandle = handle; +} + bool RunControl::promptToStop(bool *optionalPrompt) const { QTC_ASSERT(isRunning(), return true;) diff --git a/src/plugins/projectexplorer/runconfiguration.h b/src/plugins/projectexplorer/runconfiguration.h index 862edd282182c44f060a4bced8ffe445e8b5f4c7..0ae9a88983cb6a6c198f14dfd8c70e4e010e95da 100644 --- a/src/plugins/projectexplorer/runconfiguration.h +++ b/src/plugins/projectexplorer/runconfiguration.h @@ -51,6 +51,20 @@ class IRunConfigurationAspect; class RunControl; class Target; +// FIXME: This should also contain a handle to an remote device if used. +class PROJECTEXPLORER_EXPORT ProcessHandle +{ +public: + explicit ProcessHandle(quint64 pid = 0) : m_pid(pid) {} + + bool isValid() const { return m_pid != 0; } + void setPid(quint64 pid) { m_pid = pid; } + quint64 pid() const { return m_pid; } + +private: + quint64 m_pid; +}; + // Documentation inside. class PROJECTEXPLORER_EXPORT RunConfiguration : public ProjectConfiguration { @@ -210,6 +224,9 @@ public: virtual QString displayName() const; virtual QIcon icon() const = 0; + ProcessHandle applicationProcessHandle() const; + void setApplicationProcessHandle(const ProcessHandle &handle); + bool sameRunConfiguration(const RunControl *other) const; Utils::OutputFormatter *outputFormatter(); @@ -240,6 +257,9 @@ private: const QWeakPointer m_runConfiguration; Utils::OutputFormatter *m_outputFormatter; + // A handle to the actual application process. + ProcessHandle m_applicationProcessHandle; + #ifdef Q_OS_MAC //these two are used to bring apps in the foreground on Mac qint64 m_internalPid; @@ -251,5 +271,6 @@ private: // Allow a RunConfiguration to be stored in a QVariant Q_DECLARE_METATYPE(ProjectExplorer::RunConfiguration*) +Q_DECLARE_METATYPE(ProjectExplorer::RunControl*) #endif // RUNCONFIGURATION_H diff --git a/src/plugins/qmlprojectmanager/qmlprojectruncontrol.cpp b/src/plugins/qmlprojectmanager/qmlprojectruncontrol.cpp index 1a00a9f0ddfe40ac8f1703647809d8e65fff3a95..0685af95b6d09142288b2f37da192f725fbaad0c 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectruncontrol.cpp +++ b/src/plugins/qmlprojectmanager/qmlprojectruncontrol.cpp @@ -96,7 +96,7 @@ void QmlProjectRunControl::start() { m_applicationLauncher.start(ApplicationLauncher::Gui, m_executable, m_commandLineArguments); - + setApplicationProcessHandle(ProcessHandle(m_applicationLauncher.applicationPID())); emit started(); QString msg = tr("Starting %1 %2\n") .arg(QDir::toNativeSeparators(m_executable), m_commandLineArguments); diff --git a/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.cpp b/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.cpp index 11c38db1e95f5059fe75171ba9fbb4ae197a10bd..6d86d887fbadaf66e50abe2a0c89737fe7535854 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.cpp @@ -348,13 +348,14 @@ S60EmulatorRunControl::S60EmulatorRunControl(S60EmulatorRunConfiguration *runCon this, SLOT(slotAppendMessage(QString, Utils::OutputFormat))); connect(&m_applicationLauncher, SIGNAL(processExited(int)), this, SLOT(processExited(int))); - connect(&m_applicationLauncher, SIGNAL(bringToForegroundRequested(qint64)), - this, SLOT(bringApplicationToForeground(qint64))); + connect(&m_applicationLauncher, SIGNAL(bringToForegroundRequested(quint64)), + this, SLOT(bringApplicationToForeground(quint64))); } void S60EmulatorRunControl::start() { m_applicationLauncher.start(ApplicationLauncher::Gui, m_executable, QString()); + setApplicationProcessHandle(ProcessHandle(m_applicationLauncher.applicationPID())); emit started(); QString msg = tr("Starting %1...\n").arg(QDir::toNativeSeparators(m_executable));