From 62dd2a5acb322e101c98f6f8f2b405a8958bcd5e Mon Sep 17 00:00:00 2001 From: mae Date: Thu, 26 Mar 2009 15:33:32 +0100 Subject: [PATCH 1/9] Compile without warnings --- src/plugins/cmakeprojectmanager/cmakeproject.cpp | 1 + src/plugins/qt4projectmanager/qt4runconfiguration.cpp | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp index e97d2b7f007..da3b1fa530c 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp @@ -215,6 +215,7 @@ void CMakeProject::parseCMakeLists() QString CMakeProject::buildParser(const QString &buildConfiguration) const { + Q_UNUSED(buildConfiguration); // TODO this is actually slightly wrong, but do i care? // this should call toolchain(buildConfiguration) if (!m_toolChain) diff --git a/src/plugins/qt4projectmanager/qt4runconfiguration.cpp b/src/plugins/qt4projectmanager/qt4runconfiguration.cpp index 64cb11b448c..0522fab8d35 100644 --- a/src/plugins/qt4projectmanager/qt4runconfiguration.cpp +++ b/src/plugins/qt4projectmanager/qt4runconfiguration.cpp @@ -89,8 +89,8 @@ Qt4RunConfigurationWidget::Qt4RunConfigurationWidget(Qt4RunConfiguration *qt4Run : QWidget(parent), m_qt4RunConfiguration(qt4RunConfiguration), m_ignoreChange(false), - m_isShown(false), - m_usingDyldImageSuffix(0) + m_usingDyldImageSuffix(0), + m_isShown(false) { QFormLayout *toplayout = new QFormLayout(this); toplayout->setMargin(0); From 0a99fef5a390271d988537dd587ea826631a4475 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= Date: Thu, 26 Mar 2009 15:40:53 +0100 Subject: [PATCH 2/9] Avoid automatically inserting unwanted closing parentheses This is for the case of function overloads where one overload takes no parameters. Solved by keeping track of the duplicate count. Done with Roberto Raggi. --- src/plugins/cpptools/cppcodecompletion.cpp | 5 +++-- src/plugins/texteditor/completionsupport.cpp | 2 ++ src/plugins/texteditor/icompletioncollector.h | 2 ++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/plugins/cpptools/cppcodecompletion.cpp b/src/plugins/cpptools/cppcodecompletion.cpp index 35b751104d3..1be7e410012 100644 --- a/src/plugins/cpptools/cppcodecompletion.cpp +++ b/src/plugins/cpptools/cppcodecompletion.cpp @@ -1224,8 +1224,9 @@ void CppCodeCompletion::complete(const TextEditor::CompletionItem &item) extraChars += QLatin1Char('('); // If the function takes no arguments, automatically place the closing parenthesis - if (function->argumentCount() == 0 || (function->argumentCount() == 1 && - function->argumentAt(0)->type()->isVoidType())) { + if (item.m_duplicateCount == 0 && (function->argumentCount() == 0 || + (function->argumentCount() == 1 && + function->argumentAt(0)->type()->isVoidType()))) { extraChars += QLatin1Char(')'); // If the function doesn't return anything, automatically place the semicolon, diff --git a/src/plugins/texteditor/completionsupport.cpp b/src/plugins/texteditor/completionsupport.cpp index 53de9ee66e1..2e456193ad5 100644 --- a/src/plugins/texteditor/completionsupport.cpp +++ b/src/plugins/texteditor/completionsupport.cpp @@ -186,6 +186,8 @@ QList CompletionSupport::getCompletions() const if (item.m_text != lastKey) { uniquelist.append(item); lastKey = item.m_text; + } else { + uniquelist.last().m_duplicateCount++; } } diff --git a/src/plugins/texteditor/icompletioncollector.h b/src/plugins/texteditor/icompletioncollector.h index c8c035802e4..49d70f18288 100644 --- a/src/plugins/texteditor/icompletioncollector.h +++ b/src/plugins/texteditor/icompletioncollector.h @@ -46,6 +46,7 @@ struct CompletionItem { CompletionItem(ICompletionCollector *collector = 0) : m_relevance(0), + m_duplicateCount(0), m_collector(collector) { } @@ -60,6 +61,7 @@ struct CompletionItem QIcon m_icon; QVariant m_data; int m_relevance; + int m_duplicateCount; ICompletionCollector *m_collector; }; From e83788f17bd5d2b416b819b41415f4de31992c9d Mon Sep 17 00:00:00 2001 From: mae Date: Thu, 26 Mar 2009 15:54:05 +0100 Subject: [PATCH 3/9] Show the "Open Documents" navigation bar widget in the default configuration. Contains some compatible versioning code to also show it to current users, but without destroying their manual setup. --- src/plugins/coreplugin/navigationwidget.cpp | 38 +++++++++++++++------ 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/src/plugins/coreplugin/navigationwidget.cpp b/src/plugins/coreplugin/navigationwidget.cpp index 2e360155908..f1940975467 100644 --- a/src/plugins/coreplugin/navigationwidget.cpp +++ b/src/plugins/coreplugin/navigationwidget.cpp @@ -238,16 +238,27 @@ void NavigationWidget::saveSettings(QSettings *settings) void NavigationWidget::restoreSettings(QSettings *settings) { - if (settings->contains("Navigation/Views")) { - QStringList views = settings->value("Navigation/Views").toStringList(); - for (int i=0; isetFactory(view); + int version = settings->value("Navigation/Version", 1).toInt(); + QStringList views = settings->value("Navigation/Views").toStringList(); + + bool restoreSplitterState = true; + if (version == 1) { + if (views.isEmpty()) + views += "Projects"; + if (!views.contains("Open Documents")) { + views += "Open Documents"; + restoreSplitterState = false; } + settings->setValue("Navigation/Version", 2); + } + + for (int i=0; isetFactory(view); } if (settings->contains("Navigation/Visible")) { @@ -256,8 +267,15 @@ void NavigationWidget::restoreSettings(QSettings *settings) setShown(true); } - if (settings->contains("Navigation/VerticalPosition")) + if (restoreSplitterState && settings->contains("Navigation/VerticalPosition")) { restoreState(settings->value("Navigation/VerticalPosition").toByteArray()); + } else { + QList sizes; + sizes += 256; + for (int i = views.size()-1; i; --i) + sizes.prepend(512); + setSizes(sizes); + } if (settings->contains("Navigation/Width")) { m_width = settings->value("Navigation/Width").toInt(); From 393a03747b081b9cdd49e723bec95ff4d3f1d53a Mon Sep 17 00:00:00 2001 From: con Date: Thu, 26 Mar 2009 16:13:01 +0100 Subject: [PATCH 4/9] Shortcut for just opening search dialog with last filter. Task-number: 237733 --- src/plugins/find/findplugin.cpp | 27 ++++++++++++++++--- src/plugins/find/findplugin.h | 1 + src/plugins/find/findtoolbar.cpp | 2 +- src/plugins/find/textfindconstants.h | 1 + .../projectexplorer/allprojectsfind.cpp | 2 +- .../projectexplorer/currentprojectfind.cpp | 2 +- 6 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/plugins/find/findplugin.cpp b/src/plugins/find/findplugin.cpp index ee62bea84bf..2a5d1047070 100644 --- a/src/plugins/find/findplugin.cpp +++ b/src/plugins/find/findplugin.cpp @@ -105,6 +105,14 @@ void FindPlugin::filterChanged() QTC_ASSERT(changedFilter, return); QTC_ASSERT(action, return); action->setEnabled(changedFilter->isEnabled()); + bool haveEnabledFilters = false; + foreach (IFindFilter *filter, m_filterActions.keys()) { + if (filter->isEnabled()) { + haveEnabledFilters = true; + break; + } + } + m_openFindDialog->setEnabled(haveEnabledFilters); } void FindPlugin::openFindFilter() @@ -112,8 +120,6 @@ void FindPlugin::openFindFilter() QAction *action = qobject_cast(sender()); QTC_ASSERT(action, return); IFindFilter *filter = action->data().value(); - QTC_ASSERT(filter, return); - QTC_ASSERT(filter->isEnabled(), return); QString currentFindString = (m_currentDocumentFind->isEnabled() ? m_currentDocumentFind->currentFindString() : ""); if (!currentFindString.isEmpty()) m_findDialog->setFindText(currentFindString); @@ -127,6 +133,7 @@ void FindPlugin::setupMenu() Core::ActionContainer *mfind = am->createMenu(Constants::M_FIND); medit->addMenu(mfind, Core::Constants::G_EDIT_FIND); mfind->menu()->setTitle(tr("&Find/Replace")); + mfind->appendGroup(Constants::G_FIND_CURRENTDOCUMENT); mfind->appendGroup(Constants::G_FIND_FILTERS); mfind->appendGroup(Constants::G_FIND_FLAGS); mfind->appendGroup(Constants::G_FIND_ACTIONS); @@ -141,6 +148,12 @@ void FindPlugin::setupMenu() separator->setSeparator(true); cmd = am->registerAction(separator, QLatin1String("Find.Sep.Actions"), globalcontext); mfind->addAction(cmd, Constants::G_FIND_ACTIONS); + + m_openFindDialog = new QAction(tr("Find Dialog"), this); + cmd = am->registerAction(m_openFindDialog, QLatin1String("Find.Dialog"), globalcontext); + cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+F"))); + mfind->addAction(cmd, Constants::G_FIND_FILTERS); + connect(m_openFindDialog, SIGNAL(triggered()), this, SLOT(openFindFilter())); } void FindPlugin::setupFilterMenuItems() @@ -153,9 +166,13 @@ void FindPlugin::setupFilterMenuItems() Core::ActionContainer *mfind = am->actionContainer(Constants::M_FIND); m_filterActions.clear(); + bool haveEnabledFilters = false; foreach (IFindFilter *filter, findInterfaces) { - QAction *action = new QAction(filter->name(), this); - action->setEnabled(filter->isEnabled()); + QAction *action = new QAction(QString(" %1").arg(filter->name()), this); + bool isEnabled = filter->isEnabled(); + if (isEnabled) + haveEnabledFilters = true; + action->setEnabled(isEnabled); action->setData(qVariantFromValue(filter)); cmd = am->registerAction(action, QLatin1String("FindFilter.")+filter->name(), globalcontext); cmd->setDefaultKeySequence(filter->defaultShortcut()); @@ -165,6 +182,8 @@ void FindPlugin::setupFilterMenuItems() connect(filter, SIGNAL(changed()), this, SLOT(filterChanged())); } m_findDialog->setFindFilters(findInterfaces); + m_openFindDialog->setEnabled(haveEnabledFilters); + } QTextDocument::FindFlags FindPlugin::findFlags() const diff --git a/src/plugins/find/findplugin.h b/src/plugins/find/findplugin.h index 53bd805aaa2..a4c2ce28382 100644 --- a/src/plugins/find/findplugin.h +++ b/src/plugins/find/findplugin.h @@ -97,6 +97,7 @@ private: QStringListModel *m_replaceCompletionModel; QStringList m_findCompletions; QStringList m_replaceCompletions; + QAction *m_openFindDialog; }; } // namespace Internal diff --git a/src/plugins/find/findtoolbar.cpp b/src/plugins/find/findtoolbar.cpp index 2c2295740d0..97f66d5d275 100644 --- a/src/plugins/find/findtoolbar.cpp +++ b/src/plugins/find/findtoolbar.cpp @@ -149,7 +149,7 @@ FindToolBar::FindToolBar(FindPlugin *plugin, CurrentDocumentFind *currentDocumen m_findInDocumentAction = new QAction(tr("Current Document"), this); cmd = am->registerAction(m_findInDocumentAction, Constants::FIND_IN_DOCUMENT, globalcontext); cmd->setDefaultKeySequence(QKeySequence::Find); - mfind->addAction(cmd, Constants::G_FIND_FILTERS); + mfind->addAction(cmd, Constants::G_FIND_CURRENTDOCUMENT); connect(m_findInDocumentAction, SIGNAL(triggered()), this, SLOT(openFind())); if (QApplication::clipboard()->supportsFindBuffer()) { diff --git a/src/plugins/find/textfindconstants.h b/src/plugins/find/textfindconstants.h index 40394dfb857..a430c998976 100644 --- a/src/plugins/find/textfindconstants.h +++ b/src/plugins/find/textfindconstants.h @@ -34,6 +34,7 @@ namespace Find { namespace Constants { const char * const M_FIND = "Find.FindMenu"; +const char * const G_FIND_CURRENTDOCUMENT = "Find.FindMenu.CurrentDocument"; const char * const G_FIND_FILTERS = "Find.FindMenu.Filters"; const char * const G_FIND_FLAGS = "Find.FindMenu.Flags"; const char * const G_FIND_ACTIONS = "Find.FindMenu.Actions"; diff --git a/src/plugins/projectexplorer/allprojectsfind.cpp b/src/plugins/projectexplorer/allprojectsfind.cpp index af0a962ec34..c6448c2f801 100644 --- a/src/plugins/projectexplorer/allprojectsfind.cpp +++ b/src/plugins/projectexplorer/allprojectsfind.cpp @@ -65,7 +65,7 @@ bool AllProjectsFind::isEnabled() const QKeySequence AllProjectsFind::defaultShortcut() const { - return QKeySequence("Ctrl+Shift+F"); + return QKeySequence(); } QStringList AllProjectsFind::files() diff --git a/src/plugins/projectexplorer/currentprojectfind.cpp b/src/plugins/projectexplorer/currentprojectfind.cpp index 123efdbb824..4fcfc68642e 100644 --- a/src/plugins/projectexplorer/currentprojectfind.cpp +++ b/src/plugins/projectexplorer/currentprojectfind.cpp @@ -64,7 +64,7 @@ bool CurrentProjectFind::isEnabled() const QKeySequence CurrentProjectFind::defaultShortcut() const { - return QKeySequence("Ctrl+Alt+F"); + return QKeySequence(); } QStringList CurrentProjectFind::files() From 536320ea1ac63c83b6e6777a0dabe7d47e9ba8cd Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 26 Mar 2009 16:49:28 +0100 Subject: [PATCH 5/9] Start stack frame context/symbol group classes for CDB --- src/plugins/debugger/cdb/cdb.pri | 8 +- src/plugins/debugger/cdb/cdbdebugengine.cpp | 247 ++++++------------ src/plugins/debugger/cdb/cdbdebugengine_p.h | 21 +- .../debugger/cdb/cdbstacktracecontext.cpp | 161 ++++++++++++ .../debugger/cdb/cdbstacktracecontext.h | 86 ++++++ .../debugger/cdb/cdbsymbolgroupcontext.cpp | 177 +++++++++++++ .../debugger/cdb/cdbsymbolgroupcontext.h | 110 ++++++++ src/plugins/debugger/gdbengine.cpp | 12 +- src/plugins/debugger/stackhandler.cpp | 10 + src/plugins/debugger/stackhandler.h | 3 + 10 files changed, 642 insertions(+), 193 deletions(-) create mode 100644 src/plugins/debugger/cdb/cdbstacktracecontext.cpp create mode 100644 src/plugins/debugger/cdb/cdbstacktracecontext.h create mode 100644 src/plugins/debugger/cdb/cdbsymbolgroupcontext.cpp create mode 100644 src/plugins/debugger/cdb/cdbsymbolgroupcontext.h diff --git a/src/plugins/debugger/cdb/cdb.pri b/src/plugins/debugger/cdb/cdb.pri index 27186577c30..8ba7d3a6865 100644 --- a/src/plugins/debugger/cdb/cdb.pri +++ b/src/plugins/debugger/cdb/cdb.pri @@ -22,12 +22,16 @@ HEADERS += \ $$PWD/cdbdebugengine.h \ $$PWD/cdbdebugengine_p.h \ $$PWD/cdbdebugeventcallback.h \ - $$PWD/cdbdebugoutput.h + $$PWD/cdbdebugoutput.h \ + $$PWD/cdbsymbolgroupcontext.h \ + $$PWD/cdbstacktracecontext.h SOURCES += \ $$PWD/cdbdebugengine.cpp \ $$PWD/cdbdebugeventcallback.cpp \ - $$PWD/cdbdebugoutput.cpp + $$PWD/cdbdebugoutput.cpp \ + $$PWD/cdbsymbolgroupcontext.cpp \ + $$PWD/cdbstacktracecontext.cpp } else { message("Debugging Tools for Windows could not be found in $$CDB_PATH") } diff --git a/src/plugins/debugger/cdb/cdbdebugengine.cpp b/src/plugins/debugger/cdb/cdbdebugengine.cpp index 73d3953ffb3..7d054e68dd4 100644 --- a/src/plugins/debugger/cdb/cdbdebugengine.cpp +++ b/src/plugins/debugger/cdb/cdbdebugengine.cpp @@ -29,6 +29,8 @@ #include "cdbdebugengine.h" #include "cdbdebugengine_p.h" +#include "cdbsymbolgroupcontext.h" +#include "cdbstacktracecontext.h" #include "debuggermanager.h" #include "breakhandler.h" @@ -55,7 +57,12 @@ static const char *dbgEngineDllC = "dbgeng"; static const char *debugCreateFuncC = "DebugCreate"; -static QString msgDebugEngineComResult(HRESULT hr) +static const char *localSymbolRootC = "local"; + +namespace Debugger { +namespace Internal { + +QString msgDebugEngineComResult(HRESULT hr) { switch (hr) { case S_OK: @@ -87,13 +94,12 @@ static QString msgStackIndexOutOfRange(int idx, int size) return QString::fromLatin1("Frame index %1 out of range (%2).").arg(idx).arg(size); } -static QString msgComFailed(const char *func, HRESULT hr) +QString msgComFailed(const char *func, HRESULT hr) { return QString::fromLatin1("%1 failed: %2").arg(QLatin1String(func), msgDebugEngineComResult(hr)); } -namespace Debugger { -namespace Internal { +static const char *msgNoStackTraceC = "Internal error: no stack trace present."; DebuggerEngineLibrary::DebuggerEngineLibrary() : m_debugCreate(0) @@ -138,6 +144,7 @@ CdbDebugEnginePrivate::CdbDebugEnginePrivate(DebuggerManager *parent, CdbDebugEn m_engine(engine), m_debuggerManager(parent), m_debuggerManagerAccess(parent->engineInterface()), + m_currentStackTrace(0), m_mode(AttachCore) { } @@ -205,6 +212,7 @@ IDebuggerEngine *CdbDebugEngine::create(DebuggerManager *parent) CdbDebugEnginePrivate::~CdbDebugEnginePrivate() { + cleanStackTrace(); if (m_pDebugClient) m_pDebugClient->Release(); if (m_pDebugControl) @@ -217,6 +225,17 @@ CdbDebugEnginePrivate::~CdbDebugEnginePrivate() m_pDebugRegisters->Release(); } +void CdbDebugEnginePrivate::cleanStackTrace() +{ + if (debugCDB) + qDebug() << Q_FUNC_INFO; + + if (m_currentStackTrace) { + delete m_currentStackTrace; + m_currentStackTrace = 0; + } +} + CdbDebugEngine::CdbDebugEngine(DebuggerManager *parent) : IDebuggerEngine(parent), m_d(new CdbDebugEnginePrivate(parent, this)) @@ -366,6 +385,7 @@ void CdbDebugEngine::processTerminated(unsigned long exitCode) if (debugCDB) qDebug() << Q_FUNC_INFO << exitCode; + m_d->cleanStackTrace(); m_d->setDebuggeeHandles(0, 0); m_d->m_debuggerManagerAccess->notifyInferiorExited(); m_d->m_debuggerManager->exitDebugger(); @@ -377,6 +397,7 @@ void CdbDebugEngine::exitDebugger() qDebug() << Q_FUNC_INFO; if (m_d->m_hDebuggeeProcess) { + m_d->cleanStackTrace(); // Terminate or detach if we are running HRESULT hr; switch (m_d->m_mode) { @@ -407,47 +428,22 @@ void CdbDebugEngine::exitDebugger() killWatchTimer(); } -// Retrieve a symbol -static WatchData symbolToWatchData(ULONG index, const QString &namePrefix, - IDebugSymbolGroup2 *pDbgSymGroup) +class ModelBuildIterator { +public: + explicit ModelBuildIterator(WatchHandler *wh) : m_wh(wh) {} + + ModelBuildIterator & operator*() { return *this; } + ModelBuildIterator &operator=(const WatchData &wd); + ModelBuildIterator &operator++() { return *this; } + +private: + WatchHandler *m_wh; +}; + +ModelBuildIterator &ModelBuildIterator::operator=(const WatchData &wd) { - // retrieve symbol names and value strings - ULONG nameLength; - static WCHAR nameBuffer[MAX_PATH + 1]; - // Name - pDbgSymGroup->GetSymbolNameWide(index, nameBuffer, MAX_PATH, &nameLength); - nameBuffer[nameLength] = 0; - const QString name = QString::fromUtf16(nameBuffer); - // Type name - pDbgSymGroup->GetSymbolTypeNameWide(index, nameBuffer, MAX_PATH, &nameLength); - nameBuffer[nameLength] = 0; - const QString type = QString::fromUtf16(nameBuffer); - // Value - QString value; - const HRESULT hr = pDbgSymGroup->GetSymbolValueTextWide(index, nameBuffer, MAX_PATH, &nameLength); - if (SUCCEEDED(hr)) { - nameBuffer[nameLength] = 0; - value = QString::fromUtf16(nameBuffer); - } else { - value = QLatin1String(""); - } - WatchData wd; - wd.iname =namePrefix + name; - wd.name = name; - wd.value = value; - wd.type = type; - if (isPointerType(type)) { - wd.setTypeUnneeded(); - wd.setValueUnneeded(); - } else { - wd.setAllUnneeded(); - } - if (debugCDB) { - qDebug() << Q_FUNC_INFO << index << "state=0x" << QString::number(wd.state, 16) - << wd.name << " type=" << wd.type << " (" << type << ')' - << " value " << wd.value << " (" << value << ')'; - } - return wd; + m_wh->insertData(wd); + return *this; } bool CdbDebugEnginePrivate::updateLocals(int frameIndex, @@ -456,82 +452,36 @@ bool CdbDebugEnginePrivate::updateLocals(int frameIndex, { if (debugCDB) qDebug() << Q_FUNC_INFO << frameIndex; - - CdbStackTrace cdbStackTrace; - if (!getCdbStrackTrace(&cdbStackTrace, errorMessage)) - return false; - - if ((unsigned)frameIndex >= cdbStackTrace.frameCount) { - *errorMessage = msgStackIndexOutOfRange(frameIndex, cdbStackTrace.frameCount); - return false; - } - - IDebugSymbolGroup2 *pDbgSymGroup = 0; - DEBUG_SYMBOL_PARAMETERS *symParams = 0; bool success = false; - + wh->cleanup(); do { - HRESULT hr = m_pDebugSymbols->GetScopeSymbolGroup2(DEBUG_SCOPE_GROUP_LOCALS, NULL, &pDbgSymGroup); - if (FAILED(hr)) { - *errorMessage = msgComFailed("GetScopeSymbolGroup", hr); + if (!m_currentStackTrace) { + *errorMessage = QLatin1String(msgNoStackTraceC); break; } - hr = m_pDebugSymbols->SetScope(0, cdbStackTrace.frames + frameIndex, NULL, 0); - if (FAILED(hr)) { - *errorMessage = msgComFailed("SetScope", hr); + CdbSymbolGroupContext *sgc = m_currentStackTrace->symbolGroupContextAt(frameIndex, errorMessage); + if (!sgc) { break; } - // refresh with current frame - hr = m_pDebugSymbols->GetScopeSymbolGroup2(DEBUG_SCOPE_GROUP_LOCALS, pDbgSymGroup, &pDbgSymGroup); - if (FAILED(hr)) { - *errorMessage = msgComFailed("GetScopeSymbolGroup", hr); - break; - } - - ULONG symbolCount; - hr = pDbgSymGroup->GetNumberSymbols(&symbolCount); - if (FAILED(hr)) { - *errorMessage = msgComFailed("GetNumberSymbols", hr); - break; - } - - symParams = new DEBUG_SYMBOL_PARAMETERS[symbolCount]; - hr = pDbgSymGroup->GetSymbolParameters(0, symbolCount, symParams); - if (FAILED(hr)) { - *errorMessage = msgComFailed("GetSymbolParameters", hr); - break; - } - wh->cleanup(); - // retrieve symbol names and value strings. - // Add a dummy place holder in case children are needed - const QString localPrefix = QLatin1String("local."); - for (ULONG s = 0 ; s < symbolCount ; s++ ) { - WatchData wd = symbolToWatchData(s, localPrefix, pDbgSymGroup); - if (wd.isSomethingNeeded()) { - wh->insertData(wd.pointerChildPlaceHolder()); - wd.setAllUnneeded(); - wd.setChildCount(1); - } - wh->insertData(wd); - } - wh->rebuildModel(); + ModelBuildIterator it(wh); + sgc->getSymbols(sgc->prefix(), it); success = true; } while (false); + wh->rebuildModel(); - delete [] symParams; - if (pDbgSymGroup) - pDbgSymGroup->Release(); return success; } - void CdbDebugEngine::updateWatchModel() { WatchHandler *watchHandler = m_d->m_debuggerManagerAccess->watchHandler(); const QList incomplete = watchHandler->takeCurrentIncompletes(); + if (debugCDB) qDebug() << Q_FUNC_INFO << incomplete.size(); + foreach (const WatchData& wd, incomplete) + qDebug() << Q_FUNC_INFO << wd.toString(); } void CdbDebugEngine::stepExec() @@ -540,8 +490,9 @@ void CdbDebugEngine::stepExec() qDebug() << Q_FUNC_INFO; //m_pDebugControl->Execute(DEBUG_OUTCTL_THIS_CLIENT, "p", 0); - HRESULT hr; - hr = m_d->m_pDebugControl->SetExecutionStatus(DEBUG_STATUS_STEP_INTO); + m_d->cleanStackTrace(); + const HRESULT hr = m_d->m_pDebugControl->SetExecutionStatus(DEBUG_STATUS_STEP_INTO); + Q_UNUSED(hr) m_d->m_bIgnoreNextDebugEvent = true; startWatchTimer(); } @@ -594,6 +545,7 @@ void CdbDebugEngine::nextExec() if (debugCDB) qDebug() << Q_FUNC_INFO; + m_d->cleanStackTrace(); const HRESULT hr = m_d->m_pDebugControl->SetExecutionStatus(DEBUG_STATUS_STEP_OVER); if (SUCCEEDED(hr)) { startWatchTimer(); @@ -612,6 +564,7 @@ void CdbDebugEngine::nextIExec() if (debugCDB) qDebug() << Q_FUNC_INFO; + m_d->cleanStackTrace(); const HRESULT hr = m_d->m_pDebugControl->Execute(DEBUG_OUTCTL_THIS_CLIENT, "p", 0); if (SUCCEEDED(hr)) { startWatchTimer(); @@ -625,6 +578,7 @@ void CdbDebugEngine::continueInferior() if (debugCDB) qDebug() << Q_FUNC_INFO; + m_d->cleanStackTrace(); killWatchTimer(); m_d->m_debuggerManager->resetLocation(); @@ -714,7 +668,7 @@ void CdbDebugEngine::activateFrame(int frameIndex) } const StackFrame &frame = stackHandler->currentFrame(); - if (frame.file.isEmpty() || !QFileInfo(frame.file).isReadable()) { + if (!frame.isUsable()) { errorMessage = QString::fromLatin1("%1: file %2 unusable."). arg(QLatin1String(Q_FUNC_INFO), frame.file); break; @@ -933,78 +887,29 @@ void CdbDebugEnginePrivate::updateThreadList() th->setThreads(threads); } -// Get CDB stack trace -bool CdbDebugEnginePrivate::getCdbStrackTrace(CdbStackTrace *st, QString *errorMessage) -{ - HRESULT hr = m_pDebugSystemObjects->SetCurrentThreadId(m_currentThreadId); - if (FAILED(hr)) { - *errorMessage = QString::fromLatin1("%1: SetCurrentThreadId %2 failed: %3"). - arg(QString::fromLatin1(Q_FUNC_INFO)). - arg(m_currentThreadId). - arg(msgDebugEngineComResult(hr)); - return false; - } - hr = m_pDebugControl->GetStackTrace(0, 0, 0, st->frames, CdbStackTrace::maxFrames, &(st->frameCount)); - if (FAILED(hr)) { - *errorMessage = *errorMessage = msgComFailed("GetStackTrace", hr); - return false; - } - return true; -} - -bool CdbDebugEnginePrivate::getStackTrace(QList *stackFrames, - int *current, QString *errorMessage) -{ - stackFrames->clear(); - *current = -1; - // Get the CDB trace and convert into debugger plugin structures - CdbStackTrace cdbStackTrace; - if (!getCdbStrackTrace(&cdbStackTrace, errorMessage)) - return false; - - WCHAR wszBuf[MAX_PATH]; - for (ULONG i=0; i < cdbStackTrace.frameCount; ++i) { - StackFrame frame; - frame.line = 0; - frame.level = i; - frame.address = QString::fromLatin1("0x%1").arg(cdbStackTrace.frames[i].InstructionOffset, 0, 16); - - m_pDebugSymbols->GetNameByOffsetWide(cdbStackTrace.frames[i].InstructionOffset, wszBuf, MAX_PATH, 0, 0); - frame.function = QString::fromUtf16(wszBuf); - - ULONG ulLine; - ULONG ulFileNameSize; - ULONG64 ul64Displacement; - const HRESULT hr = m_pDebugSymbols->GetLineByOffsetWide(cdbStackTrace.frames[i].InstructionOffset, &ulLine, wszBuf, MAX_PATH, &ulFileNameSize, &ul64Displacement); - if (SUCCEEDED(hr)) { - frame.line = ulLine; - frame.file = QString::fromUtf16(wszBuf, ulFileNameSize); - } - stackFrames->append(frame); - } - - // find the first usable frame and select it - const int count = stackFrames->count(); - for (int i=0; i < count; ++i) { - const StackFrame &frame = stackFrames->at(i); - const bool usable = !frame.file.isEmpty() && QFileInfo(frame.file).isReadable(); - if (usable) { - *current = i; - break; - } - } - return true; -} - void CdbDebugEnginePrivate::updateStackTrace() { if (debugCDB) qDebug() << Q_FUNC_INFO; - QList stackFrames; - int current; + // Create a new context + cleanStackTrace(); QString errorMessage; - if (getStackTrace(&stackFrames, ¤t, &errorMessage)) - qWarning("%s", qPrintable(errorMessage)); + m_currentStackTrace = + CdbStackTraceContext::create(m_pDebugControl, m_pDebugSystemObjects, + m_pDebugSymbols, m_currentThreadId, &errorMessage); + if (!m_currentStackTrace) { + qWarning("%s: failed to create trace context: %s", Q_FUNC_INFO, qPrintable(errorMessage)); + return; + } + const QList stackFrames = m_currentStackTrace->frames(); + // find the first usable frame and select it + int current = -1; + const int count = stackFrames.count(); + for (int i=0; i < count; ++i) + if (stackFrames.at(i).isUsable()) { + current = i; + break; + } m_debuggerManagerAccess->stackHandler()->setFrames(stackFrames); if (current >= 0) { diff --git a/src/plugins/debugger/cdb/cdbdebugengine_p.h b/src/plugins/debugger/cdb/cdbdebugengine_p.h index e6235569a07..e1991f707de 100644 --- a/src/plugins/debugger/cdb/cdbdebugengine_p.h +++ b/src/plugins/debugger/cdb/cdbdebugengine_p.h @@ -42,6 +42,8 @@ namespace Internal { class DebuggerManager; class IDebuggerManagerAccessForEngines; class WatchHandler; +class CdbSymbolGroupContext; +class CdbStackTraceContext; // Thin wrapper around the 'DBEng' debugger engine shared library // which is loaded at runtime. @@ -61,16 +63,6 @@ private: DebugCreateFunction m_debugCreate; }; - -// Helper struct for stack traces -struct CdbStackTrace { - CdbStackTrace() : frameCount(0) {} - enum { maxFrames = 100 }; - - ULONG frameCount; - DEBUG_STACK_FRAME frames[maxFrames]; -}; - struct CdbDebugEnginePrivate { explicit CdbDebugEnginePrivate(DebuggerManager *parent, CdbDebugEngine* engine); @@ -84,10 +76,9 @@ struct CdbDebugEnginePrivate void updateThreadList(); void updateStackTrace(); bool updateLocals(int frameIndex, WatchHandler *wh, QString *errorMessage); - bool getCdbStrackTrace(CdbStackTrace *st, QString *errorMessage); - bool getStackTrace(QList *stackFrames, int *current, QString *errorMessage); void handleDebugOutput(const char* szOutputString); void handleBreakpointEvent(PDEBUG_BREAKPOINT pBP); + void cleanStackTrace(); HANDLE m_hDebuggeeProcess; HANDLE m_hDebuggeeThread; @@ -106,10 +97,16 @@ struct CdbDebugEnginePrivate CdbDebugEngine* m_engine; DebuggerManager *m_debuggerManager; IDebuggerManagerAccessForEngines *m_debuggerManagerAccess; + CdbStackTraceContext *m_currentStackTrace; + DebuggerStartMode m_mode; Core::Utils::ConsoleProcess m_consoleStubProc; }; +// Message +QString msgDebugEngineComResult(HRESULT hr); +QString msgComFailed(const char *func, HRESULT hr); + enum { debugCDB = 0 }; } // namespace Internal diff --git a/src/plugins/debugger/cdb/cdbstacktracecontext.cpp b/src/plugins/debugger/cdb/cdbstacktracecontext.cpp new file mode 100644 index 00000000000..d569c6a9bae --- /dev/null +++ b/src/plugins/debugger/cdb/cdbstacktracecontext.cpp @@ -0,0 +1,161 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +**************************************************************************/ + +#include "cdbstacktracecontext.h" +#include "cdbsymbolgroupcontext.h" +#include "cdbdebugengine_p.h" + +namespace Debugger { +namespace Internal { + +CdbStackTraceContext::CdbStackTraceContext(IDebugSystemObjects4* pDebugSystemObjects, + IDebugSymbols3* pDebugSymbols) : + m_pDebugSystemObjects(pDebugSystemObjects), + m_pDebugSymbols(pDebugSymbols) +{ +} + +CdbStackTraceContext *CdbStackTraceContext::create(IDebugControl4* pDebugControl, + IDebugSystemObjects4* pDebugSystemObjects, + IDebugSymbols3* pDebugSymbols, + unsigned long threadId, + QString *errorMessage) +{ + if (debugCDB) + qDebug() << Q_FUNC_INFO << threadId; + HRESULT hr = pDebugSystemObjects->SetCurrentThreadId(threadId); + if (FAILED(hr)) { + *errorMessage = QString::fromLatin1("%1: SetCurrentThreadId %2 failed: %3"). + arg(QString::fromLatin1(Q_FUNC_INFO)). + arg(threadId). + arg(msgDebugEngineComResult(hr)); + return 0; + } + // fill the DEBUG_STACK_FRAME array + ULONG frameCount; + CdbStackTraceContext *ctx = new CdbStackTraceContext(pDebugSystemObjects, pDebugSymbols); + hr = pDebugControl->GetStackTrace(0, 0, 0, ctx->m_cdbFrames, CdbStackTraceContext::maxFrames, &frameCount); + if (FAILED(hr)) { + delete ctx; + *errorMessage = msgComFailed("GetStackTrace", hr); + return 0; + } + if (!ctx->init(frameCount, errorMessage)) { + delete ctx; + return 0; + + } + return ctx; +} + +CdbStackTraceContext::~CdbStackTraceContext() +{ + qDeleteAll(m_symbolContexts); +} + +bool CdbStackTraceContext::init(unsigned long frameCount, QString * /*errorMessage*/) +{ + if (debugCDB) + qDebug() << Q_FUNC_INFO << frameCount; + + m_symbolContexts.resize(frameCount); + qFill(m_symbolContexts, static_cast(0)); + + // Convert the DEBUG_STACK_FRAMEs to our StackFrame structure and populate the frames + WCHAR wszBuf[MAX_PATH]; + for (ULONG i=0; i < frameCount; ++i) { + StackFrame frame(i); + const ULONG64 instructionOffset = m_cdbFrames[i].InstructionOffset; + frame.address = QString::fromLatin1("0x%1").arg(instructionOffset, 0, 16); + + m_pDebugSymbols->GetNameByOffsetWide(instructionOffset, wszBuf, MAX_PATH, 0, 0); + frame.function = QString::fromUtf16(wszBuf); + + ULONG ulLine; + ULONG ulFileNameSize; + ULONG64 ul64Displacement; + const HRESULT hr = m_pDebugSymbols->GetLineByOffsetWide(instructionOffset, &ulLine, wszBuf, MAX_PATH, &ulFileNameSize, &ul64Displacement); + if (SUCCEEDED(hr)) { + frame.line = ulLine; + frame.file = QString::fromUtf16(wszBuf, ulFileNameSize); + } + m_frames.push_back(frame); + } + return true; +} + +CdbSymbolGroupContext *CdbStackTraceContext::symbolGroupContextAt(int index, QString *errorMessage) +{ + // Create a symbol group on demand + if (debugCDB) + qDebug() << Q_FUNC_INFO << index << m_symbolContexts.at(index); + + if (index < 0 || index >= m_symbolContexts.size()) { + *errorMessage = QString::fromLatin1("%1: Index %2 out of range %3."). + arg(QLatin1String(Q_FUNC_INFO)).arg(index).arg(m_symbolContexts.size()); + return 0; + } + + if (m_symbolContexts.at(index)) + return m_symbolContexts.at(index); + IDebugSymbolGroup2 *sg = createSymbolGroup(index, errorMessage); + if (!sg) + return 0; + CdbSymbolGroupContext *sc = new CdbSymbolGroupContext(QLatin1String("local"), sg); + m_symbolContexts[index] = sc; + return sc; +} + +IDebugSymbolGroup2 *CdbStackTraceContext::createSymbolGroup(int index, QString *errorMessage) +{ + IDebugSymbolGroup2 *sg = 0; + HRESULT hr = m_pDebugSymbols->GetScopeSymbolGroup2(DEBUG_SCOPE_GROUP_LOCALS, NULL, &sg); + if (FAILED(hr)) { + *errorMessage = msgComFailed("GetScopeSymbolGroup", hr); + return 0; + } + + hr = m_pDebugSymbols->SetScope(0, m_cdbFrames + index, NULL, 0); + if (FAILED(hr)) { + *errorMessage = msgComFailed("SetScope", hr); + sg->Release(); + return 0; + } + // refresh with current frame + hr = m_pDebugSymbols->GetScopeSymbolGroup2(DEBUG_SCOPE_GROUP_LOCALS, sg, &sg); + if (FAILED(hr)) { + *errorMessage = msgComFailed("GetScopeSymbolGroup", hr); + sg->Release(); + return 0; + } + return sg; +} + +} +} diff --git a/src/plugins/debugger/cdb/cdbstacktracecontext.h b/src/plugins/debugger/cdb/cdbstacktracecontext.h new file mode 100644 index 00000000000..bb8286859ef --- /dev/null +++ b/src/plugins/debugger/cdb/cdbstacktracecontext.h @@ -0,0 +1,86 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +**************************************************************************/ + +#ifndef CDBSTACKTRACECONTEXT_H +#define CDBSTACKTRACECONTEXT_H + +#include "stackhandler.h" + +#include +#include + +#include +#include + +namespace Debugger { +namespace Internal { + +class CdbSymbolGroupContext; + +/* Context representing a break point stack consisting of several frames. + * Maintains an on-demand constructed list of CdbSymbolGroupContext + * containining the local variables of the stack. */ + +class CdbStackTraceContext +{ + Q_DISABLE_COPY(CdbStackTraceContext) + + explicit CdbStackTraceContext(IDebugSystemObjects4* pDebugSystemObjects, + IDebugSymbols3* pDebugSymbols); +public: + enum { maxFrames = 100 }; + + ~CdbStackTraceContext(); + static CdbStackTraceContext *create(IDebugControl4* pDebugControl, + IDebugSystemObjects4* pDebugSystemObjects, + IDebugSymbols3* pDebugSymbols, + unsigned long threadid, + QString *errorMessage); + + QList frames() const { return m_frames; } + inline int frameCount() const { return m_frames.size(); } + + CdbSymbolGroupContext *symbolGroupContextAt(int index, QString *errorMessage); + +private: + bool init(unsigned long frameCount, QString *errorMessage); + IDebugSymbolGroup2 *createSymbolGroup(int index, QString *errorMessage); + + IDebugSystemObjects4* m_pDebugSystemObjects; + IDebugSymbols3* m_pDebugSymbols; + + DEBUG_STACK_FRAME m_cdbFrames[maxFrames]; + QVector m_symbolContexts; + QList m_frames; +}; + +} +} + +#endif // CDBSTACKTRACECONTEXT_H diff --git a/src/plugins/debugger/cdb/cdbsymbolgroupcontext.cpp b/src/plugins/debugger/cdb/cdbsymbolgroupcontext.cpp new file mode 100644 index 00000000000..aa52ef55e1a --- /dev/null +++ b/src/plugins/debugger/cdb/cdbsymbolgroupcontext.cpp @@ -0,0 +1,177 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +**************************************************************************/ + +#include "cdbsymbolgroupcontext.h" +#include "cdbdebugengine_p.h" +#include "watchhandler.h" + +// A helper function to extract a string value from a member function of +// IDebugSymbolGroup2 taking the symbol index and a character buffer. +// Pass in the the member function as '&IDebugSymbolGroup2::GetSymbolNameWide' + +typedef HRESULT (__stdcall IDebugSymbolGroup2::*WideStringRetrievalFunction)(ULONG, PWSTR, ULONG, PULONG); + +static inline QString getSymbolString(IDebugSymbolGroup2 *sg, + WideStringRetrievalFunction wsf, + unsigned long index) +{ + static WCHAR nameBuffer[MAX_PATH + 1]; + // Name + ULONG nameLength; + const HRESULT hr = (sg->*wsf)(index, nameBuffer, MAX_PATH, &nameLength); + if (SUCCEEDED(hr)) { + nameBuffer[nameLength] = 0; + return QString::fromUtf16(nameBuffer); + } + return QString(); +} + +namespace Debugger { + namespace Internal { + +CdbSymbolGroupContext::CdbSymbolGroupContext(const QString &prefix, + IDebugSymbolGroup2 *symbolGroup) : + m_prefix(prefix), + m_nameDelimiter(QLatin1Char('.')), + m_symbolGroup(symbolGroup) +{ +} + +CdbSymbolGroupContext::~CdbSymbolGroupContext() +{ + m_symbolGroup->Release(); +} + +CdbSymbolGroupContext::Range + CdbSymbolGroupContext::getSymbolRange(const QString &prefix) +{ + if (debugCDB) + qDebug() << Q_FUNC_INFO << prefix; + const ChildRangeMap::const_iterator it = m_childRanges.constFind(prefix); + if (it != m_childRanges.constEnd()) + return it.value(); + const Range r = prefix == m_prefix ? allocateRootSymbols() : allocateChildSymbols(prefix); + m_childRanges.insert(prefix, r); + return r; +} + +CdbSymbolGroupContext::Range + CdbSymbolGroupContext::allocateChildSymbols(const QString &prefix) +{ + unsigned long startPos = 0; + unsigned long count = 0; + + bool success = false; + QString errorMessage; + do { + const int parentIndex = m_symbolINames.indexOf(prefix); + if (parentIndex == -1) { + errorMessage = QString::fromLatin1("Prefix not found '%1'").arg(prefix); + break; + } + + success = true; + } while (false); + if (!success) { + qWarning("%s\n", qPrintable(errorMessage)); + } + return Range(startPos, count); +} + +CdbSymbolGroupContext::Range + CdbSymbolGroupContext::allocateRootSymbols() +{ + unsigned long startPos = 0; + unsigned long count = 0; + bool success = false; + + QString errorMessage; + do { + HRESULT hr = m_symbolGroup->GetNumberSymbols(&count); + if (FAILED(hr)) { + errorMessage = msgComFailed("GetNumberSymbols", hr); + break; + } + + m_symbolParameters.reserve(3u * count); + m_symbolParameters.resize(count); + + hr = m_symbolGroup->GetSymbolParameters(0, count, symbolParameters()); + if (FAILED(hr)) { + errorMessage = msgComFailed("GetSymbolParameters", hr); + break; + } + const QString symbolPrefix = m_prefix + m_nameDelimiter; + for (unsigned long i = 0; i < count; i++) + m_symbolINames.push_back(symbolPrefix + getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolNameWide, i)); + + success = true; + } while (false); + if (!success) { + clear(); + count = 0; + qWarning("%s\n", qPrintable(errorMessage)); + } + return Range(startPos, count); +} + +void CdbSymbolGroupContext::clear() +{ + m_symbolParameters.clear(); + m_childRanges.clear(); + m_symbolINames.clear(); +} + +WatchData CdbSymbolGroupContext::symbolAt(unsigned long index) const +{ + if (debugCDB) + qDebug() << Q_FUNC_INFO << index; + + WatchData wd; + wd.iname = m_symbolINames.at(index); + const int lastDelimiterPos = wd.iname.lastIndexOf(m_nameDelimiter); + wd.name = lastDelimiterPos == -1 ? wd.iname : wd.iname.mid(lastDelimiterPos + 1); + wd.type = getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolTypeNameWide, index); + wd.value = getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolValueTextWide, index); + const DEBUG_SYMBOL_PARAMETERS ¶ms = m_symbolParameters.at(index); + if (params.SubElements) { + wd.setTypeUnneeded(); + wd.setValueUnneeded(); + wd.setChildCount(1); + } else { + wd.setAllUnneeded(); + } + if (debugCDB) { + qDebug() << Q_FUNC_INFO << wd.toString(); + } + return wd; +} + +} +} diff --git a/src/plugins/debugger/cdb/cdbsymbolgroupcontext.h b/src/plugins/debugger/cdb/cdbsymbolgroupcontext.h new file mode 100644 index 00000000000..e5c4ea7c9c7 --- /dev/null +++ b/src/plugins/debugger/cdb/cdbsymbolgroupcontext.h @@ -0,0 +1,110 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +**************************************************************************/ + +#ifndef CDBSYMBOLGROUPCONTEXT_H +#define CDBSYMBOLGROUPCONTEXT_H + +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace Debugger { + namespace Internal { + +class WatchData; + +/* A thin wrapper around the IDebugSymbolGroup2 interface which represents + * a flat list of symbols using an index (for example, belonging to a stack frame). + * It uses the hierarchical naming convention of WatchHandler as: + * "local" (invisible root) + * "local.string" (local class variable) + * "local.string.data" (class member). + * IDebugSymbolGroup2 can "expand" expandable symbols, appending to the flat list. + */ + +class CdbSymbolGroupContext +{ + Q_DISABLE_COPY(CdbSymbolGroupContext); + + // Start position and length of range in m_symbolParameters + typedef QPair Range; + +public: + explicit CdbSymbolGroupContext(const QString &prefix, + IDebugSymbolGroup2 *symbolGroup); + ~CdbSymbolGroupContext(); + + QString prefix() const { return m_prefix; } + + // Retrieve child symbols of prefix as a sequence of WatchData. + template + void getSymbols(const QString &prefix, OutputIterator it); + +private: + void clear(); + Range getSymbolRange(const QString &prefix); + Range allocateChildSymbols(const QString &prefix); + Range allocateRootSymbols(); + WatchData symbolAt(unsigned long index) const; + + inline DEBUG_SYMBOL_PARAMETERS *symbolParameters() { return &(*m_symbolParameters.begin()); } + inline const DEBUG_SYMBOL_PARAMETERS *symbolParameters() const { return &(*m_symbolParameters.constBegin()); } + + const QString m_prefix; + const QChar m_nameDelimiter; + IDebugSymbolGroup2 *m_symbolGroup; + + QStringList m_symbolINames; + QVector m_symbolParameters; + + typedef QMap ChildRangeMap; + + ChildRangeMap m_childRanges; +}; + +template +void CdbSymbolGroupContext::getSymbols(const QString &prefix, OutputIterator it) +{ + const Range r = getSymbolRange(prefix); + const unsigned long end = r.first + r.second; + for (unsigned long i = r.first; i < end; i++) { + *it = symbolAt(i); + ++it; + } +} + +} +} +#endif // CDBSYMBOLGROUPCONTEXT_H diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp index daf2e6e0c0b..4ef2b4c4555 100644 --- a/src/plugins/debugger/gdbengine.cpp +++ b/src/plugins/debugger/gdbengine.cpp @@ -2447,8 +2447,7 @@ void GdbEngine::handleStackListFrames(const GdbResultRecord &record) for (int i = 0; i != stack.childCount(); ++i) { //qDebug() << "HANDLING FRAME: " << stack.childAt(i).toString(); const GdbMi frameMi = stack.childAt(i); - StackFrame frame; - frame.level = i; + StackFrame frame(i); QStringList files; files.append(frameMi.findChild("fullname").data()); files.append(frameMi.findChild("file").data()); @@ -2488,8 +2487,7 @@ void GdbEngine::handleStackListFrames(const GdbResultRecord &record) if (0 && topFrame != -1) { // updates of locals already triggered early const StackFrame &frame = qq->stackHandler()->currentFrame(); - bool usable = !frame.file.isEmpty() && QFileInfo(frame.file).isReadable(); - if (usable) + if (frame.isUsable()) q->gotoLocation(frame.file, frame.line, true); else qDebug() << "FULL NAME NOT USABLE 0: " << frame.file; @@ -2500,8 +2498,7 @@ void GdbEngine::handleStackListFrames(const GdbResultRecord &record) if (topFrame != -1) { // updates of locals already triggered early const StackFrame &frame = qq->stackHandler()->currentFrame(); - bool usable = !frame.file.isEmpty() && QFileInfo(frame.file).isReadable(); - if (usable) + if (frame.isUsable()) q->gotoLocation(frame.file, frame.line, true); else qDebug() << "FULL NAME NOT USABLE 0: " << frame.file << topFrame; @@ -2551,8 +2548,7 @@ void GdbEngine::activateFrame(int frameIndex) const StackFrame &frame = stackHandler->currentFrame(); - bool usable = !frame.file.isEmpty() && QFileInfo(frame.file).isReadable(); - if (usable) + if (frame.isUsable()) q->gotoLocation(frame.file, frame.line, true); else qDebug() << "FULL NAME NOT USABLE: " << frame.file; diff --git a/src/plugins/debugger/stackhandler.cpp b/src/plugins/debugger/stackhandler.cpp index fcc28bdd19d..a131bc00428 100644 --- a/src/plugins/debugger/stackhandler.cpp +++ b/src/plugins/debugger/stackhandler.cpp @@ -37,6 +37,16 @@ using namespace Debugger::Internal; +StackFrame::StackFrame(int l) : + level(l), + line(0) +{ +} + +bool StackFrame::isUsable() const +{ + return !file.isEmpty() && QFileInfo(file).isReadable(); +} //////////////////////////////////////////////////////////////////////// // diff --git a/src/plugins/debugger/stackhandler.h b/src/plugins/debugger/stackhandler.h index d427c93e921..ae073e3d136 100644 --- a/src/plugins/debugger/stackhandler.h +++ b/src/plugins/debugger/stackhandler.h @@ -46,6 +46,9 @@ namespace Internal { struct StackFrame { + StackFrame(int level = 0); + bool isUsable() const; + int level; QString function; QString file; // we try to put an absolute file name in there From 5d8ee0d742ef591c23b99bdce29ddd4a4553e98d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= Date: Thu, 26 Mar 2009 16:43:38 +0100 Subject: [PATCH 6/9] Moved some complicated checks into convenience functions --- src/plugins/cpptools/cppcodecompletion.cpp | 9 ++------- src/shared/cplusplus/Symbols.cpp | 12 ++++++++++++ src/shared/cplusplus/Symbols.h | 6 ++++++ 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/plugins/cpptools/cppcodecompletion.cpp b/src/plugins/cpptools/cppcodecompletion.cpp index 1be7e410012..2bdaa6445f6 100644 --- a/src/plugins/cpptools/cppcodecompletion.cpp +++ b/src/plugins/cpptools/cppcodecompletion.cpp @@ -1209,10 +1209,7 @@ void CppCodeCompletion::complete(const TextEditor::CompletionItem &item) if (Function *function = symbol->type()->asFunctionType()) { // If the member is a function, automatically place the opening parenthesis, // except when it might take template parameters. - const bool hasReturnType = function->returnType().isValid() || - function->returnType().isSigned() || - function->returnType().isUnsigned(); - if (! hasReturnType && (function->identity() && !function->identity()->isDestructorNameId())) { + if (! function->hasReturnType() && (function->identity() && !function->identity()->isDestructorNameId())) { // Don't insert any magic, since the user might have just wanted to select the class } else if (function->templateParameterCount() != 0) { @@ -1224,9 +1221,7 @@ void CppCodeCompletion::complete(const TextEditor::CompletionItem &item) extraChars += QLatin1Char('('); // If the function takes no arguments, automatically place the closing parenthesis - if (item.m_duplicateCount == 0 && (function->argumentCount() == 0 || - (function->argumentCount() == 1 && - function->argumentAt(0)->type()->isVoidType()))) { + if (item.m_duplicateCount == 0 && ! function->hasArguments()) { extraChars += QLatin1Char(')'); // If the function doesn't return anything, automatically place the semicolon, diff --git a/src/shared/cplusplus/Symbols.cpp b/src/shared/cplusplus/Symbols.cpp index 5185aa82659..10b82664c34 100644 --- a/src/shared/cplusplus/Symbols.cpp +++ b/src/shared/cplusplus/Symbols.cpp @@ -217,6 +217,12 @@ FullySpecifiedType Function::returnType() const void Function::setReturnType(FullySpecifiedType returnType) { _returnType = returnType; } +bool Function::hasReturnType() const +{ + const FullySpecifiedType ty = returnType(); + return ty.isValid() || ty.isSigned() || ty.isUnsigned(); +} + unsigned Function::argumentCount() const { if (! _arguments) @@ -231,6 +237,12 @@ Symbol *Function::argumentAt(unsigned index) const Scope *Function::arguments() const { return _arguments; } +bool Function::hasArguments() const +{ + return ! (argumentCount() == 0 || + (argumentCount() == 1 && argumentAt(0)->type()->isVoidType())); +} + bool Function::isVariadic() const { return _isVariadic; } diff --git a/src/shared/cplusplus/Symbols.h b/src/shared/cplusplus/Symbols.h index 8efc0fbdbed..4052b746da2 100644 --- a/src/shared/cplusplus/Symbols.h +++ b/src/shared/cplusplus/Symbols.h @@ -288,10 +288,16 @@ public: FullySpecifiedType returnType() const; void setReturnType(FullySpecifiedType returnType); + /** Convenience function that returns whether the function returns something (including void). */ + bool hasReturnType() const; + unsigned argumentCount() const; Symbol *argumentAt(unsigned index) const; Scope *arguments() const; + /** Convenience function that returns whether the function receives any arguments. */ + bool hasArguments() const; + bool isVariadic() const; void setVariadic(bool isVariadic); From b96893205658a3158211269a1425e027e7179645 Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 26 Mar 2009 15:14:17 +0100 Subject: [PATCH 7/9] debugger: work on action handling --- src/plugins/debugger/debuggeractions.cpp | 17 +++++++---------- src/plugins/debugger/debuggeractions.h | 2 -- src/plugins/debugger/gdbengine.cpp | 15 +++++++-------- src/plugins/debugger/gdbengine.h | 4 ++-- 4 files changed, 16 insertions(+), 22 deletions(-) diff --git a/src/plugins/debugger/debuggeractions.cpp b/src/plugins/debugger/debuggeractions.cpp index 75e84b96205..f92ad7eed79 100644 --- a/src/plugins/debugger/debuggeractions.cpp +++ b/src/plugins/debugger/debuggeractions.cpp @@ -67,16 +67,13 @@ QVariant DebuggerAction::value() const void DebuggerAction::setValue(const QVariant &value, bool doemit) { - if (value != m_value) { - m_value = value; - if (this->isCheckable()) - this->setChecked(m_value.toBool()); - if (doemit) { - emit valueChanged(m_value); - emit boolValueChanged(m_value.toBool()); - emit stringValueChanged(m_value.toString()); - } - } + if (value == m_value) + return; + m_value = value; + if (this->isCheckable()) + this->setChecked(m_value.toBool()); + if (doemit) + emit valueChanged(m_value); } QVariant DebuggerAction::defaultValue() const diff --git a/src/plugins/debugger/debuggeractions.h b/src/plugins/debugger/debuggeractions.h index 5d7e5354d23..9423974ba1b 100644 --- a/src/plugins/debugger/debuggeractions.h +++ b/src/plugins/debugger/debuggeractions.h @@ -84,8 +84,6 @@ public: signals: void valueChanged(const QVariant &newValue); - void boolValueChanged(bool newValue); - void stringValueChanged(const QString &newValue); private: Q_SLOT void uncheckableButtonClicked(); diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp index 4ef2b4c4555..fa4e9330444 100644 --- a/src/plugins/debugger/gdbengine.cpp +++ b/src/plugins/debugger/gdbengine.cpp @@ -210,10 +210,10 @@ void GdbEngine::initializeConnections() q, SLOT(showApplicationOutput(QString)), Qt::QueuedConnection); - connect(theDebuggerAction(UseDumpers), SIGNAL(boolValueChanged(bool)), - this, SLOT(setUseDumpers(bool))); - connect(theDebuggerAction(DebugDumpers), SIGNAL(boolValueChanged(bool)), - this, SLOT(setDebugDumpers(bool))); + connect(theDebuggerAction(UseDumpers), SIGNAL(valueChanged(QVariant)), + this, SLOT(setUseDumpers(QVariant))); + connect(theDebuggerAction(DebugDumpers), SIGNAL(valueChanged(QVariant)), + this, SLOT(setDebugDumpers(QVariant))); connect(theDebuggerAction(RecheckDumpers), SIGNAL(triggered()), this, SLOT(recheckCustomDumperAvailability())); @@ -1834,9 +1834,9 @@ void GdbEngine::setTokenBarrier() m_oldestAcceptableToken = currentToken(); } -void GdbEngine::setDebugDumpers(bool on) +void GdbEngine::setDebugDumpers(const QVariant &on) { - if (on) { + if (on.toBool()) { debugMessage("SWITCHING ON DUMPER DEBUGGING"); sendCommand("set unwindonsignal off"); q->breakByFunction("qDumpObjectData440"); @@ -2849,10 +2849,9 @@ static void setWatchDataSAddress(WatchData &data, const GdbMi &mi) data.saddr = mi.data(); } -void GdbEngine::setUseDumpers(bool on) +void GdbEngine::setUseDumpers(const QVariant &on) { qDebug() << "SWITCHING ON/OFF DUMPER DEBUGGING:" << on; - Q_UNUSED(on); // FIXME: a bit too harsh, but otherwise the treeview sometimes look funny //m_expandedINames.clear(); setTokenBarrier(); diff --git a/src/plugins/debugger/gdbengine.h b/src/plugins/debugger/gdbengine.h index d35f0f08271..49b823e957b 100644 --- a/src/plugins/debugger/gdbengine.h +++ b/src/plugins/debugger/gdbengine.h @@ -130,8 +130,8 @@ private: void loadSymbols(const QString &moduleName); void loadAllSymbols(); - Q_SLOT void setDebugDumpers(bool on); - Q_SLOT void setUseDumpers(bool on); + Q_SLOT void setDebugDumpers(const QVariant &on); + Q_SLOT void setUseDumpers(const QVariant &on); // // Own stuff From f54440b4a50ca1a2e18a3651f4dfed93db6ee3d2 Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 26 Mar 2009 15:56:16 +0100 Subject: [PATCH 8/9] debugger: work on generalizing the new debugger actions --- src/plugins/debugger/debuggeractions.cpp | 34 ++++++- src/plugins/debugger/debuggeractions.h | 16 ++++ src/plugins/debugger/debuggerplugin.cpp | 107 ++++++++--------------- 3 files changed, 87 insertions(+), 70 deletions(-) diff --git a/src/plugins/debugger/debuggeractions.cpp b/src/plugins/debugger/debuggeractions.cpp index f92ad7eed79..355eac5130a 100644 --- a/src/plugins/debugger/debuggeractions.cpp +++ b/src/plugins/debugger/debuggeractions.cpp @@ -172,6 +172,8 @@ void DebuggerAction::writeSettings(QSettings *settings) void DebuggerAction::connectWidget(QWidget *widget, ApplyMode applyMode) { using namespace Core::Utils; + QTC_ASSERT(!m_widget, + qDebug() << "ALREADY CONNECTED: " << widget << m_widget << toString(); return); m_widget = widget; m_applyMode = applyMode; @@ -200,6 +202,12 @@ void DebuggerAction::connectWidget(QWidget *widget, ApplyMode applyMode) } } +void DebuggerAction::disconnectWidget() +{ + QTC_ASSERT(m_widget, + qDebug() << "ALREADY DISCONNECTED: " << m_widget << toString(); return); + m_widget = 0; +} void DebuggerAction::apply(QSettings *s) { using namespace Core::Utils; @@ -209,7 +217,6 @@ void DebuggerAction::apply(QSettings *s) setValue(lineEdit->text()); else if (PathChooser *pathChooser = qobject_cast(m_widget)) setValue(pathChooser->path()); - m_widget = 0; if (s) writeSettings(s); } @@ -270,6 +277,31 @@ void DebuggerAction::trigger(const QVariant &data) } +////////////////////////////////////////////////////////////////////////// +// +// DebuggerSettingsGroup +// +////////////////////////////////////////////////////////////////////////// + +void DebuggerSettingsGroup::insert(DebuggerAction *action, QWidget *widget) +{ + m_list.append(action); + action->connectWidget(widget); +} + +void DebuggerSettingsGroup::apply(QSettings *settings) +{ + foreach (DebuggerAction *action, m_list) + action->apply(settings); +} + +void DebuggerSettingsGroup::finish() +{ + foreach (DebuggerAction *action, m_list) + action->disconnectWidget(); +} + + ////////////////////////////////////////////////////////////////////////// // // DebuggerSettings diff --git a/src/plugins/debugger/debuggeractions.h b/src/plugins/debugger/debuggeractions.h index 9423974ba1b..172969aee23 100644 --- a/src/plugins/debugger/debuggeractions.h +++ b/src/plugins/debugger/debuggeractions.h @@ -75,6 +75,7 @@ public: Q_SLOT virtual void writeSettings(QSettings *settings); virtual void connectWidget(QWidget *widget, ApplyMode applyMode = DeferedApply); + virtual void disconnectWidget(); Q_SLOT virtual void apply(QSettings *settings); virtual QString textPattern() const; @@ -102,6 +103,21 @@ private: ApplyMode m_applyMode; }; +class DebuggerSettingsGroup +{ +public: + DebuggerSettingsGroup() {} + ~DebuggerSettingsGroup() {} + + void insert(DebuggerAction *action, QWidget *widget); + void apply(QSettings *settings); + void finish(); + +private: + QList m_list; +}; + + class DebuggerSettings : public QObject { Q_OBJECT diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index 34152a52ca5..86803a34b05 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -251,14 +251,15 @@ public: QString trCategory() const { return tr("Debugger"); } QWidget *createPage(QWidget *parent); - void apply(); - void finish() {} // automatically calls "apply" + void apply() { m_group.apply(ICore::instance()->settings()); } + void finish() { m_group.finish(); } private: friend class DebuggerPlugin; Ui::GdbOptionPage m_ui; DebuggerPlugin *m_plugin; + DebuggerSettingsGroup m_group; }; QWidget *GdbOptionPage::createPage(QWidget *parent) @@ -272,30 +273,28 @@ QWidget *GdbOptionPage::createPage(QWidget *parent) m_ui.terminalChooser->setExpectedKind(Core::Utils::PathChooser::Command); m_ui.terminalChooser->setPromptDialogTitle(tr("Choose Location of Terminal Application")); - theDebuggerAction(GdbLocation) - ->connectWidget(m_ui.gdbLocationChooser); - theDebuggerAction(GdbScriptFile) - ->connectWidget(m_ui.scriptFileChooser); - theDebuggerAction(GdbEnvironment) - ->connectWidget(m_ui.environmentEdit); - theDebuggerAction(TerminalApplication) - ->connectWidget(m_ui.terminalChooser); + m_group.insert(theDebuggerAction(GdbLocation), + m_ui.gdbLocationChooser); + m_group.insert(theDebuggerAction(GdbScriptFile), + m_ui.scriptFileChooser); + m_group.insert(theDebuggerAction(GdbEnvironment), + m_ui.environmentEdit); + m_group.insert(theDebuggerAction(TerminalApplication), + m_ui.terminalChooser); - theDebuggerAction(AllPluginBreakpoints) - ->connectWidget(m_ui.radioButtonAllPluginBreakpoints); - theDebuggerAction(SelectedPluginBreakpoints) - ->connectWidget(m_ui.radioButtonSelectedPluginBreakpoints); - theDebuggerAction(NoPluginBreakpoints) - ->connectWidget(m_ui.radioButtonNoPluginBreakpoints); - theDebuggerAction(SelectedPluginBreakpointsPattern) - ->connectWidget(m_ui.lineEditSelectedPluginBreakpointsPattern); + m_group.insert(theDebuggerAction(AllPluginBreakpoints), + m_ui.radioButtonAllPluginBreakpoints); + m_group.insert(theDebuggerAction(SelectedPluginBreakpoints), + m_ui.radioButtonSelectedPluginBreakpoints); + m_group.insert(theDebuggerAction(NoPluginBreakpoints), + m_ui.radioButtonNoPluginBreakpoints); + m_group.insert(theDebuggerAction(SelectedPluginBreakpointsPattern), + m_ui.lineEditSelectedPluginBreakpointsPattern); - theDebuggerAction(SkipKnownFrames) - ->connectWidget(m_ui.checkBoxSkipKnownFrames); - theDebuggerAction(UseToolTips) - ->connectWidget(m_ui.checkBoxUseToolTips); - theDebuggerAction(SelectedPluginBreakpointsPattern) - ->connectWidget(m_ui.lineEditSelectedPluginBreakpointsPattern); + m_group.insert(theDebuggerAction(SkipKnownFrames), + m_ui.checkBoxSkipKnownFrames); + m_group.insert(theDebuggerAction(UseToolTips), + m_ui.checkBoxUseToolTips); m_ui.lineEditSelectedPluginBreakpointsPattern-> setEnabled(theDebuggerAction(SelectedPluginBreakpoints)->value().toBool()); @@ -312,25 +311,6 @@ QWidget *GdbOptionPage::createPage(QWidget *parent) return w; } -void GdbOptionPage::apply() -{ - QSettings *s = ICore::instance()->settings(); - - theDebuggerAction(GdbLocation)->apply(s); - theDebuggerAction(GdbScriptFile)->apply(s); - theDebuggerAction(GdbEnvironment)->apply(s); - theDebuggerAction(TerminalApplication)->apply(s); - - theDebuggerAction(AllPluginBreakpoints)->apply(s); - theDebuggerAction(SelectedPluginBreakpoints)->apply(s); - theDebuggerAction(NoPluginBreakpoints)->apply(s); - theDebuggerAction(SelectedPluginBreakpointsPattern)->apply(s); - - theDebuggerAction(SkipKnownFrames)->apply(s); - theDebuggerAction(UseToolTips)->apply(s); - theDebuggerAction(SelectedPluginBreakpointsPattern)->apply(s); -} - } // namespace Internal } // namespace Debugger @@ -358,14 +338,15 @@ public: QString trCategory() const { return tr("Debugger"); } QWidget *createPage(QWidget *parent); - void apply(); - void finish() {} // automatically calls "apply" + void apply() { m_group.apply(ICore::instance()->settings()); } + void finish() { m_group.finish(); } private: friend class DebuggerPlugin; Ui::DumperOptionPage m_ui; DebuggerPlugin *m_plugin; + DebuggerSettingsGroup m_group; }; QWidget *DumperOptionPage::createPage(QWidget *parent) @@ -381,19 +362,19 @@ QWidget *DumperOptionPage::createPage(QWidget *parent) connect(m_ui.radioButtonUsePrebuiltDumpers, SIGNAL(toggled(bool)), m_ui.dumperLocationChooser, SLOT(setEnabled(bool))); - theDebuggerAction(UseQtDumpers) - ->connectWidget(m_ui.radioButtonUseQtDumpers); - theDebuggerAction(UsePrebuiltDumpers) - ->connectWidget(m_ui.radioButtonUsePrebuiltDumpers); - theDebuggerAction(BuildDumpersOnTheFly) - ->connectWidget(m_ui.radioButtonBuildDumpersOnTheFly); - theDebuggerAction(PrebuiltDumpersLocation) - ->connectWidget(m_ui.dumperLocationChooser); + m_group.insert(theDebuggerAction(UseQtDumpers), + m_ui.radioButtonUseQtDumpers); + m_group.insert(theDebuggerAction(UsePrebuiltDumpers), + m_ui.radioButtonUsePrebuiltDumpers); + m_group.insert(theDebuggerAction(BuildDumpersOnTheFly), + m_ui.radioButtonBuildDumpersOnTheFly); + m_group.insert(theDebuggerAction(PrebuiltDumpersLocation), + m_ui.dumperLocationChooser); - theDebuggerAction(UseDumpers) - ->connectWidget(m_ui.checkBoxUseDumpers); - theDebuggerAction(DebugDumpers) - ->connectWidget(m_ui.checkBoxDebugDumpers); + m_group.insert(theDebuggerAction(UseDumpers), + m_ui.checkBoxUseDumpers); + m_group.insert(theDebuggerAction(DebugDumpers), + m_ui.checkBoxDebugDumpers); m_ui.dumperLocationChooser-> setEnabled(theDebuggerAction(UsePrebuiltDumpers)->value().toBool()); @@ -411,18 +392,6 @@ QWidget *DumperOptionPage::createPage(QWidget *parent) return w; } -void DumperOptionPage::apply() -{ - QSettings *s = ICore::instance()->settings(); - - theDebuggerAction(UseDumpers)->apply(s); - theDebuggerAction(UseQtDumpers)->apply(s); - theDebuggerAction(UsePrebuiltDumpers)->apply(s); - theDebuggerAction(BuildDumpersOnTheFly)->apply(s); - theDebuggerAction(PrebuiltDumpersLocation)->apply(s); - theDebuggerAction(DebugDumpers)->apply(s); -} - } // namespace Internal } // namespace Debugger From 8ba891bb0c3f2aeaf3a4c0615dcadd9041a55e4d Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 26 Mar 2009 17:27:44 +0100 Subject: [PATCH 9/9] debugger: progress on action generalization mostly renamings --- src/plugins/debugger/debuggeractions.cpp | 175 +++++++++++------------ src/plugins/debugger/debuggeractions.h | 33 +++-- src/plugins/debugger/debuggerplugin.cpp | 8 +- 3 files changed, 112 insertions(+), 104 deletions(-) diff --git a/src/plugins/debugger/debuggeractions.cpp b/src/plugins/debugger/debuggeractions.cpp index 355eac5130a..f5ae15bef10 100644 --- a/src/plugins/debugger/debuggeractions.cpp +++ b/src/plugins/debugger/debuggeractions.cpp @@ -43,29 +43,29 @@ #include -namespace Debugger { -namespace Internal { +using namespace Debugger::Internal; +using namespace Core::Utils; ////////////////////////////////////////////////////////////////////////// // -// DebuggerAction +// SavedAction // ////////////////////////////////////////////////////////////////////////// -DebuggerAction::DebuggerAction(QObject *parent) +SavedAction::SavedAction(QObject *parent) : QAction(parent) { m_widget = 0; connect(this, SIGNAL(triggered(bool)), this, SLOT(actionTriggered(bool))); } -QVariant DebuggerAction::value() const +QVariant SavedAction::value() const { return m_value; } -void DebuggerAction::setValue(const QVariant &value, bool doemit) +void SavedAction::setValue(const QVariant &value, bool doemit) { if (value == m_value) return; @@ -76,60 +76,60 @@ void DebuggerAction::setValue(const QVariant &value, bool doemit) emit valueChanged(m_value); } -QVariant DebuggerAction::defaultValue() const +QVariant SavedAction::defaultValue() const { return m_defaultValue; } -void DebuggerAction::setDefaultValue(const QVariant &value) +void SavedAction::setDefaultValue(const QVariant &value) { m_defaultValue = value; } -QString DebuggerAction::settingsKey() const +QString SavedAction::settingsKey() const { return m_settingsKey; } -void DebuggerAction::setSettingsKey(const QString &key) +void SavedAction::setSettingsKey(const QString &key) { m_settingsKey = key; } -void DebuggerAction::setSettingsKey(const QString &group, const QString &key) +void SavedAction::setSettingsKey(const QString &group, const QString &key) { m_settingsKey = key; m_settingsGroup = group; } -QString DebuggerAction::settingsGroup() const +QString SavedAction::settingsGroup() const { return m_settingsGroup; } -void DebuggerAction::setSettingsGroup(const QString &group) +void SavedAction::setSettingsGroup(const QString &group) { m_settingsGroup = group; } -QString DebuggerAction::textPattern() const +QString SavedAction::textPattern() const { return m_textPattern; } -void DebuggerAction::setTextPattern(const QString &value) +void SavedAction::setTextPattern(const QString &value) { m_textPattern = value; } -QString DebuggerAction::toString() const +QString SavedAction::toString() const { return "value: " + m_value.toString() + " defaultvalue: " + m_defaultValue.toString() + " settingskey: " + m_settingsGroup + '/' + m_settingsKey; } -QAction *DebuggerAction::updatedAction(const QString &text0) +QAction *SavedAction::updatedAction(const QString &text0) { QString text = text0; bool enabled = true; @@ -149,7 +149,7 @@ QAction *DebuggerAction::updatedAction(const QString &text0) return this; } -void DebuggerAction::readSettings(QSettings *settings) +void SavedAction::readSettings(QSettings *settings) { if (m_settingsGroup.isEmpty() || m_settingsKey.isEmpty()) return; @@ -159,7 +159,7 @@ void DebuggerAction::readSettings(QSettings *settings) settings->endGroup(); } -void DebuggerAction::writeSettings(QSettings *settings) +void SavedAction::writeSettings(QSettings *settings) { if (m_settingsGroup.isEmpty() || m_settingsKey.isEmpty()) return; @@ -169,9 +169,8 @@ void DebuggerAction::writeSettings(QSettings *settings) settings->endGroup(); } -void DebuggerAction::connectWidget(QWidget *widget, ApplyMode applyMode) +void SavedAction::connectWidget(QWidget *widget, ApplyMode applyMode) { - using namespace Core::Utils; QTC_ASSERT(!m_widget, qDebug() << "ALREADY CONNECTED: " << widget << m_widget << toString(); return); m_widget = widget; @@ -198,19 +197,18 @@ void DebuggerAction::connectWidget(QWidget *widget, ApplyMode applyMode) connect(pathChooser, SIGNAL(browsingFinished()), this, SLOT(pathChooserEditingFinished())); } else { - qDebug() << "CANNOT CONNECT WIDGET " << widget; + qDebug() << "Cannot connect widget " << widget << toString(); } } -void DebuggerAction::disconnectWidget() +void SavedAction::disconnectWidget() { QTC_ASSERT(m_widget, - qDebug() << "ALREADY DISCONNECTED: " << m_widget << toString(); return); + qDebug() << "Widget already disconnected: " << m_widget << toString(); return); m_widget = 0; } -void DebuggerAction::apply(QSettings *s) +void SavedAction::apply(QSettings *s) { - using namespace Core::Utils; if (QAbstractButton *button = qobject_cast(m_widget)) setValue(button->isChecked()); else if (QLineEdit *lineEdit = qobject_cast(m_widget)) @@ -221,7 +219,7 @@ void DebuggerAction::apply(QSettings *s) writeSettings(s); } -void DebuggerAction::uncheckableButtonClicked() +void SavedAction::uncheckableButtonClicked() { QAbstractButton *button = qobject_cast(sender()); QTC_ASSERT(button, return); @@ -229,7 +227,7 @@ void DebuggerAction::uncheckableButtonClicked() QAction::trigger(); } -void DebuggerAction::checkableButtonClicked(bool) +void SavedAction::checkableButtonClicked(bool) { QAbstractButton *button = qobject_cast(sender()); QTC_ASSERT(button, return); @@ -238,39 +236,35 @@ void DebuggerAction::checkableButtonClicked(bool) setValue(button->isChecked()); } -void DebuggerAction::lineEditEditingFinished() +void SavedAction::lineEditEditingFinished() { QLineEdit *lineEdit = qobject_cast(sender()); QTC_ASSERT(lineEdit, return); - //qDebug() << "LINEEDIT: " << sender() << lineEdit->text(); if (m_applyMode == ImmediateApply) setValue(lineEdit->text()); } -void DebuggerAction::pathChooserEditingFinished() +void SavedAction::pathChooserEditingFinished() { - using namespace Core::Utils; PathChooser *pathChooser = qobject_cast(sender()); QTC_ASSERT(pathChooser, return); - //qDebug() << "PATHCHOOSER: " << sender() << pathChooser->path(); if (m_applyMode == ImmediateApply) setValue(pathChooser->path()); } -void DebuggerAction::actionTriggered(bool) +void SavedAction::actionTriggered(bool) { - //qDebug() << "TRIGGERING" << this << actionGroup(); if (isCheckable()) setValue(isChecked()); if (actionGroup() && actionGroup()->isExclusive()) { // FIXME: should be taken care of more directly foreach (QAction *act, actionGroup()->actions()) - if (DebuggerAction *dact = qobject_cast(act)) + if (SavedAction *dact = qobject_cast(act)) dact->setValue(bool(act == this)); } } -void DebuggerAction::trigger(const QVariant &data) +void SavedAction::trigger(const QVariant &data) { setData(data); QAction::trigger(); @@ -279,25 +273,25 @@ void DebuggerAction::trigger(const QVariant &data) ////////////////////////////////////////////////////////////////////////// // -// DebuggerSettingsGroup +// SavedActionSet // ////////////////////////////////////////////////////////////////////////// -void DebuggerSettingsGroup::insert(DebuggerAction *action, QWidget *widget) +void SavedActionSet::insert(SavedAction *action, QWidget *widget) { m_list.append(action); action->connectWidget(widget); } -void DebuggerSettingsGroup::apply(QSettings *settings) +void SavedActionSet::apply(QSettings *settings) { - foreach (DebuggerAction *action, m_list) + foreach (SavedAction *action, m_list) action->apply(settings); } -void DebuggerSettingsGroup::finish() +void SavedActionSet::finish() { - foreach (DebuggerAction *action, m_list) + foreach (SavedAction *action, m_list) action->disconnectWidget(); } @@ -308,6 +302,9 @@ void DebuggerSettingsGroup::finish() // ////////////////////////////////////////////////////////////////////////// +namespace Debugger { +namespace Internal { + DebuggerSettings::DebuggerSettings(QObject *parent) : QObject(parent) {} @@ -317,24 +314,24 @@ DebuggerSettings::~DebuggerSettings() qDeleteAll(m_items); } -void DebuggerSettings::insertItem(int code, DebuggerAction *item) +void DebuggerSettings::insertItem(int code, SavedAction *item) { m_items[code] = item; } void DebuggerSettings::readSettings(QSettings *settings) { - foreach (DebuggerAction *item, m_items) + foreach (SavedAction *item, m_items) item->readSettings(settings); } void DebuggerSettings::writeSettings(QSettings *settings) { - foreach (DebuggerAction *item, m_items) + foreach (SavedAction *item, m_items) item->writeSettings(settings); } -DebuggerAction *DebuggerSettings::item(int code) +SavedAction *DebuggerSettings::item(int code) { QTC_ASSERT(m_items.value(code, 0), return 0); return m_items.value(code, 0); @@ -345,7 +342,7 @@ QString DebuggerSettings::dump() QString out; QTextStream ts(&out); ts << "Debugger settings: "; - foreach (DebuggerAction *item, m_items) + foreach (SavedAction *item, m_items) ts << "\n" << item->value().toString(); return out; } @@ -367,16 +364,16 @@ DebuggerSettings *theDebuggerSettings() instance = new DebuggerSettings; - DebuggerAction *item = 0; + SavedAction *item = 0; // // View // - item = new DebuggerAction(instance); + item = new SavedAction(instance); instance->insertItem(AdjustColumnWidths, item); item->setText(QObject::tr("Adjust column widths to contents")); - item = new DebuggerAction(instance); + item = new SavedAction(instance); instance->insertItem(AlwaysAdjustColumnWidths, item); item->setText(QObject::tr("Always adjust column widths to contents")); item->setCheckable(true); @@ -384,50 +381,50 @@ DebuggerSettings *theDebuggerSettings() // // Locals & Watchers // - item = new DebuggerAction(instance); + item = new SavedAction(instance); instance->insertItem(WatchExpression, item); item->setTextPattern(QObject::tr("Watch expression \"%1\"")); - item = new DebuggerAction(instance); + item = new SavedAction(instance); instance->insertItem(RemoveWatchExpression, item); item->setTextPattern(QObject::tr("Remove watch expression \"%1\"")); - item = new DebuggerAction(instance); + item = new SavedAction(instance); instance->insertItem(WatchExpressionInWindow, item); item->setTextPattern(QObject::tr("Watch expression \"%1\" in separate window")); //item->setCheckable(true); - item = new DebuggerAction(instance); + item = new SavedAction(instance); instance->insertItem(AssignValue, item); - item = new DebuggerAction(instance); + item = new SavedAction(instance); instance->insertItem(ExpandItem, item); item->setText(QObject::tr("Expand item")); - item = new DebuggerAction(instance); + item = new SavedAction(instance); instance->insertItem(CollapseItem, item); item->setText(QObject::tr("Collapse item")); // // Dumpers // - item = new DebuggerAction(instance); + item = new SavedAction(instance); instance->insertItem(SettingsDialog, item); item->setText(QObject::tr("Debugger properties...")); - item = new DebuggerAction(instance); + item = new SavedAction(instance); instance->insertItem(DebugDumpers, item); item->setText(QObject::tr("Debug custom dumpers")); item->setCheckable(true); - item = new DebuggerAction(instance); + item = new SavedAction(instance); item->setText(QObject::tr("Recheck custom dumper availability")); instance->insertItem(RecheckDumpers, item); // // Breakpoints // - item = new DebuggerAction(instance); + item = new SavedAction(instance); item->setText(QObject::tr("Syncronize breakpoints")); instance->insertItem(SynchronizeBreakpoints, item); @@ -438,7 +435,7 @@ DebuggerSettings *theDebuggerSettings() QActionGroup *registerFormatGroup = new QActionGroup(instance); registerFormatGroup->setExclusive(true); - item = new DebuggerAction(instance); + item = new SavedAction(instance); item->setText(QObject::tr("Hexadecimal")); item->setCheckable(true); item->setSettingsKey("DebugMode", "FormatHexadecimal"); @@ -446,35 +443,35 @@ DebuggerSettings *theDebuggerSettings() instance->insertItem(FormatHexadecimal, item); registerFormatGroup->addAction(item); - item = new DebuggerAction(instance); + item = new SavedAction(instance); item->setText(QObject::tr("Decimal")); item->setCheckable(true); item->setSettingsKey("DebugMode", "FormatDecimal"); instance->insertItem(FormatDecimal, item); registerFormatGroup->addAction(item); - item = new DebuggerAction(instance); + item = new SavedAction(instance); item->setText(QObject::tr("Octal")); item->setCheckable(true); item->setSettingsKey("DebugMode", "FormatOctal"); instance->insertItem(FormatOctal, item); registerFormatGroup->addAction(item); - item = new DebuggerAction(instance); + item = new SavedAction(instance); item->setText(QObject::tr("Binary")); item->setCheckable(true); item->setSettingsKey("DebugMode", "FormatBinary"); instance->insertItem(FormatBinary, item); registerFormatGroup->addAction(item); - item = new DebuggerAction(instance); + item = new SavedAction(instance); item->setText(QObject::tr("Raw")); item->setCheckable(true); item->setSettingsKey("DebugMode", "FormatRaw"); instance->insertItem(FormatRaw, item); registerFormatGroup->addAction(item); - item = new DebuggerAction(instance); + item = new SavedAction(instance); item->setText(QObject::tr("Natural")); item->setCheckable(true); item->setSettingsKey("DebugMode", "FormatNatural"); @@ -485,17 +482,17 @@ DebuggerSettings *theDebuggerSettings() // Misc // - item = new DebuggerAction(instance); + item = new SavedAction(instance); instance->insertItem(SkipKnownFrames, item); item->setText(QObject::tr("Skip known frames")); item->setCheckable(true); - item = new DebuggerAction(instance); + item = new SavedAction(instance); instance->insertItem(UseToolTips, item); item->setText(QObject::tr("Use tooltips when debugging")); item->setCheckable(true); - item = new DebuggerAction(instance); + item = new SavedAction(instance); instance->insertItem(ListSourceFiles, item); item->setText(QObject::tr("List source files")); item->setCheckable(true); @@ -504,91 +501,91 @@ DebuggerSettings *theDebuggerSettings() // // Settings // - item = new DebuggerAction(instance); + item = new SavedAction(instance); instance->insertItem(GdbLocation, item); item->setSettingsKey("DebugMode", "Location"); - item = new DebuggerAction(instance); + item = new SavedAction(instance); instance->insertItem(GdbEnvironment, item); item->setSettingsKey("DebugMode", "Environment"); - item = new DebuggerAction(instance); + item = new SavedAction(instance); instance->insertItem(GdbScriptFile, item); item->setSettingsKey("DebugMode", "ScriptFile"); - item = new DebuggerAction(instance); + item = new SavedAction(instance); item->setSettingsKey("DebugMode", "AutoQuit"); item->setText(QObject::tr("Automatically quit debugger")); item->setCheckable(true); instance->insertItem(AutoQuit, item); - item = new DebuggerAction(instance); + item = new SavedAction(instance); instance->insertItem(UseToolTips, item); item->setSettingsKey("DebugMode", "UseToolTips"); - item = new DebuggerAction(instance); + item = new SavedAction(instance); instance->insertItem(UseDumpers, item); item->setSettingsKey("DebugMode", "UseCustomDumpers"); item->setText(QObject::tr("Use custom dumpers")); item->setCheckable(true); - item = new DebuggerAction(instance); + item = new SavedAction(instance); instance->insertItem(BuildDumpersOnTheFly, item); item->setDefaultValue(true); item->setSettingsKey("DebugMode", "BuildDumpersOnTheFly"); item->setCheckable(true); - item = new DebuggerAction(instance); + item = new SavedAction(instance); instance->insertItem(UseQtDumpers, item); item->setSettingsKey("DebugMode", "UseQtDumpers"); item->setCheckable(true); - item = new DebuggerAction(instance); + item = new SavedAction(instance); instance->insertItem(UsePrebuiltDumpers, item); item->setSettingsKey("DebugMode", "UsePrebuiltDumpers"); item->setCheckable(true); - item = new DebuggerAction(instance); + item = new SavedAction(instance); instance->insertItem(PrebuiltDumpersLocation, item); item->setSettingsKey("DebugMode", "PrebuiltDumpersLocation"); - item = new DebuggerAction(instance); + item = new SavedAction(instance); instance->insertItem(TerminalApplication, item); item->setDefaultValue("xterm"); item->setSettingsKey("DebugMode", "Terminal"); - item = new DebuggerAction(instance); + item = new SavedAction(instance); instance->insertItem(ListSourceFiles, item); item->setSettingsKey("DebugMode", "ListSourceFiles"); - item = new DebuggerAction(instance); + item = new SavedAction(instance); instance->insertItem(SkipKnownFrames, item); item->setSettingsKey("DebugMode", "SkipKnownFrames"); - item = new DebuggerAction(instance); + item = new SavedAction(instance); instance->insertItem(DebugDumpers, item); item->setSettingsKey("DebugMode", "DebugDumpers"); - item = new DebuggerAction(instance); + item = new SavedAction(instance); instance->insertItem(AllPluginBreakpoints, item); item->setSettingsKey("DebugMode", "AllPluginBreakpoints"); - item = new DebuggerAction(instance); + item = new SavedAction(instance); instance->insertItem(SelectedPluginBreakpoints, item); item->setSettingsKey("DebugMode", "SelectedPluginBreakpoints"); - item = new DebuggerAction(instance); + item = new SavedAction(instance); instance->insertItem(NoPluginBreakpoints, item); item->setSettingsKey("DebugMode", "NoPluginBreakpoints"); - item = new DebuggerAction(instance); + item = new SavedAction(instance); instance->insertItem(SelectedPluginBreakpointsPattern, item); item->setSettingsKey("DebugMode", "SelectedPluginBreakpointsPattern"); return instance; } -DebuggerAction *theDebuggerAction(int code) +SavedAction *theDebuggerAction(int code) { return theDebuggerSettings()->item(code); } diff --git a/src/plugins/debugger/debuggeractions.h b/src/plugins/debugger/debuggeractions.h index 172969aee23..e738ac9eedb 100644 --- a/src/plugins/debugger/debuggeractions.h +++ b/src/plugins/debugger/debuggeractions.h @@ -42,17 +42,17 @@ class QSettings; QT_END_NAMESPACE -namespace Debugger { -namespace Internal { +namespace Core { +namespace Utils { enum ApplyMode { ImmediateApply, DeferedApply }; -class DebuggerAction : public QAction +class SavedAction : public QAction { Q_OBJECT public: - DebuggerAction(QObject *parent = 0); + SavedAction(QObject *parent = 0); virtual QVariant value() const; Q_SLOT virtual void setValue(const QVariant &value, bool doemit = true); @@ -103,20 +103,27 @@ private: ApplyMode m_applyMode; }; -class DebuggerSettingsGroup +class SavedActionSet { public: - DebuggerSettingsGroup() {} - ~DebuggerSettingsGroup() {} + SavedActionSet() {} + ~SavedActionSet() {} - void insert(DebuggerAction *action, QWidget *widget); + void insert(SavedAction *action, QWidget *widget); void apply(QSettings *settings); void finish(); + void clear() { m_list.clear(); } private: - QList m_list; + QList m_list; }; +} // namespace Utils +} // namespace Core + + +namespace Debugger { +namespace Internal { class DebuggerSettings : public QObject { @@ -126,8 +133,8 @@ public: DebuggerSettings(QObject *parent = 0); ~DebuggerSettings(); - void insertItem(int code, DebuggerAction *item); - DebuggerAction *item(int code); + void insertItem(int code, Core::Utils::SavedAction *item); + Core::Utils::SavedAction *item(int code); QString dump(); @@ -136,7 +143,7 @@ public slots: void writeSettings(QSettings *settings); private: - QHash m_items; + QHash m_items; }; @@ -199,7 +206,7 @@ enum DebuggerActionCode // singleton access DebuggerSettings *theDebuggerSettings(); -DebuggerAction *theDebuggerAction(int code); +Core::Utils::SavedAction *theDebuggerAction(int code); // convienience bool theDebuggerBoolSetting(int code); diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index 86803a34b05..5fabcee1821 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -259,7 +259,7 @@ private: Ui::GdbOptionPage m_ui; DebuggerPlugin *m_plugin; - DebuggerSettingsGroup m_group; + Core::Utils::SavedActionSet m_group; }; QWidget *GdbOptionPage::createPage(QWidget *parent) @@ -273,6 +273,7 @@ QWidget *GdbOptionPage::createPage(QWidget *parent) m_ui.terminalChooser->setExpectedKind(Core::Utils::PathChooser::Command); m_ui.terminalChooser->setPromptDialogTitle(tr("Choose Location of Terminal Application")); + m_group.clear(); m_group.insert(theDebuggerAction(GdbLocation), m_ui.gdbLocationChooser); m_group.insert(theDebuggerAction(GdbScriptFile), @@ -291,6 +292,8 @@ QWidget *GdbOptionPage::createPage(QWidget *parent) m_group.insert(theDebuggerAction(SelectedPluginBreakpointsPattern), m_ui.lineEditSelectedPluginBreakpointsPattern); + m_group.insert(theDebuggerAction(ListSourceFiles), + m_ui.checkBoxListSourceFiles); m_group.insert(theDebuggerAction(SkipKnownFrames), m_ui.checkBoxSkipKnownFrames); m_group.insert(theDebuggerAction(UseToolTips), @@ -346,7 +349,7 @@ private: Ui::DumperOptionPage m_ui; DebuggerPlugin *m_plugin; - DebuggerSettingsGroup m_group; + Core::Utils::SavedActionSet m_group; }; QWidget *DumperOptionPage::createPage(QWidget *parent) @@ -362,6 +365,7 @@ QWidget *DumperOptionPage::createPage(QWidget *parent) connect(m_ui.radioButtonUsePrebuiltDumpers, SIGNAL(toggled(bool)), m_ui.dumperLocationChooser, SLOT(setEnabled(bool))); + m_group.clear(); m_group.insert(theDebuggerAction(UseQtDumpers), m_ui.radioButtonUseQtDumpers); m_group.insert(theDebuggerAction(UsePrebuiltDumpers),