diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp
index 45df839ff0f7552e5dea0828dfe168de12e904a7..b048257b8a1e523e5af90b86651e27c83fb26951 100644
--- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp
@@ -260,6 +260,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/coreplugin/navigationwidget.cpp b/src/plugins/coreplugin/navigationwidget.cpp
index 2e360155908dc726ff2aa74ec7791a9d3b8c71a4..f1940975467196da52c67dd1190784b764f9e419 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; i<views.count()-1; ++i) {
-            insertSubItem(0);
-        }
-        for (int i=0; i<views.count(); ++i) {
-            const QString &view = views.at(i);
-            NavigationSubWidget *nsw = m_subWidgets.at(i);
-            nsw->setFactory(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; i<views.count()-1; ++i) {
+        insertSubItem(0);
+    }
+    for (int i=0; i<views.count(); ++i) {
+        const QString &view = views.at(i);
+        NavigationSubWidget *nsw = m_subWidgets.at(i);
+        nsw->setFactory(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<int> 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();
diff --git a/src/plugins/cpptools/cppcodecompletion.cpp b/src/plugins/cpptools/cppcodecompletion.cpp
index 35b751104d39882b6c8d21426f3f2734b0eb1da0..2bdaa6445f632d134fcb720235b83d1f80c18d61 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,8 +1221,7 @@ 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->hasArguments()) {
                         extraChars += QLatin1Char(')');
 
                         // If the function doesn't return anything, automatically place the semicolon,
diff --git a/src/plugins/debugger/cdb/cdb.pri b/src/plugins/debugger/cdb/cdb.pri
index 27186577c3041746f0c48c5952df1c72d3daba6b..8ba7d3a68650872f537992b0c9fd5fd50b18a6c2 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 73d3953ffb3a51dc3a83ea0fa91bbe11917923a0..7d054e68dd430d24dd42de3d94ad47ad38d3c04b 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("<unknown>");
-    }
-    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);
-            break;
-        }
-
-        hr = m_pDebugSymbols->SetScope(0, cdbStackTrace.frames + frameIndex, NULL, 0);
-        if (FAILED(hr)) {
-            *errorMessage = msgComFailed("SetScope", hr);
-            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);
+        if (!m_currentStackTrace) {
+            *errorMessage = QLatin1String(msgNoStackTraceC);
             break;
         }
 
-        symParams = new DEBUG_SYMBOL_PARAMETERS[symbolCount];
-        hr = pDbgSymGroup->GetSymbolParameters(0, symbolCount, symParams);
-        if (FAILED(hr)) {
-            *errorMessage = msgComFailed("GetSymbolParameters", hr);
+        CdbSymbolGroupContext *sgc = m_currentStackTrace->symbolGroupContextAt(frameIndex, errorMessage);
+        if (!sgc) {
             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<WatchData> 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<StackFrame> *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<StackFrame> stackFrames;
-    int current;
+    // Create a new context
+    cleanStackTrace();
     QString errorMessage;
-    if (getStackTrace(&stackFrames, &current, &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<StackFrame> 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 e6235569a074b8320cdd3d73363559ed405db4f6..e1991f707deedc75d73b052014eb6653372aaf13 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<StackFrame> *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 0000000000000000000000000000000000000000..d569c6a9baefb6a6b93500c6d06a85b31611d293
--- /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<CdbSymbolGroupContext*>(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 0000000000000000000000000000000000000000..bb8286859ef2ed3ade602808f5729a1be37a3511
--- /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 <windows.h>
+#include <inc/dbgeng.h>
+
+#include <QtCore/QString>
+#include <QtCore/QVector>
+
+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<StackFrame> 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 <CdbSymbolGroupContext*> m_symbolContexts;
+    QList<StackFrame> 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 0000000000000000000000000000000000000000..aa52ef55e1a304a4d95b832cbefcaf8b24de7702
--- /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 &params = 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 0000000000000000000000000000000000000000..e5c4ea7c9c731fba630ba1dca161ecdfa0caf2ae
--- /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 <windows.h>
+#include <inc/dbgeng.h>
+
+#include <QtCore/QString>
+#include <QtCore/QVector>
+#include <QtCore/QList>
+#include <QtCore/QStringList>
+#include <QtCore/QPair>
+#include <QtCore/QMap>
+
+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<unsigned long, unsigned long> 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 <class OutputIterator>
+            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<DEBUG_SYMBOL_PARAMETERS> m_symbolParameters;
+
+    typedef QMap<QString, Range> ChildRangeMap;
+
+    ChildRangeMap m_childRanges;
+};
+
+template <class OutputIterator>
+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/debuggeractions.cpp b/src/plugins/debugger/debuggeractions.cpp
index 75e84b962054a6a97eacd7b670272b0082244c25..f5ae15bef109d883c0b86aa3558ad4dcf6ed8bff 100644
--- a/src/plugins/debugger/debuggeractions.cpp
+++ b/src/plugins/debugger/debuggeractions.cpp
@@ -43,96 +43,93 @@
 #include <QtGui/QLineEdit>
 
 
-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) {
-        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
+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;
@@ -152,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;
@@ -162,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;
@@ -172,9 +169,10 @@ 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;
     m_applyMode = applyMode;
     
@@ -199,25 +197,29 @@ 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::apply(QSettings *s)
+void SavedAction::disconnectWidget()
+{
+    QTC_ASSERT(m_widget,
+        qDebug() << "Widget already disconnected: " << m_widget << toString(); return);
+    m_widget = 0;
+}
+void SavedAction::apply(QSettings *s)
 {
-    using namespace Core::Utils;
     if (QAbstractButton *button = qobject_cast<QAbstractButton *>(m_widget))
         setValue(button->isChecked());
     else if (QLineEdit *lineEdit = qobject_cast<QLineEdit *>(m_widget))
         setValue(lineEdit->text());
     else if (PathChooser *pathChooser = qobject_cast<PathChooser *>(m_widget))
         setValue(pathChooser->path());
-    m_widget = 0;
     if (s)
        writeSettings(s);
 }
 
-void DebuggerAction::uncheckableButtonClicked()
+void SavedAction::uncheckableButtonClicked()
 {
     QAbstractButton *button = qobject_cast<QAbstractButton *>(sender());
     QTC_ASSERT(button, return);
@@ -225,7 +227,7 @@ void DebuggerAction::uncheckableButtonClicked()
     QAction::trigger();
 }
 
-void DebuggerAction::checkableButtonClicked(bool)
+void SavedAction::checkableButtonClicked(bool)
 {
     QAbstractButton *button = qobject_cast<QAbstractButton *>(sender());
     QTC_ASSERT(button, return);
@@ -234,51 +236,75 @@ void DebuggerAction::checkableButtonClicked(bool)
         setValue(button->isChecked());
 }
 
-void DebuggerAction::lineEditEditingFinished()
+void SavedAction::lineEditEditingFinished()
 {
     QLineEdit *lineEdit = qobject_cast<QLineEdit *>(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<PathChooser *>(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<DebuggerAction *>(act))
+            if (SavedAction *dact = qobject_cast<SavedAction *>(act))
                 dact->setValue(bool(act == this));
     }
 }
 
-void DebuggerAction::trigger(const QVariant &data)
+void SavedAction::trigger(const QVariant &data)
 {
     setData(data);
     QAction::trigger();
 }
 
 
+//////////////////////////////////////////////////////////////////////////
+//
+// SavedActionSet
+//
+//////////////////////////////////////////////////////////////////////////
+
+void SavedActionSet::insert(SavedAction *action, QWidget *widget)
+{
+    m_list.append(action);
+    action->connectWidget(widget);
+}
+
+void SavedActionSet::apply(QSettings *settings)
+{
+    foreach (SavedAction *action, m_list)
+        action->apply(settings);
+}
+
+void SavedActionSet::finish()
+{
+    foreach (SavedAction *action, m_list)
+        action->disconnectWidget();
+}
+
+
 //////////////////////////////////////////////////////////////////////////
 //
 // DebuggerSettings
 //
 //////////////////////////////////////////////////////////////////////////
 
+namespace Debugger {
+namespace Internal {
+
 DebuggerSettings::DebuggerSettings(QObject *parent)
     : QObject(parent)
 {}
@@ -288,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);
@@ -316,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;
 }
@@ -338,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);
@@ -355,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);
 
@@ -409,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");
@@ -417,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");
@@ -456,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);
@@ -475,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 5d7e5354d239c332baab76fb0a0d002f0b2fc31b..e738ac9eedba7e6f8f6bbdfa3e4d7d8ff3d0b85a 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);
@@ -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;
@@ -84,8 +85,6 @@ public:
 
 signals:
     void valueChanged(const QVariant &newValue);
-    void boolValueChanged(bool newValue);
-    void stringValueChanged(const QString &newValue);
 
 private:
     Q_SLOT void uncheckableButtonClicked();
@@ -104,6 +103,28 @@ private:
     ApplyMode m_applyMode;
 };
 
+class SavedActionSet
+{
+public:
+    SavedActionSet() {}
+    ~SavedActionSet() {}
+
+    void insert(SavedAction *action, QWidget *widget);
+    void apply(QSettings *settings);
+    void finish();
+    void clear() { m_list.clear(); }
+
+private:
+    QList<SavedAction *> m_list;
+};
+
+} // namespace Utils
+} // namespace Core
+
+
+namespace Debugger {
+namespace Internal {
+
 class DebuggerSettings : public QObject
 {
     Q_OBJECT
@@ -112,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();
 
@@ -122,7 +143,7 @@ public slots:
     void writeSettings(QSettings *settings);
 
 private:
-    QHash<int, DebuggerAction *> m_items; 
+    QHash<int, Core::Utils::SavedAction *> m_items; 
 };
 
 
@@ -185,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 34152a52ca5bff419fb17cb495e78b94f44627f6..5fabcee182187d4978974073675cf05c16016e3e 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;
+    Core::Utils::SavedActionSet m_group;
 };
 
 QWidget *GdbOptionPage::createPage(QWidget *parent)
@@ -272,30 +273,31 @@ 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);
-
-    theDebuggerAction(AllPluginBreakpoints)
-        ->connectWidget(m_ui.radioButtonAllPluginBreakpoints);
-    theDebuggerAction(SelectedPluginBreakpoints)
-        ->connectWidget(m_ui.radioButtonSelectedPluginBreakpoints);
-    theDebuggerAction(NoPluginBreakpoints)
-        ->connectWidget(m_ui.radioButtonNoPluginBreakpoints);
-    theDebuggerAction(SelectedPluginBreakpointsPattern)
-        ->connectWidget(m_ui.lineEditSelectedPluginBreakpointsPattern);
-
-    theDebuggerAction(SkipKnownFrames)
-        ->connectWidget(m_ui.checkBoxSkipKnownFrames);
-    theDebuggerAction(UseToolTips)
-        ->connectWidget(m_ui.checkBoxUseToolTips);
-    theDebuggerAction(SelectedPluginBreakpointsPattern)
-        ->connectWidget(m_ui.lineEditSelectedPluginBreakpointsPattern);
+    m_group.clear();
+    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);
+
+    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);
+
+    m_group.insert(theDebuggerAction(ListSourceFiles), 
+        m_ui.checkBoxListSourceFiles);
+    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 +314,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 +341,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;
+    Core::Utils::SavedActionSet m_group;
 };
 
 QWidget *DumperOptionPage::createPage(QWidget *parent)
@@ -381,19 +365,20 @@ 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);
-
-    theDebuggerAction(UseDumpers)
-        ->connectWidget(m_ui.checkBoxUseDumpers);
-    theDebuggerAction(DebugDumpers)
-        ->connectWidget(m_ui.checkBoxDebugDumpers);
+    m_group.clear();
+    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);
+
+    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 +396,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
 
diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp
index daf2e6e0c0b355dc4a0af37bf785da39efe2dcd2..fa4e933044416917b1704258648fa9cf139e78a6 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");
@@ -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;
@@ -2853,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 d35f0f0827174a8b059940436ebd175f9daa0dbf..49b823e957bed4e23888531822e99ed9d513c50f 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
diff --git a/src/plugins/debugger/stackhandler.cpp b/src/plugins/debugger/stackhandler.cpp
index fcc28bdd19df2de7ae87bee3a74e4cf7c8b04936..a131bc004286343ab4c0201994f929ac09d87f07 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 d427c93e92139cd2743d82b1aa90d03c3f07c836..ae073e3d1369f74a42ba6eeb9b5df0580c545205 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
diff --git a/src/plugins/find/findplugin.cpp b/src/plugins/find/findplugin.cpp
index ee62bea84bf99848b62c834153d2ba2911aa8396..2a5d10470708990a5ed420e1f15ac6ca211a3ce6 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<QAction*>(sender());
     QTC_ASSERT(action, return);
     IFindFilter *filter = action->data().value<IFindFilter *>();
-    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 53bd805aaa2d5a8f05a2cf2054d48a5e727bbbb7..a4c2ce283823902d6e22495d5ebbdd9a975f1661 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 2c2295740d01bfd0be4a0a445b0d4a938ad21edd..97f66d5d27565b3d6af0cbabec5b8df8f8ab2a11 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 40394dfb857c37c5288974819bd32a771a376f59..a430c9989767a57c9437f6bb446b79e670f90d51 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 af0a962ec34c54ddd3daa5b8fa51920ae133f6cc..c6448c2f801ae33d924d958e48d9d0d92424dfc3 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 123efdbb82409039088a320ce20903ee628cb1f4..4fcfc68642e5f5f27717c98aa242730f86143430 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()
diff --git a/src/plugins/qt4projectmanager/qt4runconfiguration.cpp b/src/plugins/qt4projectmanager/qt4runconfiguration.cpp
index 64cb11b448c1d3ff0cb54ece8ed110d056587145..0522fab8d35f9b33e9ea9d5d83ceac92ef1501e6 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);
diff --git a/src/plugins/texteditor/completionsupport.cpp b/src/plugins/texteditor/completionsupport.cpp
index 53de9ee66e1dee79c833953bb2413b6d6a9fd3e6..2e456193ad52f2af57952a6667f6e3a63f885ea7 100644
--- a/src/plugins/texteditor/completionsupport.cpp
+++ b/src/plugins/texteditor/completionsupport.cpp
@@ -186,6 +186,8 @@ QList<CompletionItem> 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 c8c035802e4e0c83f305b07c6f05421427cd39f7..49d70f182883b2302cd16c1203b2216b3a39d749 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;
 };
 
diff --git a/src/shared/cplusplus/Symbols.cpp b/src/shared/cplusplus/Symbols.cpp
index 5185aa82659a8fd1f5e6897f21abfeab6cc4a5d0..10b82664c345aeb94648a55049d010e2246fcd72 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 8efc0fbdbed0c104a843564817f77520b8131223..4052b746da29517391db21158a6db0cef77a60bc 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);