Commit 942d024b authored by Friedemann Kleint's avatar Friedemann Kleint

ProjectExplorer: Fix enabling of buttons in the output pane.

Enable debug only if run control has a valid process handle.
Restore icon of rerun-button.

Take the concept of the ProcessHandle further (give it
descriptive string, add change signal to run control, clear it
when process stops to correctly enable debug).

No longer set ProcessHandle to debug run control as this would
allow attach a 2nd debugger to the process.

Reviewed-by: hjk

Change-Id: Iecf388e239fcd365864fe59177d76afac7484ecc
Reviewed-on: http://codereview.qt.nokia.com/1212Reviewed-by: default avatarQt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: default avatarEike Ziller <eike.ziller@nokia.com>
parent 4cdfacff
......@@ -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
......
......@@ -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);
......
......@@ -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);
......
......@@ -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);
......
......@@ -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
......
......@@ -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();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment