Fixes: Error logging, polish attach remote dialog

This commit is contained in:
Friedemann Kleint
2009-03-05 17:30:29 +01:00
committed by unknown
parent cb2cce5139
commit 355f44fe8f
6 changed files with 239 additions and 144 deletions

View File

@@ -1,7 +1,8 @@
<ui version="4.0" > <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>AttachRemoteDialog</class> <class>AttachRemoteDialog</class>
<widget class="QDialog" name="AttachRemoteDialog" > <widget class="QDialog" name="AttachRemoteDialog">
<property name="geometry" > <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
@@ -9,50 +10,76 @@
<height>866</height> <height>866</height>
</rect> </rect>
</property> </property>
<property name="windowTitle" > <property name="windowTitle">
<string>Start Debugger</string> <string>Start Debugger</string>
</property> </property>
<layout class="QVBoxLayout" > <layout class="QVBoxLayout">
<property name="spacing" > <property name="spacing">
<number>6</number> <number>6</number>
</property> </property>
<property name="margin" > <property name="margin">
<number>9</number> <number>9</number>
</property> </property>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout" > <layout class="QFormLayout" name="formLayout">
<item> <item row="0" column="0">
<widget class="QLabel" name="pidLabel" > <widget class="QLabel" name="pidLabel">
<property name="text" > <property name="text">
<string>Attach to Process ID:</string> <string>Attach to Process ID:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="1">
<widget class="QLineEdit" name="pidLineEdit"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Filter:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QWidget" name="filterWidget" native="true">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="margin">
<number>0</number>
</property>
<item> <item>
<widget class="QLineEdit" name="pidLineEdit" /> <widget class="QLineEdit" name="filterLineEdit"/>
</item>
<item>
<widget class="QToolButton" name="filterClearToolButton">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</widget>
</item> </item>
</layout> </layout>
</item> </item>
<item> <item>
<widget class="QTreeView" name="procView" > <widget class="QTreeView" name="procView">
<property name="editTriggers" > <property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set> <set>QAbstractItemView::NoEditTriggers</set>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="Line" name="line" > <widget class="Line" name="line">
<property name="orientation" > <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QDialogButtonBox" name="buttonBox" > <widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation" > <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
<property name="standardButtons" > <property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property> </property>
</widget> </widget>

View File

@@ -33,6 +33,7 @@
#include "debuggermanager.h" #include "debuggermanager.h"
#include "breakhandler.h" #include "breakhandler.h"
#include "stackhandler.h" #include "stackhandler.h"
#include "watchhandler.h"
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/winutils.h> #include <utils/winutils.h>
@@ -50,11 +51,13 @@
static const char *dbgEngineDllC = "dbgeng"; static const char *dbgEngineDllC = "dbgeng";
static const char *debugCreateFuncC = "DebugCreate"; static const char *debugCreateFuncC = "DebugCreate";
static QString debugEngineComError(HRESULT hr) static QString msgDebugEngineComResult(HRESULT hr)
{ {
if (!FAILED(hr))
return QLatin1String("S_OK");
switch (hr) { switch (hr) {
case S_OK:
return QLatin1String("S_OK");
case S_FALSE:
return QLatin1String("S_FALSE");
case E_FAIL: case E_FAIL:
break; break;
case E_INVALIDARG: case E_INVALIDARG:
@@ -207,6 +210,7 @@ bool CdbDebugEngine::startDebugger()
m_d->m_debuggerManager->showStatusMessage("Starting Debugger", -1); m_d->m_debuggerManager->showStatusMessage("Starting Debugger", -1);
QString errorMessage; QString errorMessage;
bool rc = false; bool rc = false;
m_d->m_bIgnoreNextDebugEvent = false;
switch (m_d->m_debuggerManager->startMode()) { switch (m_d->m_debuggerManager->startMode()) {
case AttachExternal: case AttachExternal:
rc = startAttachDebugger(m_d->m_debuggerManager->m_attachedPID, &errorMessage); rc = startAttachDebugger(m_d->m_debuggerManager->m_attachedPID, &errorMessage);
@@ -235,7 +239,7 @@ bool CdbDebugEngine::startAttachDebugger(unsigned long pid, QString *errorMessag
if (debugCDB) if (debugCDB)
qDebug() << "Attaching to " << pid << " returns " << hr; qDebug() << "Attaching to " << pid << " returns " << hr;
if (FAILED(hr)) { if (FAILED(hr)) {
*errorMessage = tr("AttachProcess failed for pid %1: %2").arg(pid).arg(debugEngineComError(hr)); *errorMessage = tr("AttachProcess failed for pid %1: %2").arg(pid).arg(msgDebugEngineComResult(hr));
return false; return false;
} }
return true; return true;
@@ -276,7 +280,7 @@ bool CdbDebugEngine::startDebuggerWithExecutable(QString *errorMessage)
m_d->m_debuggerManager->m_workingDir.utf16(), m_d->m_debuggerManager->m_workingDir.utf16(),
env); env);
if (FAILED(hr)) { if (FAILED(hr)) {
*errorMessage = tr("CreateProcess2Wide failed for '%1': %2").arg(cmd).arg(debugEngineComError(hr)); *errorMessage = tr("CreateProcess2Wide failed for '%1': %2").arg(cmd).arg(msgDebugEngineComResult(hr));
m_d->m_debuggerManagerAccess->notifyInferiorExited(); m_d->m_debuggerManagerAccess->notifyInferiorExited();
return false; return false;
} }
@@ -295,6 +299,9 @@ void CdbDebugEngine::exitDebugger()
void CdbDebugEngine::updateWatchModel() void CdbDebugEngine::updateWatchModel()
{ {
const QList<WatchData> incomplete = m_d->m_debuggerManagerAccess->watchHandler()->takeCurrentIncompletes();
if (debugCDB)
qDebug() << Q_FUNC_INFO << incomplete.size();
} }
void CdbDebugEngine::stepExec() void CdbDebugEngine::stepExec()
@@ -357,9 +364,12 @@ void CdbDebugEngine::nextExec()
if (debugCDB) if (debugCDB)
qDebug() << Q_FUNC_INFO; qDebug() << Q_FUNC_INFO;
HRESULT hr; const HRESULT hr = m_d->m_pDebugControl->SetExecutionStatus(DEBUG_STATUS_STEP_OVER);
hr = m_d->m_pDebugControl->SetExecutionStatus(DEBUG_STATUS_STEP_OVER); if (SUCCEEDED(hr)) {
startWatchTimer(); startWatchTimer();
} else {
qWarning("%s failed: %s", Q_FUNC_INFO, qPrintable(msgDebugEngineComResult(hr)));
}
} }
void CdbDebugEngine::stepIExec() void CdbDebugEngine::stepIExec()
@@ -372,8 +382,12 @@ void CdbDebugEngine::nextIExec()
if (debugCDB) if (debugCDB)
qDebug() << Q_FUNC_INFO; qDebug() << Q_FUNC_INFO;
m_d->m_pDebugControl->Execute(DEBUG_OUTCTL_THIS_CLIENT, "p", 0); const HRESULT hr = m_d->m_pDebugControl->Execute(DEBUG_OUTCTL_THIS_CLIENT, "p", 0);
if (SUCCEEDED(hr)) {
startWatchTimer(); startWatchTimer();
} else {
qWarning("%s failed: %s", Q_FUNC_INFO, qPrintable(msgDebugEngineComResult(hr)));
}
} }
void CdbDebugEngine::continueInferior() void CdbDebugEngine::continueInferior()
@@ -386,26 +400,30 @@ void CdbDebugEngine::continueInferior()
ULONG executionStatus; ULONG executionStatus;
HRESULT hr = m_d->m_pDebugControl->GetExecutionStatus(&executionStatus); HRESULT hr = m_d->m_pDebugControl->GetExecutionStatus(&executionStatus);
if (SUCCEEDED(hr) && executionStatus != DEBUG_STATUS_GO) if (SUCCEEDED(hr) && executionStatus != DEBUG_STATUS_GO) {
m_d->m_pDebugControl->SetExecutionStatus(DEBUG_STATUS_GO); hr = m_d->m_pDebugControl->SetExecutionStatus(DEBUG_STATUS_GO);
if (SUCCEEDED(hr)) {
startWatchTimer(); startWatchTimer();
m_d->m_debuggerManagerAccess->notifyInferiorRunning(); m_d->m_debuggerManagerAccess->notifyInferiorRunning();
} else {
qWarning("%s failed: %s", Q_FUNC_INFO, qPrintable(msgDebugEngineComResult(hr)));
}
}
} }
void CdbDebugEngine::interruptInferior() void CdbDebugEngine::interruptInferior()
{ {
if (debugCDB) if (debugCDB)
qDebug() << Q_FUNC_INFO; qDebug() << Q_FUNC_INFO << m_d->m_hDebuggeeProcess;
//TODO: better use IDebugControl::SetInterrupt? //TODO: better use IDebugControl::SetInterrupt?
if (!m_d->m_hDebuggeeProcess) if (!m_d->m_hDebuggeeProcess)
return; return;
if (!DebugBreakProcess(m_d->m_hDebuggeeProcess)) { if (DebugBreakProcess(m_d->m_hDebuggeeProcess)) {
qWarning("DebugBreakProcess failed.");
return;
}
m_d->m_debuggerManagerAccess->notifyInferiorStopped(); m_d->m_debuggerManagerAccess->notifyInferiorStopped();
} else {
qWarning("DebugBreakProcess failed: %s", Core::Utils::winErrorMessage(GetLastError()));
}
} }
void CdbDebugEngine::runToLineExec(const QString &fileName, int lineNumber) void CdbDebugEngine::runToLineExec(const QString &fileName, int lineNumber)
@@ -571,43 +589,30 @@ void CdbDebugEngine::timerEvent(QTimerEvent* te)
if (te->timerId() != m_d->m_watchTimer) if (te->timerId() != m_d->m_watchTimer)
return; return;
if (debugCDB > 1) const HRESULT hr = m_d->m_pDebugControl->WaitForEvent(0, 1);
qDebug() << Q_FUNC_INFO; if (debugCDB)
if (debugCDB > 1 || hr != S_FALSE)
qDebug() << Q_FUNC_INFO << "WaitForEvent" << msgDebugEngineComResult(hr);
HRESULT hr;
hr = m_d->m_pDebugControl->WaitForEvent(0, 1);
switch (hr) { switch (hr) {
case S_OK: case S_OK:
if (debugCDB > 1)
qDebug() << "WaitForEvent S_OK";
killWatchTimer(); killWatchTimer();
m_d->handleDebugEvent(); m_d->handleDebugEvent();
break; break;
case S_FALSE: case S_FALSE:
if (debugCDB > 1)
qDebug() << "WaitForEvent S_FALSE";
break;
case E_PENDING: case E_PENDING:
if (debugCDB > 1) case E_FAIL:
qDebug() << "WaitForEvent E_PENDING";
break; break;
case E_UNEXPECTED: case E_UNEXPECTED:
if (debugCDB > 1)
qDebug() << "WaitForEvent E_UNEXPECTED";
killWatchTimer(); killWatchTimer();
break; break;
case E_FAIL:
if (debugCDB > 1)
qDebug() << "WaitForEvent E_FAIL";
break;
} }
} }
void CdbDebugEnginePrivate::handleDebugEvent() void CdbDebugEnginePrivate::handleDebugEvent()
{ {
if (debugCDB) if (debugCDB)
qDebug() << Q_FUNC_INFO; qDebug() << Q_FUNC_INFO << m_hDebuggeeProcess;
if (m_bIgnoreNextDebugEvent) { if (m_bIgnoreNextDebugEvent) {
m_engine->startWatchTimer(); m_engine->startWatchTimer();
@@ -630,10 +635,18 @@ void CdbDebugEnginePrivate::handleDebugEvent()
//} //}
} }
void CdbDebugEnginePrivate::setDebuggeeHandles(HANDLE hDebuggeeProcess, HANDLE hDebuggeeThread)
{
if (debugCDB)
qDebug() << Q_FUNC_INFO << hDebuggeeProcess << hDebuggeeThread;
m_hDebuggeeProcess = hDebuggeeProcess;
m_hDebuggeeThread = hDebuggeeThread;
}
void CdbDebugEnginePrivate::updateThreadList() void CdbDebugEnginePrivate::updateThreadList()
{ {
if (debugCDB) if (debugCDB)
qDebug() << Q_FUNC_INFO; qDebug() << Q_FUNC_INFO << m_hDebuggeeProcess;
ThreadsHandler* th = m_debuggerManagerAccess->threadsHandler(); ThreadsHandler* th = m_debuggerManagerAccess->threadsHandler();
QList<ThreadData> threads; QList<ThreadData> threads;

View File

@@ -62,6 +62,8 @@ struct CdbDebugEnginePrivate
explicit CdbDebugEnginePrivate(const DebuggerEngineLibrary &lib, DebuggerManager *parent, CdbDebugEngine* engine); explicit CdbDebugEnginePrivate(const DebuggerEngineLibrary &lib, DebuggerManager *parent, CdbDebugEngine* engine);
~CdbDebugEnginePrivate(); ~CdbDebugEnginePrivate();
void setDebuggeeHandles(HANDLE hDebuggeeProcess, HANDLE hDebuggeeThread);
bool isDebuggeeRunning() const { return m_watchTimer != -1; } bool isDebuggeeRunning() const { return m_watchTimer != -1; }
void handleDebugEvent(); void handleDebugEvent();
void updateThreadList(); void updateThreadList();

View File

@@ -91,6 +91,13 @@ STDMETHODIMP CdbDebugEventCallback::Breakpoint(THIS_ __in PDEBUG_BREAKPOINT Bp)
return S_OK; return S_OK;
} }
static inline QString msgException(const EXCEPTION_RECORD64 *Exception, ULONG FirstChance)
{
return QString::fromLatin1("An exception occurred: Code=0x%1 FirstChance=%2").
arg(QString::number(Exception->ExceptionCode, 16)).
arg(FirstChance);
}
STDMETHODIMP CdbDebugEventCallback::Exception( STDMETHODIMP CdbDebugEventCallback::Exception(
THIS_ THIS_
__in PEXCEPTION_RECORD64 Exception, __in PEXCEPTION_RECORD64 Exception,
@@ -99,7 +106,11 @@ STDMETHODIMP CdbDebugEventCallback::Exception(
{ {
Q_UNUSED(Exception) Q_UNUSED(Exception)
if (debugCDB) if (debugCDB)
qDebug() << Q_FUNC_INFO << FirstChance; qDebug() << Q_FUNC_INFO << msgException(Exception, FirstChance);
// First chance are harmless
if (!FirstChance)
qWarning("%s", qPrintable(msgException(Exception, FirstChance)));
return S_OK; return S_OK;
} }
@@ -161,8 +172,7 @@ STDMETHODIMP CdbDebugEventCallback::CreateProcess(
if (debugCDB) if (debugCDB)
qDebug() << Q_FUNC_INFO << ModuleName; qDebug() << Q_FUNC_INFO << ModuleName;
m_pEngine->m_d->m_hDebuggeeProcess = (HANDLE)Handle; m_pEngine->m_d->setDebuggeeHandles(reinterpret_cast<HANDLE>(Handle), reinterpret_cast<HANDLE>(InitialThreadHandle));
m_pEngine->m_d->m_hDebuggeeThread = (HANDLE)InitialThreadHandle;
m_pEngine->m_d->m_debuggerManagerAccess->notifyInferiorRunning(); m_pEngine->m_d->m_debuggerManagerAccess->notifyInferiorRunning();
ULONG currentThreadId; ULONG currentThreadId;
@@ -183,8 +193,7 @@ STDMETHODIMP CdbDebugEventCallback::ExitProcess(
if (debugCDB) if (debugCDB)
qDebug() << Q_FUNC_INFO << ExitCode; qDebug() << Q_FUNC_INFO << ExitCode;
m_pEngine->m_d->m_hDebuggeeProcess = 0; m_pEngine->m_d->setDebuggeeHandles(0, 0);
m_pEngine->m_d->m_hDebuggeeThread = 0;
m_pEngine->m_d->m_debuggerManagerAccess->notifyInferiorExited(); m_pEngine->m_d->m_debuggerManagerAccess->notifyInferiorExited();
return S_OK; return S_OK;
} }

View File

@@ -49,7 +49,72 @@
#include <QtGui/QProxyModel> #include <QtGui/QProxyModel>
#include <QtGui/QSortFilterProxyModel> #include <QtGui/QSortFilterProxyModel>
using namespace Debugger::Internal;
namespace Debugger {
namespace Internal {
bool operator<(const ProcData &p1, const ProcData &p2)
{
return p1.name < p2.name;
}
// A filterable process list model
class ProcessListFilterModel : public QSortFilterProxyModel {
public:
explicit ProcessListFilterModel(QObject *parent);
QString processIdAt(const QModelIndex &index) const;
void populate(QList<ProcData> processes, const QString &excludePid = QString());
private:
QStandardItemModel *m_model;
};
ProcessListFilterModel::ProcessListFilterModel(QObject *parent) :
QSortFilterProxyModel(parent),
m_model(new QStandardItemModel(this))
{
QStringList columns;
columns << AttachExternalDialog::tr("Process ID")
<< AttachExternalDialog::tr("Name")
<< AttachExternalDialog::tr("State");
m_model->setHorizontalHeaderLabels(columns);
setSourceModel(m_model);
setFilterCaseSensitivity(Qt::CaseInsensitive);
setFilterKeyColumn(1);
}
QString ProcessListFilterModel::processIdAt(const QModelIndex &index) const
{
if (index.isValid()) {
const QModelIndex index0 = mapToSource(index);
QModelIndex index = index0.sibling(index0.row(), 0);
if (const QStandardItem *item = m_model->itemFromIndex(index))
return item->text();
}
return QString();
}
void ProcessListFilterModel::populate(QList<ProcData> processes, const QString &excludePid)
{
qStableSort(processes);
if (const int rowCount = m_model->rowCount())
m_model->removeRows(0, rowCount);
QStandardItem *root = m_model->invisibleRootItem();
foreach(const ProcData &proc, processes) {
QList<QStandardItem *> row;
row.append(new QStandardItem(proc.ppid));
row.append(new QStandardItem(proc.name));
if (!proc.image.isEmpty())
row.back()->setToolTip(proc.image);
row.append(new QStandardItem(proc.state));
if (proc.ppid == excludePid)
foreach(QStandardItem *i, row)
i->setEnabled(false);
root->appendRow(row);
}
}
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
// //
@@ -105,17 +170,6 @@ void AttachCoreDialog::setCoreFile(const QString &fileName)
// //
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
static QStandardItemModel *createProcessModel(QObject *parent)
{
QStandardItemModel *rc = new QStandardItemModel(parent);
QStringList columns;
columns << AttachExternalDialog::tr("Process ID")
<< AttachExternalDialog::tr("Name")
<< AttachExternalDialog::tr("State");
rc->setHorizontalHeaderLabels(columns);
return rc;
}
static bool isUnixProcessId(const QString &procname) static bool isUnixProcessId(const QString &procname)
{ {
for (int i = 0; i != procname.size(); ++i) for (int i = 0; i != procname.size(); ++i)
@@ -124,13 +178,6 @@ static bool isUnixProcessId(const QString &procname)
return true; return true;
} }
QT_BEGIN_NAMESPACE
bool operator<(const ProcData &p1, const ProcData &p2)
{
return p1.name < p2.name;
}
QT_END_NAMESPACE
// Determine UNIX processes by reading "/proc" // Determine UNIX processes by reading "/proc"
static QList<ProcData> unixProcessList() static QList<ProcData> unixProcessList()
{ {
@@ -162,40 +209,13 @@ static QList<ProcData> unixProcessList()
return rc; return rc;
} }
static inline QStandardItem *createStandardItem(const QString &text, static QList<ProcData> processList()
bool enabled)
{
QStandardItem *rc = new QStandardItem(text);
rc->setEnabled(enabled);
return rc;
}
// Populate a standard item model with a list
// of processes and gray out the excludePid.
static void populateProcessModel(QStandardItemModel *model,
const QString &excludePid = QString())
{ {
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
QList<ProcData> processes = winProcessList(); return winProcessList();
#else #else
QList<ProcData> processes = unixProcessList(); return unixProcessList();
#endif #endif
qStableSort(processes);
if (const int rowCount = model->rowCount())
model->removeRows(0, rowCount);
QStandardItem *root = model->invisibleRootItem();
foreach(const ProcData &proc, processes) {
const bool enabled = proc.ppid != excludePid;
QList<QStandardItem *> row;
row.append(createStandardItem(proc.ppid, enabled));
row.append(createStandardItem(proc.name, enabled));
if (!proc.image.isEmpty())
row.back()->setToolTip(proc.image);
row.append(createStandardItem(proc.state, enabled));
root->appendRow(row);
}
} }
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
@@ -208,17 +228,13 @@ AttachExternalDialog::AttachExternalDialog(QWidget *parent) :
QDialog(parent), QDialog(parent),
m_selfPid(QString::number(QCoreApplication::applicationPid())), m_selfPid(QString::number(QCoreApplication::applicationPid())),
m_ui(new Ui::AttachExternalDialog), m_ui(new Ui::AttachExternalDialog),
m_proxyModel(new QSortFilterProxyModel(this)), m_model(new ProcessListFilterModel(this))
m_model(createProcessModel(this))
{ {
m_ui->setupUi(this); m_ui->setupUi(this);
okButton()->setDefault(true); okButton()->setDefault(true);
okButton()->setEnabled(false); okButton()->setEnabled(false);
m_proxyModel->setSourceModel(m_model); m_ui->procView->setModel(m_model);
m_proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
m_proxyModel->setFilterKeyColumn(1);
m_ui->procView->setModel(m_proxyModel);
m_ui->procView->setSortingEnabled(true); m_ui->procView->setSortingEnabled(true);
connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept())); connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
@@ -227,7 +243,8 @@ AttachExternalDialog::AttachExternalDialog(QWidget *parent) :
connect(refreshButton, SIGNAL(clicked()), this, SLOT(rebuildProcessList())); connect(refreshButton, SIGNAL(clicked()), this, SLOT(rebuildProcessList()));
m_ui->buttonBox->addButton(refreshButton, QDialogButtonBox::ActionRole); m_ui->buttonBox->addButton(refreshButton, QDialogButtonBox::ActionRole);
connect(m_ui->procView, SIGNAL(activated(QModelIndex)), // Do not use activated, will be single click in Oxygen
connect(m_ui->procView, SIGNAL(doubleClicked(QModelIndex)),
this, SLOT(procSelected(QModelIndex))); this, SLOT(procSelected(QModelIndex)));
connect(m_ui->pidLineEdit, SIGNAL(textChanged(QString)), connect(m_ui->pidLineEdit, SIGNAL(textChanged(QString)),
this, SLOT(pidChanged(QString))); this, SLOT(pidChanged(QString)));
@@ -235,7 +252,7 @@ AttachExternalDialog::AttachExternalDialog(QWidget *parent) :
connect(m_ui->filterClearToolButton, SIGNAL(clicked()), connect(m_ui->filterClearToolButton, SIGNAL(clicked()),
m_ui->filterLineEdit, SLOT(clear())); m_ui->filterLineEdit, SLOT(clear()));
connect(m_ui->filterLineEdit, SIGNAL(textChanged(QString)), connect(m_ui->filterLineEdit, SIGNAL(textChanged(QString)),
m_proxyModel, SLOT(setFilterFixedString(QString))); m_model, SLOT(setFilterFixedString(QString)));
rebuildProcessList(); rebuildProcessList();
} }
@@ -252,7 +269,7 @@ QPushButton *AttachExternalDialog::okButton() const
void AttachExternalDialog::rebuildProcessList() void AttachExternalDialog::rebuildProcessList()
{ {
populateProcessModel(m_model, m_selfPid); m_model->populate(processList(), m_selfPid);
m_ui->procView->expandAll(); m_ui->procView->expandAll();
m_ui->procView->resizeColumnToContents(0); m_ui->procView->resizeColumnToContents(0);
m_ui->procView->resizeColumnToContents(1); m_ui->procView->resizeColumnToContents(1);
@@ -260,10 +277,9 @@ void AttachExternalDialog::rebuildProcessList()
void AttachExternalDialog::procSelected(const QModelIndex &proxyIndex) void AttachExternalDialog::procSelected(const QModelIndex &proxyIndex)
{ {
const QModelIndex index0 = m_proxyModel->mapToSource(proxyIndex); const QString proccessId = m_model->processIdAt(proxyIndex);
QModelIndex index = index0.sibling(index0.row(), 0); if (!proccessId.isEmpty()) {
if (const QStandardItem *item = m_model->itemFromIndex(index)) { m_ui->pidLineEdit->setText(proccessId);
m_ui->pidLineEdit->setText(item->text());
if (okButton()->isEnabled()) if (okButton()->isEnabled())
okButton()->animateClick(); okButton()->animateClick();
} }
@@ -276,7 +292,7 @@ int AttachExternalDialog::attachPID() const
void AttachExternalDialog::pidChanged(const QString &pid) void AttachExternalDialog::pidChanged(const QString &pid)
{ {
okButton()->setEnabled(!pid.isEmpty() && pid != m_selfPid); okButton()->setEnabled(!pid.isEmpty() && pid != QLatin1String("0") && pid != m_selfPid);
} }
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
@@ -288,7 +304,7 @@ void AttachExternalDialog::pidChanged(const QString &pid)
AttachRemoteDialog::AttachRemoteDialog(QWidget *parent, const QString &pid) : AttachRemoteDialog::AttachRemoteDialog(QWidget *parent, const QString &pid) :
QDialog(parent), QDialog(parent),
m_ui(new Ui::AttachRemoteDialog), m_ui(new Ui::AttachRemoteDialog),
m_model(createProcessModel(this)) m_model(new ProcessListFilterModel(this))
{ {
m_ui->setupUi(this); m_ui->setupUi(this);
m_ui->buttonBox->button(QDialogButtonBox::Ok)->setDefault(true); m_ui->buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
@@ -300,9 +316,22 @@ AttachRemoteDialog::AttachRemoteDialog(QWidget *parent, const QString &pid) :
connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept())); connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject())); connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
connect(m_ui->procView, SIGNAL(activated(QModelIndex)), // Do not use activated, will be single click in Oxygen
connect(m_ui->procView, SIGNAL(doubleClicked(QModelIndex)),
this, SLOT(procSelected(QModelIndex))); this, SLOT(procSelected(QModelIndex)));
QPushButton *refreshButton = new QPushButton(tr("Refresh"));
connect(refreshButton, SIGNAL(clicked()), this, SLOT(rebuildProcessList()));
m_ui->buttonBox->addButton(refreshButton, QDialogButtonBox::ActionRole);
connect(m_ui->pidLineEdit, SIGNAL(textChanged(QString)),
this, SLOT(pidChanged(QString)));
connect(m_ui->filterClearToolButton, SIGNAL(clicked()),
m_ui->filterLineEdit, SLOT(clear()));
connect(m_ui->filterLineEdit, SIGNAL(textChanged(QString)),
m_model, SLOT(setFilterFixedString(QString)));
m_ui->pidLineEdit->setText(m_defaultPID); m_ui->pidLineEdit->setText(m_defaultPID);
rebuildProcessList(); rebuildProcessList();
} }
@@ -312,9 +341,14 @@ AttachRemoteDialog::~AttachRemoteDialog()
delete m_ui; delete m_ui;
} }
QPushButton *AttachRemoteDialog::okButton() const
{
return m_ui->buttonBox->button(QDialogButtonBox::Ok);
}
void AttachRemoteDialog::rebuildProcessList() void AttachRemoteDialog::rebuildProcessList()
{ {
populateProcessModel(m_model); m_model->populate(processList());
m_ui->procView->expandAll(); m_ui->procView->expandAll();
m_ui->procView->resizeColumnToContents(0); m_ui->procView->resizeColumnToContents(0);
m_ui->procView->resizeColumnToContents(1); m_ui->procView->resizeColumnToContents(1);
@@ -322,12 +356,12 @@ void AttachRemoteDialog::rebuildProcessList()
void AttachRemoteDialog::procSelected(const QModelIndex &index0) void AttachRemoteDialog::procSelected(const QModelIndex &index0)
{ {
QModelIndex index = index0.sibling(index0.row(), 0); const QString proccessId = m_model->processIdAt(index0);
QStandardItem *item = m_model->itemFromIndex(index); if (!proccessId.isEmpty()) {
if (!item) m_ui->pidLineEdit->setText(proccessId);
return; if (okButton()->isEnabled())
m_ui->pidLineEdit->setText(item->text()); okButton()->animateClick();
accept(); }
} }
int AttachRemoteDialog::attachPID() const int AttachRemoteDialog::attachPID() const
@@ -335,6 +369,12 @@ int AttachRemoteDialog::attachPID() const
return m_ui->pidLineEdit->text().toInt(); return m_ui->pidLineEdit->text().toInt();
} }
void AttachRemoteDialog::pidChanged(const QString &pid)
{
okButton()->setEnabled(!pid.isEmpty() && pid != QLatin1String("0"));
}
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
// //
// StartExternalDialog // StartExternalDialog
@@ -385,3 +425,6 @@ QString StartExternalDialog::executableArguments() const
{ {
return m_ui->argsEdit->text(); return m_ui->argsEdit->text();
} }
}
}

View File

@@ -35,8 +35,6 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QModelIndex; class QModelIndex;
class QStandardItemModel;
class QSortFilterProxyModel;
class QPushButton; class QPushButton;
namespace Ui { namespace Ui {
@@ -52,6 +50,8 @@ QT_END_NAMESPACE
namespace Debugger { namespace Debugger {
namespace Internal { namespace Internal {
class ProcessListFilterModel;
struct ProcData struct ProcData
{ {
QString ppid; QString ppid;
@@ -98,8 +98,7 @@ private:
const QString m_selfPid; const QString m_selfPid;
Ui::AttachExternalDialog *m_ui; Ui::AttachExternalDialog *m_ui;
QStandardItemModel *m_model; ProcessListFilterModel *m_model;
QSortFilterProxyModel *m_proxyModel;
}; };
@@ -116,11 +115,13 @@ public:
private slots: private slots:
void rebuildProcessList(); void rebuildProcessList();
void procSelected(const QModelIndex &); void procSelected(const QModelIndex &);
void pidChanged(const QString &);
private: private:
inline QPushButton *okButton() const;
Ui::AttachRemoteDialog *m_ui; Ui::AttachRemoteDialog *m_ui;
QString m_defaultPID; QString m_defaultPID;
QStandardItemModel *m_model; ProcessListFilterModel *m_model;
}; };