diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp index 904ced335532b4d6afeba28b56affc44f0a96252..799537c99100be3f7450f684e26e62778122990b 100644 --- a/src/plugins/debugger/debuggerengine.cpp +++ b/src/plugins/debugger/debuggerengine.cpp @@ -1177,8 +1177,6 @@ void DebuggerEngine::notifyInferiorPid(qint64 pid) return; d->m_inferiorPid = pid; if (pid) { - if (d->m_runControl) - 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/projectexplorer/appoutputpane.cpp b/src/plugins/projectexplorer/appoutputpane.cpp index 99b62823584bf7fc61bcf1b4b87a24b87906f0b5..c8acfb71b51945de8d504296f742107bd93f4540 100644 --- a/src/plugins/projectexplorer/appoutputpane.cpp +++ b/src/plugins/projectexplorer/appoutputpane.cpp @@ -69,6 +69,13 @@ static QObject *debuggerCore() return ExtensionSystem::PluginManager::instance()->getObjectByName("DebuggerCore"); } +static QString msgAttachDebuggerTooltip(const QString &handleDescription = QString()) +{ + return handleDescription.isEmpty() ? + AppOutputPane::tr("Attach debugger to this process") : + AppOutputPane::tr("Attach debugger to %1").arg(handleDescription); +} + AppOutputPane::RunControlTab::RunControlTab(RunControl *rc, Core::OutputWindow *w) : runControl(rc), window(w), asyncClosing(false) { @@ -109,7 +116,7 @@ AppOutputPane::AppOutputPane() : this, SLOT(stopRunControl())); // Attach - m_attachButton->setToolTip(tr("Attach debugger to this process")); + m_attachButton->setToolTip(msgAttachDebuggerTooltip()); m_attachButton->setEnabled(false); m_attachButton->setIcon(QIcon(ProjectExplorer::Constants::ICON_DEBUG_SMALL)); m_attachButton->setAutoRaise(true); @@ -251,6 +258,8 @@ void AppOutputPane::createNewOutputWindow(RunControl *rc) this, SLOT(runControlStarted())); connect(rc, SIGNAL(finished()), this, SLOT(runControlFinished())); + connect(rc, SIGNAL(applicationProcessHandleChanged()), + this, SLOT(enableButtons())); connect(rc, SIGNAL(appendMessage(ProjectExplorer::RunControl*,QString,Utils::OutputFormat)), this, SLOT(appendMessage(ProjectExplorer::RunControl*,QString,Utils::OutputFormat))); @@ -423,33 +432,51 @@ void AppOutputPane::projectRemoved() tabChanged(m_tabWidget->currentIndex()); } -void AppOutputPane::tabChanged(int i) +void AppOutputPane::enableButtons() { - if (i == -1) { - m_stopAction->setEnabled(false); + const RunControl *rc = currentRunControl(); + const bool isRunning = rc && rc->isRunning(); + enableButtons(rc, isRunning); +} + +void AppOutputPane::enableButtons(const RunControl *rc /* = 0 */, bool isRunning /* = false */) +{ + if (rc) { + m_reRunButton->setEnabled(!isRunning); + m_reRunButton->setIcon(rc->icon()); + m_stopAction->setEnabled(isRunning); + if (isRunning && debuggerCore() && rc->applicationProcessHandle().isValid()) { + m_attachButton->setEnabled(true); + m_attachButton->setToolTip(msgAttachDebuggerTooltip(rc->applicationProcessHandle().toString())); + } else { + m_attachButton->setEnabled(false); + m_attachButton->setToolTip(msgAttachDebuggerTooltip()); + } + } else { m_reRunButton->setEnabled(false); + m_reRunButton->setIcon(QIcon(QLatin1String(ProjectExplorer::Constants::ICON_RUN_SMALL))); m_attachButton->setEnabled(false); - } else { - const int index = indexOf(m_tabWidget->widget(i)); - QTC_ASSERT(index != -1, return; ) + m_attachButton->setToolTip(msgAttachDebuggerTooltip()); + m_stopAction->setEnabled(false); + } +} - RunControl *rc = m_runControlTabs.at(index).runControl; - m_stopAction->setEnabled(rc->isRunning()); - m_reRunButton->setEnabled(!rc->isRunning()); - m_reRunButton->setIcon(rc->icon()); - m_attachButton->setEnabled(debuggerCore()); +void AppOutputPane::tabChanged(int i) +{ + const int index = indexOf(m_tabWidget->widget(i)); + if (i != -1) { + const RunControl *rc = m_runControlTabs.at(index).runControl; + enableButtons(rc, rc->isRunning()); + } else { + enableButtons(); } } void AppOutputPane::runControlStarted() { RunControl *current = currentRunControl(); - if (current && current == sender()) { - m_reRunButton->setEnabled(false); - m_stopAction->setEnabled(true); - m_attachButton->setEnabled(debuggerCore()); - m_reRunButton->setIcon(current->icon()); - } + if (current && current == sender()) + enableButtons(current, true); // RunControl::isRunning() cannot be trusted in signal handler. } void AppOutputPane::runControlFinished() @@ -466,12 +493,9 @@ void AppOutputPane::runControlFinished() qDebug() << "OutputPane::runControlFinished" << senderRunControl << senderIndex << " current " << current << m_runControlTabs.size(); - if (current && current == sender()) { - m_reRunButton->setEnabled(true); - m_stopAction->setEnabled(false); - m_attachButton->setEnabled(false); - m_reRunButton->setIcon(current->icon()); - } + if (current && current == sender()) + enableButtons(current, false); // RunControl::isRunning() cannot be trusted in signal handler. + // Check for asynchronous close. Close the tab. if (m_runControlTabs.at(senderIndex).asyncClosing) closeTab(tabWidgetIndexOf(senderIndex), CloseTabNoPrompt); diff --git a/src/plugins/projectexplorer/appoutputpane.h b/src/plugins/projectexplorer/appoutputpane.h index f16c866fce20b7b3af0f996cc3ea548df195438b..7336f23ea6ba67028552f620f83e3cf78d946aea 100644 --- a/src/plugins/projectexplorer/appoutputpane.h +++ b/src/plugins/projectexplorer/appoutputpane.h @@ -105,8 +105,11 @@ private slots: void aboutToUnloadSession(); void updateFromSettings(); + void enableButtons(); private: + void enableButtons(const RunControl *rc, bool isRunning); + struct RunControlTab { explicit RunControlTab(RunControl *runControl = 0, Core::OutputWindow *window = 0); diff --git a/src/plugins/projectexplorer/localapplicationruncontrol.cpp b/src/plugins/projectexplorer/localapplicationruncontrol.cpp index dffb39f204fa093da0bd7cdaf23def035a2f4037..b1ca9cb635da831c0cb532b7f2a6279a0deb6e9b 100644 --- a/src/plugins/projectexplorer/localapplicationruncontrol.cpp +++ b/src/plugins/projectexplorer/localapplicationruncontrol.cpp @@ -139,6 +139,7 @@ void LocalApplicationRunControl::slotAppendMessage(const QString &err, void LocalApplicationRunControl::processExited(int exitCode) { + setApplicationProcessHandle(ProcessHandle()); QString msg = tr("%1 exited with code %2\n") .arg(QDir::toNativeSeparators(m_executable)).arg(exitCode); appendMessage(msg, Utils::NormalMessageFormat); diff --git a/src/plugins/projectexplorer/runconfiguration.cpp b/src/plugins/projectexplorer/runconfiguration.cpp index 42bb2bc277e44fed645d7424fd308d2870347c8d..c9c93a0ea103d573a64f49493e1b19868cb24475 100644 --- a/src/plugins/projectexplorer/runconfiguration.cpp +++ b/src/plugins/projectexplorer/runconfiguration.cpp @@ -154,8 +154,43 @@ IRunConfigurationFactory *findRunConfigurationFactory(RunConfigurationFactoryMat \class ProjectExplorer::ProcessHandle \brief Helper class to describe a process. + Encapsulates parameters of a running process, local (PID) or remote (to be done, + address, port, etc). */ +ProcessHandle::ProcessHandle(quint64 pid) : + m_pid(pid) +{ +} + +bool ProcessHandle::isValid() const +{ + return m_pid != 0; +} + +void ProcessHandle::setPid(quint64 pid) +{ + m_pid = pid; +} + +quint64 ProcessHandle::pid() const +{ + return m_pid; +} + +QString ProcessHandle::toString() const +{ + if (m_pid) + return RunControl::tr("PID %1").arg(m_pid); + //: Invalid process handle. + return RunControl::tr("Invalid"); +} + +bool ProcessHandle::equals(const ProcessHandle &rhs) const +{ + return m_pid == rhs.m_pid; +} + /*! \class ProjectExplorer::RunConfiguration \brief Base class for a run configuration. A run configuration specifies how a @@ -506,7 +541,10 @@ ProcessHandle RunControl::applicationProcessHandle() const void RunControl::setApplicationProcessHandle(const ProcessHandle &handle) { - m_applicationProcessHandle = handle; + if (m_applicationProcessHandle != handle) { + m_applicationProcessHandle = handle; + emit applicationProcessHandleChanged(); + } } bool RunControl::promptToStop(bool *optionalPrompt) const diff --git a/src/plugins/projectexplorer/runconfiguration.h b/src/plugins/projectexplorer/runconfiguration.h index 0ae9a88983cb6a6c198f14dfd8c70e4e010e95da..b5fb55f77141ffdbdfdaf1824e8f327e9f01a91b 100644 --- a/src/plugins/projectexplorer/runconfiguration.h +++ b/src/plugins/projectexplorer/runconfiguration.h @@ -55,16 +55,22 @@ class Target; class PROJECTEXPLORER_EXPORT ProcessHandle { public: - explicit ProcessHandle(quint64 pid = 0) : m_pid(pid) {} + explicit ProcessHandle(quint64 pid = 0); - bool isValid() const { return m_pid != 0; } - void setPid(quint64 pid) { m_pid = pid; } - quint64 pid() const { return m_pid; } + bool isValid() const; + void setPid(quint64 pid); + quint64 pid() const; + QString toString() const; + + bool equals(const ProcessHandle &) const; private: quint64 m_pid; }; +inline bool operator==(const ProcessHandle &p1, const ProcessHandle &p2) { return p1.equals(p2); } +inline bool operator!=(const ProcessHandle &p1, const ProcessHandle &p2) { return !p1.equals(p2); } + // Documentation inside. class PROJECTEXPLORER_EXPORT RunConfiguration : public ProjectConfiguration { @@ -241,6 +247,7 @@ signals: const QString &msg, Utils::OutputFormat format); void started(); void finished(); + void applicationProcessHandleChanged(); private slots: void bringApplicationToForegroundInternal();