From 355f44fe8fb9e28f826f1bb9033a36afa61abfa7 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint <qtc-committer@nokia.com> Date: Thu, 5 Mar 2009 17:30:29 +0100 Subject: [PATCH] Fixes: Error logging, polish attach remote dialog --- src/plugins/debugger/attachremotedialog.ui | 67 +++++-- src/plugins/debugger/cdb/cdbdebugengine.cpp | 95 +++++---- src/plugins/debugger/cdb/cdbdebugengine_p.h | 2 + .../debugger/cdb/cdbdebugeventcallback.cpp | 19 +- src/plugins/debugger/debuggerdialogs.cpp | 189 +++++++++++------- src/plugins/debugger/debuggerdialogs.h | 11 +- 6 files changed, 239 insertions(+), 144 deletions(-) diff --git a/src/plugins/debugger/attachremotedialog.ui b/src/plugins/debugger/attachremotedialog.ui index 4d478e3b0f3..04a1073492c 100644 --- a/src/plugins/debugger/attachremotedialog.ui +++ b/src/plugins/debugger/attachremotedialog.ui @@ -1,7 +1,8 @@ -<ui version="4.0" > +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> <class>AttachRemoteDialog</class> - <widget class="QDialog" name="AttachRemoteDialog" > - <property name="geometry" > + <widget class="QDialog" name="AttachRemoteDialog"> + <property name="geometry"> <rect> <x>0</x> <y>0</y> @@ -9,50 +10,76 @@ <height>866</height> </rect> </property> - <property name="windowTitle" > + <property name="windowTitle"> <string>Start Debugger</string> </property> - <layout class="QVBoxLayout" > - <property name="spacing" > + <layout class="QVBoxLayout"> + <property name="spacing"> <number>6</number> </property> - <property name="margin" > + <property name="margin"> <number>9</number> </property> <item> - <layout class="QHBoxLayout" name="horizontalLayout" > - <item> - <widget class="QLabel" name="pidLabel" > - <property name="text" > + <layout class="QFormLayout" name="formLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="pidLabel"> + <property name="text"> <string>Attach to Process ID:</string> </property> </widget> </item> - <item> - <widget class="QLineEdit" name="pidLineEdit" /> + <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> + <widget class="QLineEdit" name="filterLineEdit"/> + </item> + <item> + <widget class="QToolButton" name="filterClearToolButton"> + <property name="text"> + <string>...</string> + </property> + </widget> + </item> + </layout> + </widget> </item> </layout> </item> <item> - <widget class="QTreeView" name="procView" > - <property name="editTriggers" > + <widget class="QTreeView" name="procView"> + <property name="editTriggers"> <set>QAbstractItemView::NoEditTriggers</set> </property> </widget> </item> <item> - <widget class="Line" name="line" > - <property name="orientation" > + <widget class="Line" name="line"> + <property name="orientation"> <enum>Qt::Horizontal</enum> </property> </widget> </item> <item> - <widget class="QDialogButtonBox" name="buttonBox" > - <property name="orientation" > + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> <enum>Qt::Horizontal</enum> </property> - <property name="standardButtons" > + <property name="standardButtons"> <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> </property> </widget> diff --git a/src/plugins/debugger/cdb/cdbdebugengine.cpp b/src/plugins/debugger/cdb/cdbdebugengine.cpp index ab71dc23e81..f35a2486697 100644 --- a/src/plugins/debugger/cdb/cdbdebugengine.cpp +++ b/src/plugins/debugger/cdb/cdbdebugengine.cpp @@ -33,6 +33,7 @@ #include "debuggermanager.h" #include "breakhandler.h" #include "stackhandler.h" +#include "watchhandler.h" #include <utils/qtcassert.h> #include <utils/winutils.h> @@ -50,11 +51,13 @@ static const char *dbgEngineDllC = "dbgeng"; static const char *debugCreateFuncC = "DebugCreate"; -static QString debugEngineComError(HRESULT hr) +static QString msgDebugEngineComResult(HRESULT hr) { - if (!FAILED(hr)) - return QLatin1String("S_OK"); switch (hr) { + case S_OK: + return QLatin1String("S_OK"); + case S_FALSE: + return QLatin1String("S_FALSE"); case E_FAIL: break; case E_INVALIDARG: @@ -207,6 +210,7 @@ bool CdbDebugEngine::startDebugger() m_d->m_debuggerManager->showStatusMessage("Starting Debugger", -1); QString errorMessage; bool rc = false; + m_d->m_bIgnoreNextDebugEvent = false; switch (m_d->m_debuggerManager->startMode()) { case AttachExternal: rc = startAttachDebugger(m_d->m_debuggerManager->m_attachedPID, &errorMessage); @@ -235,7 +239,7 @@ bool CdbDebugEngine::startAttachDebugger(unsigned long pid, QString *errorMessag if (debugCDB) qDebug() << "Attaching to " << pid << " returns " << 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 true; @@ -276,7 +280,7 @@ bool CdbDebugEngine::startDebuggerWithExecutable(QString *errorMessage) m_d->m_debuggerManager->m_workingDir.utf16(), env); 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(); return false; } @@ -295,6 +299,9 @@ void CdbDebugEngine::exitDebugger() void CdbDebugEngine::updateWatchModel() { + const QList<WatchData> incomplete = m_d->m_debuggerManagerAccess->watchHandler()->takeCurrentIncompletes(); + if (debugCDB) + qDebug() << Q_FUNC_INFO << incomplete.size(); } void CdbDebugEngine::stepExec() @@ -357,9 +364,12 @@ void CdbDebugEngine::nextExec() if (debugCDB) qDebug() << Q_FUNC_INFO; - HRESULT hr; - hr = m_d->m_pDebugControl->SetExecutionStatus(DEBUG_STATUS_STEP_OVER); - startWatchTimer(); + const HRESULT hr = m_d->m_pDebugControl->SetExecutionStatus(DEBUG_STATUS_STEP_OVER); + if (SUCCEEDED(hr)) { + startWatchTimer(); + } else { + qWarning("%s failed: %s", Q_FUNC_INFO, qPrintable(msgDebugEngineComResult(hr))); + } } void CdbDebugEngine::stepIExec() @@ -372,8 +382,12 @@ void CdbDebugEngine::nextIExec() if (debugCDB) qDebug() << Q_FUNC_INFO; - m_d->m_pDebugControl->Execute(DEBUG_OUTCTL_THIS_CLIENT, "p", 0); - startWatchTimer(); + const HRESULT hr = m_d->m_pDebugControl->Execute(DEBUG_OUTCTL_THIS_CLIENT, "p", 0); + if (SUCCEEDED(hr)) { + startWatchTimer(); + } else { + qWarning("%s failed: %s", Q_FUNC_INFO, qPrintable(msgDebugEngineComResult(hr))); + } } void CdbDebugEngine::continueInferior() @@ -386,26 +400,30 @@ void CdbDebugEngine::continueInferior() ULONG executionStatus; HRESULT hr = m_d->m_pDebugControl->GetExecutionStatus(&executionStatus); - if (SUCCEEDED(hr) && executionStatus != DEBUG_STATUS_GO) - m_d->m_pDebugControl->SetExecutionStatus(DEBUG_STATUS_GO); - - startWatchTimer(); - m_d->m_debuggerManagerAccess->notifyInferiorRunning(); + if (SUCCEEDED(hr) && executionStatus != DEBUG_STATUS_GO) { + hr = m_d->m_pDebugControl->SetExecutionStatus(DEBUG_STATUS_GO); + if (SUCCEEDED(hr)) { + startWatchTimer(); + m_d->m_debuggerManagerAccess->notifyInferiorRunning(); + } else { + qWarning("%s failed: %s", Q_FUNC_INFO, qPrintable(msgDebugEngineComResult(hr))); + } + } } void CdbDebugEngine::interruptInferior() { if (debugCDB) - qDebug() << Q_FUNC_INFO; + qDebug() << Q_FUNC_INFO << m_d->m_hDebuggeeProcess; //TODO: better use IDebugControl::SetInterrupt? if (!m_d->m_hDebuggeeProcess) return; - if (!DebugBreakProcess(m_d->m_hDebuggeeProcess)) { - qWarning("DebugBreakProcess failed."); - return; + if (DebugBreakProcess(m_d->m_hDebuggeeProcess)) { + m_d->m_debuggerManagerAccess->notifyInferiorStopped(); + } else { + qWarning("DebugBreakProcess failed: %s", Core::Utils::winErrorMessage(GetLastError())); } - m_d->m_debuggerManagerAccess->notifyInferiorStopped(); } void CdbDebugEngine::runToLineExec(const QString &fileName, int lineNumber) @@ -571,43 +589,30 @@ void CdbDebugEngine::timerEvent(QTimerEvent* te) if (te->timerId() != m_d->m_watchTimer) return; - if (debugCDB > 1) - qDebug() << Q_FUNC_INFO; + const HRESULT hr = m_d->m_pDebugControl->WaitForEvent(0, 1); + 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) { case S_OK: - if (debugCDB > 1) - qDebug() << "WaitForEvent S_OK"; - killWatchTimer(); m_d->handleDebugEvent(); break; case S_FALSE: - if (debugCDB > 1) - qDebug() << "WaitForEvent S_FALSE"; - break; case E_PENDING: - if (debugCDB > 1) - qDebug() << "WaitForEvent E_PENDING"; + case E_FAIL: break; case E_UNEXPECTED: - if (debugCDB > 1) - qDebug() << "WaitForEvent E_UNEXPECTED"; killWatchTimer(); - break; - case E_FAIL: - if (debugCDB > 1) - qDebug() << "WaitForEvent E_FAIL"; - break; + break; } } void CdbDebugEnginePrivate::handleDebugEvent() { if (debugCDB) - qDebug() << Q_FUNC_INFO; + qDebug() << Q_FUNC_INFO << m_hDebuggeeProcess; if (m_bIgnoreNextDebugEvent) { 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() { if (debugCDB) - qDebug() << Q_FUNC_INFO; + qDebug() << Q_FUNC_INFO << m_hDebuggeeProcess; ThreadsHandler* th = m_debuggerManagerAccess->threadsHandler(); QList<ThreadData> threads; diff --git a/src/plugins/debugger/cdb/cdbdebugengine_p.h b/src/plugins/debugger/cdb/cdbdebugengine_p.h index 369c4719438..76960d637a6 100644 --- a/src/plugins/debugger/cdb/cdbdebugengine_p.h +++ b/src/plugins/debugger/cdb/cdbdebugengine_p.h @@ -62,6 +62,8 @@ struct CdbDebugEnginePrivate explicit CdbDebugEnginePrivate(const DebuggerEngineLibrary &lib, DebuggerManager *parent, CdbDebugEngine* engine); ~CdbDebugEnginePrivate(); + void setDebuggeeHandles(HANDLE hDebuggeeProcess, HANDLE hDebuggeeThread); + bool isDebuggeeRunning() const { return m_watchTimer != -1; } void handleDebugEvent(); void updateThreadList(); diff --git a/src/plugins/debugger/cdb/cdbdebugeventcallback.cpp b/src/plugins/debugger/cdb/cdbdebugeventcallback.cpp index b6f073f473a..c0f6cd80a40 100644 --- a/src/plugins/debugger/cdb/cdbdebugeventcallback.cpp +++ b/src/plugins/debugger/cdb/cdbdebugeventcallback.cpp @@ -91,6 +91,13 @@ STDMETHODIMP CdbDebugEventCallback::Breakpoint(THIS_ __in PDEBUG_BREAKPOINT Bp) 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( THIS_ __in PEXCEPTION_RECORD64 Exception, @@ -99,7 +106,11 @@ STDMETHODIMP CdbDebugEventCallback::Exception( { Q_UNUSED(Exception) 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; } @@ -161,8 +172,7 @@ STDMETHODIMP CdbDebugEventCallback::CreateProcess( if (debugCDB) qDebug() << Q_FUNC_INFO << ModuleName; - m_pEngine->m_d->m_hDebuggeeProcess = (HANDLE)Handle; - m_pEngine->m_d->m_hDebuggeeThread = (HANDLE)InitialThreadHandle; + m_pEngine->m_d->setDebuggeeHandles(reinterpret_cast<HANDLE>(Handle), reinterpret_cast<HANDLE>(InitialThreadHandle)); m_pEngine->m_d->m_debuggerManagerAccess->notifyInferiorRunning(); ULONG currentThreadId; @@ -183,8 +193,7 @@ STDMETHODIMP CdbDebugEventCallback::ExitProcess( if (debugCDB) qDebug() << Q_FUNC_INFO << ExitCode; - m_pEngine->m_d->m_hDebuggeeProcess = 0; - m_pEngine->m_d->m_hDebuggeeThread = 0; + m_pEngine->m_d->setDebuggeeHandles(0, 0); m_pEngine->m_d->m_debuggerManagerAccess->notifyInferiorExited(); return S_OK; } diff --git a/src/plugins/debugger/debuggerdialogs.cpp b/src/plugins/debugger/debuggerdialogs.cpp index 38abffe91d8..c4c517327e7 100644 --- a/src/plugins/debugger/debuggerdialogs.cpp +++ b/src/plugins/debugger/debuggerdialogs.cpp @@ -49,7 +49,72 @@ #include <QtGui/QProxyModel> #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) { for (int i = 0; i != procname.size(); ++i) @@ -124,13 +178,6 @@ static bool isUnixProcessId(const QString &procname) 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" static QList<ProcData> unixProcessList() { @@ -162,40 +209,13 @@ static QList<ProcData> unixProcessList() return rc; } -static inline QStandardItem *createStandardItem(const QString &text, - 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()) +static QList<ProcData> processList() { #ifdef Q_OS_WIN - QList<ProcData> processes = winProcessList(); + return winProcessList(); #else - QList<ProcData> processes = unixProcessList(); + return unixProcessList(); #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), m_selfPid(QString::number(QCoreApplication::applicationPid())), m_ui(new Ui::AttachExternalDialog), - m_proxyModel(new QSortFilterProxyModel(this)), - m_model(createProcessModel(this)) + m_model(new ProcessListFilterModel(this)) { m_ui->setupUi(this); okButton()->setDefault(true); okButton()->setEnabled(false); - m_proxyModel->setSourceModel(m_model); - m_proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); - m_proxyModel->setFilterKeyColumn(1); - m_ui->procView->setModel(m_proxyModel); + m_ui->procView->setModel(m_model); m_ui->procView->setSortingEnabled(true); connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept())); @@ -227,7 +243,8 @@ AttachExternalDialog::AttachExternalDialog(QWidget *parent) : connect(refreshButton, SIGNAL(clicked()), this, SLOT(rebuildProcessList())); 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))); connect(m_ui->pidLineEdit, SIGNAL(textChanged(QString)), this, SLOT(pidChanged(QString))); @@ -235,7 +252,7 @@ AttachExternalDialog::AttachExternalDialog(QWidget *parent) : connect(m_ui->filterClearToolButton, SIGNAL(clicked()), m_ui->filterLineEdit, SLOT(clear())); connect(m_ui->filterLineEdit, SIGNAL(textChanged(QString)), - m_proxyModel, SLOT(setFilterFixedString(QString))); + m_model, SLOT(setFilterFixedString(QString))); rebuildProcessList(); } @@ -252,7 +269,7 @@ QPushButton *AttachExternalDialog::okButton() const void AttachExternalDialog::rebuildProcessList() { - populateProcessModel(m_model, m_selfPid); + m_model->populate(processList(), m_selfPid); m_ui->procView->expandAll(); m_ui->procView->resizeColumnToContents(0); m_ui->procView->resizeColumnToContents(1); @@ -260,10 +277,9 @@ void AttachExternalDialog::rebuildProcessList() void AttachExternalDialog::procSelected(const QModelIndex &proxyIndex) { - const QModelIndex index0 = m_proxyModel->mapToSource(proxyIndex); - QModelIndex index = index0.sibling(index0.row(), 0); - if (const QStandardItem *item = m_model->itemFromIndex(index)) { - m_ui->pidLineEdit->setText(item->text()); + const QString proccessId = m_model->processIdAt(proxyIndex); + if (!proccessId.isEmpty()) { + m_ui->pidLineEdit->setText(proccessId); if (okButton()->isEnabled()) okButton()->animateClick(); } @@ -276,7 +292,7 @@ int AttachExternalDialog::attachPID() const 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) : QDialog(parent), m_ui(new Ui::AttachRemoteDialog), - m_model(createProcessModel(this)) + m_model(new ProcessListFilterModel(this)) { m_ui->setupUi(this); 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(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))); + 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); rebuildProcessList(); } @@ -312,22 +341,27 @@ AttachRemoteDialog::~AttachRemoteDialog() delete m_ui; } +QPushButton *AttachRemoteDialog::okButton() const +{ + return m_ui->buttonBox->button(QDialogButtonBox::Ok); +} + void AttachRemoteDialog::rebuildProcessList() { - populateProcessModel(m_model); + m_model->populate(processList()); m_ui->procView->expandAll(); m_ui->procView->resizeColumnToContents(0); m_ui->procView->resizeColumnToContents(1); } void AttachRemoteDialog::procSelected(const QModelIndex &index0) -{ - QModelIndex index = index0.sibling(index0.row(), 0); - QStandardItem *item = m_model->itemFromIndex(index); - if (!item) - return; - m_ui->pidLineEdit->setText(item->text()); - accept(); +{ + const QString proccessId = m_model->processIdAt(index0); + if (!proccessId.isEmpty()) { + m_ui->pidLineEdit->setText(proccessId); + if (okButton()->isEnabled()) + okButton()->animateClick(); + } } int AttachRemoteDialog::attachPID() const @@ -335,6 +369,12 @@ int AttachRemoteDialog::attachPID() const return m_ui->pidLineEdit->text().toInt(); } +void AttachRemoteDialog::pidChanged(const QString &pid) +{ + okButton()->setEnabled(!pid.isEmpty() && pid != QLatin1String("0")); +} + + /////////////////////////////////////////////////////////////////////// // // StartExternalDialog @@ -385,3 +425,6 @@ QString StartExternalDialog::executableArguments() const { return m_ui->argsEdit->text(); } + +} +} diff --git a/src/plugins/debugger/debuggerdialogs.h b/src/plugins/debugger/debuggerdialogs.h index 1e11c356f7d..f263e710c66 100644 --- a/src/plugins/debugger/debuggerdialogs.h +++ b/src/plugins/debugger/debuggerdialogs.h @@ -35,8 +35,6 @@ QT_BEGIN_NAMESPACE class QModelIndex; -class QStandardItemModel; -class QSortFilterProxyModel; class QPushButton; namespace Ui { @@ -52,6 +50,8 @@ QT_END_NAMESPACE namespace Debugger { namespace Internal { +class ProcessListFilterModel; + struct ProcData { QString ppid; @@ -98,8 +98,7 @@ private: const QString m_selfPid; Ui::AttachExternalDialog *m_ui; - QStandardItemModel *m_model; - QSortFilterProxyModel *m_proxyModel; + ProcessListFilterModel *m_model; }; @@ -116,11 +115,13 @@ public: private slots: void rebuildProcessList(); void procSelected(const QModelIndex &); + void pidChanged(const QString &); private: + inline QPushButton *okButton() const; Ui::AttachRemoteDialog *m_ui; QString m_defaultPID; - QStandardItemModel *m_model; + ProcessListFilterModel *m_model; }; -- GitLab