From ad46f1286fd3242089f8a5a8c20794e433a05645 Mon Sep 17 00:00:00 2001
From: hjk <qtc-committer@nokia.com>
Date: Mon, 13 Jul 2009 09:11:07 +0200
Subject: [PATCH] Revert "Enabled the use of Debugger-specific watch/locals
 models."

This reverts commit abf5e3ddc39b8f4971f61fb9f8dccdb1d4635bf5.
---
 .../debugger/abstractsyncwatchmodel.cpp       | 107 ---
 src/plugins/debugger/asyncwatchmodel.cpp      | 232 ------
 src/plugins/debugger/asyncwatchmodel.h        | 102 ---
 src/plugins/debugger/cdb/cdb.pri              |   8 +-
 src/plugins/debugger/cdb/cdbdebugengine.cpp   | 178 ++---
 src/plugins/debugger/cdb/cdbdebugengine.h     |  16 +-
 src/plugins/debugger/cdb/cdbdebugengine_p.h   |  13 +-
 .../cdbstackframecontext.h}                   |  54 +-
 .../debugger/cdb/cdbstacktracecontext.cpp     |  55 +-
 .../debugger/cdb/cdbstacktracecontext.h       |  17 +-
 .../debugger/cdb/cdbsymbolgroupcontext.cpp    |   1 +
 .../debugger/cdb/cdbsymbolgroupcontext.h      |  25 +
 .../debugger/cdb/cdbsymbolgroupcontext_tpl.h  |  99 +++
 src/plugins/debugger/cdb/cdbwatchmodels.cpp   | 477 -------------
 src/plugins/debugger/cdb/cdbwatchmodels.h     |  96 ---
 src/plugins/debugger/debugger.pro             |   4 -
 src/plugins/debugger/debuggermanager.cpp      |  58 +-
 src/plugins/debugger/debuggermanager.h        |   8 +-
 src/plugins/debugger/gdb/gdbengine.cpp        |  20 +-
 src/plugins/debugger/gdb/gdbengine.h          |   6 +-
 src/plugins/debugger/idebuggerengine.h        |   7 +-
 src/plugins/debugger/script/scriptengine.cpp  |  21 +-
 src/plugins/debugger/script/scriptengine.h    |   9 +-
 src/plugins/debugger/tcf/tcfengine.cpp        |  10 +-
 src/plugins/debugger/tcf/tcfengine.h          |   9 +-
 src/plugins/debugger/watchhandler.cpp         | 661 +++++++++---------
 src/plugins/debugger/watchhandler.h           | 151 ++--
 src/plugins/debugger/watchutils.cpp           |  23 +-
 src/plugins/debugger/watchwindow.cpp          |   8 +-
 29 files changed, 687 insertions(+), 1788 deletions(-)
 delete mode 100644 src/plugins/debugger/abstractsyncwatchmodel.cpp
 delete mode 100644 src/plugins/debugger/asyncwatchmodel.cpp
 delete mode 100644 src/plugins/debugger/asyncwatchmodel.h
 rename src/plugins/debugger/{abstractsyncwatchmodel.h => cdb/cdbstackframecontext.h} (52%)
 delete mode 100644 src/plugins/debugger/cdb/cdbwatchmodels.cpp
 delete mode 100644 src/plugins/debugger/cdb/cdbwatchmodels.h

diff --git a/src/plugins/debugger/abstractsyncwatchmodel.cpp b/src/plugins/debugger/abstractsyncwatchmodel.cpp
deleted file mode 100644
index 9cf1d8404dd..00000000000
--- a/src/plugins/debugger/abstractsyncwatchmodel.cpp
+++ /dev/null
@@ -1,107 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (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 http://www.qtsoftware.com/contact.
-**
-**************************************************************************/
-
-#include "abstractsyncwatchmodel.h"
-
-#include <utils/qtcassert.h>
-#include <QtCore/QDebug>
-
-namespace Debugger {
-namespace Internal {
-
-enum  { debug = 0 };
-
-AbstractSyncWatchModel::AbstractSyncWatchModel(WatchHandler *handler, WatchType type, QObject *parent) :
-    WatchModel(handler, type, parent)
-{
-}
-
-void AbstractSyncWatchModel::fetchMore(const QModelIndex &parent)
-{
-    WatchItem *item = watchItem(parent);
-    if (!item || item == root())
-        return;
-    if (debug)
-        qDebug() << ">fetchMore" << item->toString();
-    // Figure out children...
-    if (item->isHasChildrenNeeded()) {
-        m_errorMessage.clear();
-        if (!complete(item, &m_errorMessage)) {
-            item->setHasChildren(false);
-            emit error(m_errorMessage);
-        }
-    }
-    if (item->isChildrenNeeded()) {
-        m_errorMessage.clear();
-        if (fetchChildren(item, &m_errorMessage)) {
-            item->setChildrenUnneeded();
-        } else {
-            item->setHasChildren(false);
-            emit error(m_errorMessage);
-        }
-    }
-
-    if (debug)
-        qDebug() << "<fetchMore" << item->iname << item->children.size();
-}
-
-bool AbstractSyncWatchModel::canFetchMore(const QModelIndex &parent) const
-{
-    WatchItem *item = watchItem(parent);
-    if (!item || item == root())
-        return false;
-    const bool rc = item->isChildrenNeeded() || item->isHasChildrenNeeded();
-    if (debug)
-        qDebug() << "canFetchMore" << rc << item->iname;
-    return rc;
-}
-
-QVariant AbstractSyncWatchModel::data(const QModelIndex &idx, int role) const
-{
-    if (WatchItem *wdata = watchItem(idx)) {
-        const int column = idx.column();
-        // Is any display data (except children) needed?
-        const bool incomplete = (wdata->state & ~WatchData::ChildrenNeeded);
-        if ((debug > 1) && incomplete && column == 0 && role == Qt::DisplayRole)
-            qDebug() << "data()" << "incomplete=" << incomplete << wdata->toString();
-        if (incomplete) {
-            AbstractSyncWatchModel *nonConstThis = const_cast<AbstractSyncWatchModel *>(this);
-            m_errorMessage.clear();
-            if (!nonConstThis->complete(wdata, &m_errorMessage)) {
-                wdata->setAllUnneeded();
-                nonConstThis->emit error(m_errorMessage);
-            }
-        }
-        return WatchModel::data(*wdata, column, role);
-    }
-    return QVariant();
-}
-
-} // namespace Internal
-} // namespace Debugger
diff --git a/src/plugins/debugger/asyncwatchmodel.cpp b/src/plugins/debugger/asyncwatchmodel.cpp
deleted file mode 100644
index 5b627eb8606..00000000000
--- a/src/plugins/debugger/asyncwatchmodel.cpp
+++ /dev/null
@@ -1,232 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (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 http://www.qtsoftware.com/contact.
-**
-**************************************************************************/
-
-#include "asyncwatchmodel.h"
-
-#include <QtCore/QCoreApplication>
-
-#include <utils/qtcassert.h>
-
-namespace Debugger {
-namespace Internal {
-
-int AsyncWatchModel::generationCounter = 0;
-
-static const QString strNotInScope =
-        QCoreApplication::translate("Debugger::Internal::WatchData", "<not in scope>");
-
-////////////////////////////////////////////////////////////////////
-//
-// WatchItem
-//
-////////////////////////////////////////////////////////////////////
-
-AsyncWatchModel::AsyncWatchModel(WatchHandler *handler, WatchType type, QObject *parent) :
-    WatchModel(handler, type, parent)
-{
-    dummyRoot()->fetchTriggered = true;
-}
-
-void AsyncWatchModel::removeOutdated()
-{
-    WatchItem *item = dummyRoot();
-    QTC_ASSERT(item, return);
-    foreach (WatchItem *child, item->children)
-        removeOutdatedHelper(child);
-#if DEBUG_MODEL
-#if USE_MODEL_TEST
-    //(void) new ModelTest(this, this);
-#endif
-#endif
-}
-
-void AsyncWatchModel::removeOutdatedHelper(WatchItem *item)
-{
-    if (item->generation < generationCounter)
-        removeItem(item);
-    else {
-        foreach (WatchItem *child, item->children)
-            removeOutdatedHelper(child);
-        item->fetchTriggered = false;
-    }
-}
-
-bool AsyncWatchModel::canFetchMore(const QModelIndex &index) const
-{
-    if (index.isValid())
-        if (const WatchItem *item = watchItem(index))
-            return !item->fetchTriggered;
-    return false;
-}
-
-void AsyncWatchModel::fetchMore(const QModelIndex &index)
-{
-    QTC_ASSERT(index.isValid(), return);
-    WatchItem *item = watchItem(index);
-    QTC_ASSERT(item && !item->fetchTriggered, return);
-    item->fetchTriggered = true;
-    WatchData data = *item;
-    data.setChildrenNeeded();
-    emit watchDataUpdateNeeded(data);
-}
-
-static bool iNameSorter(const WatchItem *item1, const WatchItem *item2)
-{
-    QString name1 = item1->iname.section('.', -1);
-    QString name2 = item2->iname.section('.', -1);
-    if (!name1.isEmpty() && !name2.isEmpty()) {
-        if (name1.at(0).isDigit() && name2.at(0).isDigit())
-            return name1.toInt() < name2.toInt();
-    }
-    return name1 < name2;
-}
-
-static int findInsertPosition(const QList<WatchItem *> &list, const WatchItem *item)
-{
-    QList<WatchItem *>::const_iterator it =
-        qLowerBound(list.begin(), list.end(), item, iNameSorter);
-    return it - list.begin();
-}
-
-void AsyncWatchModel::insertData(const WatchData &data)
-{
-    // qDebug() << "WMI:" << data.toString();
-    QTC_ASSERT(!data.iname.isEmpty(), return);
-    WatchItem *parent = findItemByIName(parentName(data.iname), root());
-    if (!parent) {
-        WatchData parent;
-        parent.iname = parentName(data.iname);
-        insertData(parent);
-        //MODEL_DEBUG("\nFIXING MISSING PARENT FOR\n" << data.iname);
-        return;
-    }
-    QModelIndex index = watchIndex(parent);
-    if (WatchItem *oldItem = findItemByIName(data.iname, parent)) {
-        // overwrite old entry
-        //MODEL_DEBUG("OVERWRITE : " << data.iname << data.value);
-        bool changed = !data.value.isEmpty()
-            && data.value != oldItem->value
-            && data.value != strNotInScope;
-        oldItem->setData(data);
-        oldItem->changed = changed;
-        oldItem->generation = generationCounter;
-        QModelIndex idx = watchIndex(oldItem);
-        emit dataChanged(idx, idx.sibling(idx.row(), 2));
-    } else {
-        // add new entry
-        //MODEL_DEBUG("INSERT : " << data.iname << data.value);
-        WatchItem *item = new WatchItem(data);
-        item->parent = parent;
-        item->generation = generationCounter;
-        item->changed = true;
-        int n = findInsertPosition(parent->children, item);
-        beginInsertRows(index, n, n);
-        parent->children.insert(n, item);
-        endInsertRows();
-    }
-}
-
-// ----------------- AsyncWatchModelMixin
-AsyncWatchModelMixin::AsyncWatchModelMixin(WatchHandler *wh,
-                                           QObject *parent) :
-    QObject(parent),
-    m_wh(wh)
-{
-}
-
-AsyncWatchModelMixin::~AsyncWatchModelMixin()
-{
-}
-
-AsyncWatchModel *AsyncWatchModelMixin::model(int wt) const
-{
-    if (wt < 0 ||  wt >= WatchModelCount)
-        return 0;
-    if (!m_models[wt]) {
-        m_models[wt] = new AsyncWatchModel(m_wh, static_cast<WatchType>(wt), const_cast<AsyncWatchModelMixin *>(this));
-        connect(m_models[wt], SIGNAL(watchDataUpdateNeeded(WatchData)), this, SIGNAL(watchDataUpdateNeeded(WatchData)));
-        m_models[wt]->setObjectName(QLatin1String("model") + QString::number(wt));
-    }
-    return m_models[wt];
-}
-
-AsyncWatchModel *AsyncWatchModelMixin::modelForIName(const QString &iname) const
-{
-    const WatchType wt = WatchHandler::watchTypeOfIName(iname);
-    QTC_ASSERT(wt != WatchModelCount, return 0);
-    return model(wt);
-}
-
-void AsyncWatchModelMixin::beginCycle()
-{
-    ++AsyncWatchModel::generationCounter;
-}
-
-void AsyncWatchModelMixin::updateWatchers()
-{
-    //qDebug() << "UPDATE WATCHERS";
-    // copy over all watchers and mark all watchers as incomplete
-    foreach (const QString &exp, m_wh->watcherExpressions()) {
-        WatchData data;
-        data.iname = m_wh->watcherName(exp);
-        data.setAllNeeded();
-        data.name = exp;
-        data.exp = exp;
-        insertData(data);
-    }
-}
-
-void AsyncWatchModelMixin::endCycle()
-{
-    for (int m = 0; m < WatchModelCount; m++)
-        if (m_models[m])
-            m_models[m]->removeOutdated();
-}
-
-void AsyncWatchModelMixin::insertWatcher(const WatchData &data)
-{
-    // Is the engine active?
-    if (m_models[WatchersWatch] && m_wh->model(WatchersWatch) == m_models[WatchersWatch])
-        insertData(data);
-}
-
-void AsyncWatchModelMixin::insertData(const WatchData &data)
-{
-    QTC_ASSERT(data.isValid(), return);
-    if (data.isSomethingNeeded()) {
-        emit watchDataUpdateNeeded(data);
-    } else {
-        AsyncWatchModel *model = modelForIName(data.iname);
-        QTC_ASSERT(model, return);
-        model->insertData(data);
-    }
-}
-
-} // namespace Internal
-} // namespace Debugger
diff --git a/src/plugins/debugger/asyncwatchmodel.h b/src/plugins/debugger/asyncwatchmodel.h
deleted file mode 100644
index 880f2f83d76..00000000000
--- a/src/plugins/debugger/asyncwatchmodel.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (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 http://www.qtsoftware.com/contact.
-**
-**************************************************************************/
-
-#ifndef ASYNCWATCHMODEL_H
-#define ASYNCWATCHMODEL_H
-
-#include "watchhandler.h"
-#include <QtCore/QPointer>
-
-namespace Debugger {
-namespace Internal {
-
-/* AsyncWatchModel: incrementally populated by asynchronous debuggers via
- * fetch. */
-
-class AsyncWatchModel : public WatchModel
-{
-    Q_OBJECT
-public:
-    explicit AsyncWatchModel(WatchHandler *handler, WatchType type, QObject *parent = 0);
-
-    bool canFetchMore(const QModelIndex &parent) const;
-    void fetchMore(const QModelIndex &parent);
-
-    friend class WatchHandler;
-    friend class GdbEngine;
-
-    void insertData(const WatchData &data);
-
-    void removeOutdated();
-    void removeOutdatedHelper(WatchItem *item);
-
-    void setActiveData(const QString &data) { m_activeData = data; }
-
-    static int generationCounter;
-
-signals:
-    void watchDataUpdateNeeded(const WatchData &data);
-
-private:
-    QString m_activeData;
-    WatchItem *m_root;
-};
-
-/* A Mixin to manage asynchronous models. */
-
-class AsyncWatchModelMixin :  public QObject {
-    Q_OBJECT
-public:
-    explicit AsyncWatchModelMixin(WatchHandler *wh, QObject *parent = 0);
-    virtual ~AsyncWatchModelMixin();
-
-    AsyncWatchModel *model(int t) const;
-    AsyncWatchModel *modelForIName(const QString &iname) const;
-
-    void beginCycle(); // called at begin of updateLocals() cycle
-    void updateWatchers(); // called after locals are fetched
-    void endCycle(); // called after all results have been received
-
-public slots:
-    void insertData(const WatchData &data);
-    // For watchers, ensures that engine is active
-    void insertWatcher(const WatchData &data);
-
-signals:
-    void watchDataUpdateNeeded(const WatchData &data);
-
-private:
-    WatchHandler *m_wh;
-    mutable QPointer<AsyncWatchModel> m_models[WatchModelCount];
-};
-
-} // namespace Internal
-} // namespace Debugger
-
-#endif // ASYNCWATCHMODEL_H
diff --git a/src/plugins/debugger/cdb/cdb.pri b/src/plugins/debugger/cdb/cdb.pri
index 3c7398567b8..06f14409d32 100644
--- a/src/plugins/debugger/cdb/cdb.pri
+++ b/src/plugins/debugger/cdb/cdb.pri
@@ -39,6 +39,7 @@ HEADERS += \
     $$PWD/cdbsymbolgroupcontext.h \
     $$PWD/cdbsymbolgroupcontext_tpl.h \
     $$PWD/cdbstacktracecontext.h \
+    $$PWD/cdbstackframecontext.h \
     $$PWD/cdbbreakpoint.h \
     $$PWD/cdbmodules.h \
     $$PWD/cdbassembler.h \
@@ -46,14 +47,14 @@ HEADERS += \
     $$PWD/cdboptionspage.h \
     $$PWD/cdbdumperhelper.h \
     $$PWD/cdbsymbolpathlisteditor.h \
-    $$PWD/cdbexceptionutils.h \
-    $$PWD/cdbwatchmodels.h
+    $$PWD/cdbexceptionutils.h
 
 SOURCES += \
     $$PWD/cdbdebugengine.cpp \
     $$PWD/cdbdebugeventcallback.cpp \
     $$PWD/cdbdebugoutput.cpp \
     $$PWD/cdbsymbolgroupcontext.cpp \
+    $$PWD/cdbstackframecontext.cpp \
     $$PWD/cdbstacktracecontext.cpp \
     $$PWD/cdbbreakpoint.cpp \
     $$PWD/cdbmodules.cpp \
@@ -62,8 +63,7 @@ SOURCES += \
     $$PWD/cdboptionspage.cpp \
     $$PWD/cdbdumperhelper.cpp \
     $$PWD/cdbsymbolpathlisteditor.cpp \
-    $$PWD/cdbexceptionutils.cpp \
-    $$PWD/cdbwatchmodels.cpp
+    $$PWD/cdbexceptionutils.cpp
 
 FORMS += $$PWD/cdboptionspagewidget.ui
 
diff --git a/src/plugins/debugger/cdb/cdbdebugengine.cpp b/src/plugins/debugger/cdb/cdbdebugengine.cpp
index 867cfb5a91c..798f5234ff4 100644
--- a/src/plugins/debugger/cdb/cdbdebugengine.cpp
+++ b/src/plugins/debugger/cdb/cdbdebugengine.cpp
@@ -30,6 +30,7 @@
 #include "cdbdebugengine.h"
 #include "cdbdebugengine_p.h"
 #include "cdbstacktracecontext.h"
+#include "cdbstackframecontext.h"
 #include "cdbsymbolgroupcontext.h"
 #include "cdbbreakpoint.h"
 #include "cdbmodules.h"
@@ -46,7 +47,6 @@
 #include "moduleshandler.h"
 #include "disassemblerhandler.h"
 #include "watchutils.h"
-#include "cdbwatchmodels.h"
 
 #include <coreplugin/icore.h>
 #include <utils/qtcassert.h>
@@ -301,9 +301,7 @@ CdbDebugEnginePrivate::CdbDebugEnginePrivate(DebuggerManager *parent,
     m_debuggerManagerAccess(parent->engineInterface()),
     m_currentStackTrace(0),
     m_firstActivatedFrame(true),
-    m_mode(AttachCore),
-    m_localsModel(0),
-    m_watchModel(0)
+    m_mode(AttachCore)
 {
 }
 
@@ -392,15 +390,6 @@ CdbDebugEnginePrivate::~CdbDebugEnginePrivate()
         m_cif.debugDataSpaces->Release();
 }
 
-void CdbDebugEnginePrivate::saveLocalsViewState()
-{
-    if (m_localsModel && m_localsModel->symbolGroupContext()) {
-        const int oldFrame = m_debuggerManagerAccess->stackHandler()->currentIndex();
-        if (oldFrame != -1)
-            m_debuggerManagerAccess->watchHandler()->saveLocalsViewState(oldFrame);
-    }
-}
-
 void CdbDebugEnginePrivate::clearForRun()
 {
     if (debugCDB)
@@ -414,10 +403,6 @@ void CdbDebugEnginePrivate::clearForRun()
 
 void CdbDebugEnginePrivate::cleanStackTrace()
 {
-    if (m_localsModel) {
-        saveLocalsViewState();
-        m_localsModel->setSymbolGroupContext(0);
-    }
     if (m_currentStackTrace) {
         delete m_currentStackTrace;
         m_currentStackTrace = 0;
@@ -480,19 +465,14 @@ QString CdbDebugEngine::editorToolTip(const QString &exp, const QString &functio
     QString errorMessage;
     QString rc;
     // Find the frame of the function if there is any
-    const QString iname = QLatin1String("local.") + exp;
+    CdbStackFrameContext *frame = 0;
     if (m_d->m_currentStackTrace &&  !function.isEmpty()) {
         const int frameIndex = m_d->m_currentStackTrace->indexOf(function);
-        if (frameIndex != -1) {
-            // Are we at the current frame?
-            if (frameIndex == m_d->m_debuggerManagerAccess->stackHandler()->currentIndex()) {
-                if (const WatchData *wd = m_d->m_localsModel->findItemByIName(iname, m_d->m_localsModel->root()))
-                    return wd->toToolTip();                            }
-            // Nope, try to retrieve via another symbol group
-            if (m_d->m_currentStackTrace->editorToolTip(frameIndex, iname, &rc, &errorMessage))
-                return rc;
-        }
+        if (frameIndex != -1)
+            frame = m_d->m_currentStackTrace->frameContextAt(frameIndex, &errorMessage);
     }
+    if (frame && frame->editorToolTip(QLatin1String("local.") + exp, &rc, &errorMessage))
+        return rc;
     // No function/symbol context found, try to evaluate in current context.
     // Do not append type as this will mostly be 'long long' for integers, etc.
     QString type;
@@ -790,6 +770,67 @@ void CdbDebugEngine::detachDebugger()
     m_d->endDebugging(CdbDebugEnginePrivate::EndDebuggingDetach);
 }
 
+CdbStackFrameContext *CdbDebugEnginePrivate::getStackFrameContext(int frameIndex, QString *errorMessage) const
+{
+    if (!m_currentStackTrace) {
+        *errorMessage = QLatin1String(msgNoStackTraceC);
+        return 0;
+    }
+    if (CdbStackFrameContext *sg = m_currentStackTrace->frameContextAt(frameIndex, errorMessage))
+        return sg;
+    return 0;
+}
+
+void CdbDebugEngine::evaluateWatcher(WatchData *wd)
+{
+    if (debugCDBWatchHandling)
+        qDebug() << Q_FUNC_INFO << wd->exp;
+    QString errorMessage;
+    QString value;
+    QString type;
+    if (evaluateExpression(wd->exp, &value, &type, &errorMessage)) {
+        wd->setValue(value);
+        wd->setType(type);
+    } else {
+        wd->setValue(errorMessage);
+        wd->setTypeUnneeded();
+    }
+    wd->setHasChildren(false);
+}
+
+void CdbDebugEngine::updateWatchData(const WatchData &incomplete)
+{
+    // Watch item was edited while running
+    if (m_d->isDebuggeeRunning())
+        return;
+
+    if (debugCDBWatchHandling)
+        qDebug() << Q_FUNC_INFO << "\n    " << incomplete.toString();
+
+    WatchHandler *watchHandler = m_d->m_debuggerManagerAccess->watchHandler();
+    if (incomplete.iname.startsWith(QLatin1String("watch."))) {
+        WatchData watchData = incomplete;
+        evaluateWatcher(&watchData);
+        watchHandler->insertData(watchData);
+        return;
+    }
+
+    const int frameIndex = m_d->m_debuggerManagerAccess->stackHandler()->currentIndex();
+
+    bool success = false;
+    QString errorMessage;
+    do {
+        CdbStackFrameContext *sg = m_d->m_currentStackTrace->frameContextAt(frameIndex, &errorMessage);
+        if (!sg)
+            break;
+        if (!sg->completeData(incomplete, watchHandler, &errorMessage))
+            break;
+        success = true;
+    } while (false);
+    if (!success)
+        warning(msgFunctionFailed(Q_FUNC_INFO, errorMessage));
+}
+
 void CdbDebugEngine::stepExec()
 {
     if (debugCDB)
@@ -996,14 +1037,18 @@ void CdbDebugEngine::assignValueInDebugger(const QString &expr, const QString &v
     bool success = false;
     do {
         QString newValue;
-        if (frameIndex < 0 || !m_d->m_currentStackTrace) {
-            errorMessage = tr("No current stack trace.");
+        CdbStackFrameContext *sg = m_d->getStackFrameContext(frameIndex, &errorMessage);
+        if (!sg)
             break;
-        }
-        // Assign in stack and update view
-        if (!m_d->m_currentStackTrace->assignValue(frameIndex, expr, value, &newValue, &errorMessage))
+        if (!sg->assignValue(expr, value, &newValue, &errorMessage))
             break;
-        m_d->m_localsModel->setValueByExpression(expr, newValue);
+        // Update view
+        WatchHandler *watchHandler = m_d->m_debuggerManagerAccess->watchHandler();
+        if (WatchData *fwd = watchHandler->findItem(expr)) {
+            fwd->setValue(newValue);
+            watchHandler->insertData(*fwd);
+            watchHandler->updateWatchers();
+        }
         success = true;
     } while (false);
     if (!success) {
@@ -1033,11 +1078,6 @@ bool CdbDebugEnginePrivate::executeDebuggerCommand(CIDebugControl *ctrl, const Q
     return true;
 }
 
-bool CdbDebugEngine::isDebuggeeHalted() const
-{
-    return m_d->m_hDebuggeeProcess && !m_d->isDebuggeeRunning();
-}
-
 bool CdbDebugEngine::evaluateExpression(const QString &expression,
                                         QString *value,
                                         QString *type,
@@ -1092,21 +1132,21 @@ void CdbDebugEngine::activateFrame(int frameIndex)
     bool success = false;
     do {
         StackHandler *stackHandler = m_d->m_debuggerManagerAccess->stackHandler();
+        WatchHandler *watchHandler = m_d->m_debuggerManagerAccess->watchHandler();
         const int oldIndex = stackHandler->currentIndex();
         if (frameIndex >= stackHandler->stackSize()) {
             errorMessage = msgStackIndexOutOfRange(frameIndex, stackHandler->stackSize());
             break;
         }
 
-        if (oldIndex != frameIndex) {
-            m_d->saveLocalsViewState();
+        if (oldIndex != frameIndex)
             stackHandler->setCurrentIndex(frameIndex);
-        }
 
         const StackFrame &frame = stackHandler->currentFrame();
         if (!frame.isUsable()) {
-            m_d->m_localsModel->setSymbolGroupContext(0);
             // Clean out model
+            watchHandler->beginCycle();
+            watchHandler->endCycle();
             errorMessage = QString::fromLatin1("%1: file %2 unusable.").
                            arg(QLatin1String(Q_FUNC_INFO), frame.file);
             break;
@@ -1115,18 +1155,10 @@ void CdbDebugEngine::activateFrame(int frameIndex)
         m_d->m_debuggerManager->gotoLocation(frame.file, frame.line, true);
 
         if (oldIndex != frameIndex || m_d->m_firstActivatedFrame) {
-            m_d->m_localsModel->setUseDumpers(m_d->m_dumper->isEnabled() && theDebuggerBoolSetting(UseDebuggingHelpers));
-            CdbSymbolGroupContext *ctx = 0;
-            if (m_d->m_currentStackTrace) {
-                ctx = m_d->m_currentStackTrace->symbolGroupAt(frameIndex, &errorMessage);
-                success = ctx != 0;
-            } else {
-                errorMessage = QLatin1String(msgNoStackTraceC);
-            }
-            m_d->m_localsModel->setSymbolGroupContext(ctx);
-            m_d->m_debuggerManagerAccess->watchHandler()->restoreLocalsViewState(frameIndex);
-        } else {
-            success = true;
+            watchHandler->beginCycle();
+            if (CdbStackFrameContext *sgc = m_d->getStackFrameContext(frameIndex, &errorMessage))
+                success = sgc->populateModelInitially(watchHandler, &errorMessage);
+            watchHandler->endCycle();
         }
     } while (false);
     if (!success)
@@ -1190,7 +1222,7 @@ bool CdbDebugEnginePrivate::attemptBreakpointSynchronization(QString *errorMessa
                                                  m_cif.debugSymbols,
                                                  m_debuggerManagerAccess->breakHandler(),
                                                  errorMessage, &warnings);
-    if (const int warningsCount = warnings.size())
+    if (const int warningsCount = warnings.size())        
         for (int w = 0; w < warningsCount; w++)
             m_engine->warning(warnings.at(w));
     return ok;
@@ -1468,8 +1500,7 @@ void CdbDebugEnginePrivate::updateStackTrace()
         m_debuggerManagerAccess->stackHandler()->setCurrentIndex(current);
         m_engine->activateFrame(current);
     }
-    // Update watchers
-    m_watchModel->refresh();
+    m_debuggerManagerAccess->watchHandler()->updateWatchers();
 }
 
 void CdbDebugEnginePrivate::updateModules()
@@ -1481,6 +1512,8 @@ void CdbDebugEnginePrivate::updateModules()
     m_debuggerManagerAccess->modulesHandler()->setModules(modules);
 }
 
+static const char *dumperPrefixC = "dumper";
+
 void CdbDebugEnginePrivate::handleModuleLoad(const QString &name)
 {
     if (debugCDB>2)
@@ -1553,37 +1586,6 @@ bool CdbDebugEnginePrivate::setSymbolPaths(const QStringList &s, QString *errorM
     return true;
 }
 
-void CdbDebugEngine::insertWatcher(const WatchData &wd)
-{
-    // Make sure engine is active
-    if (m_d->m_watchModel && m_d->m_watchModel == m_d->m_debuggerManagerAccess->watchHandler()->model(WatchersWatch))
-        m_d->m_watchModel->addWatcher(wd);
-}
-
-WatchModel *CdbDebugEngine::watchModel(int type) const
-{
-    switch (type) {
-    case LocalsWatch:
-        if (!m_d->m_localsModel) {
-            m_d->m_localsModel = new CdbLocalsModel(m_d->m_dumper, m_d->m_debuggerManagerAccess->watchHandler(), LocalsWatch, const_cast<CdbDebugEngine*>(this));
-            connect(m_d->m_localsModel, SIGNAL(error(QString)), this, SLOT(warning(QString)));
-        }
-        return m_d->m_localsModel;
-    case WatchersWatch:
-        if (!m_d->m_watchModel) {
-            CdbDebugEngine* nonConstThis = const_cast<CdbDebugEngine*>(this);
-            WatchHandler *wh = m_d->m_debuggerManagerAccess->watchHandler();
-            m_d->m_watchModel = new CdbWatchModel(nonConstThis, m_d->m_dumper, wh, WatchersWatch, nonConstThis);
-            connect(m_d->m_watchModel, SIGNAL(error(QString)), this, SLOT(warning(QString)));
-            connect(wh, SIGNAL(watcherInserted(WatchData)), this, SLOT(insertWatcher(WatchData)));
-        }
-        return m_d->m_watchModel;
-    default:
-        break;
-    }
-    return 0;
-}
-
 } // namespace Internal
 } // namespace Debugger
 
diff --git a/src/plugins/debugger/cdb/cdbdebugengine.h b/src/plugins/debugger/cdb/cdbdebugengine.h
index 8c827769709..13725bb97e4 100644
--- a/src/plugins/debugger/cdb/cdbdebugengine.h
+++ b/src/plugins/debugger/cdb/cdbdebugengine.h
@@ -64,14 +64,15 @@ public:
     virtual bool startDebugger(const QSharedPointer<DebuggerStartParameters> &startParameters);
     virtual void exitDebugger();
     virtual void detachDebugger();
+    virtual void updateWatchData(const WatchData &data);
 
     virtual void stepExec();
     virtual void stepOutExec();
     virtual void nextExec();
     virtual void stepIExec();
     virtual void nextIExec();
-
-    virtual void continueInferior();
+    
+    virtual void continueInferior();    
     virtual void interruptInferior();
 
     virtual void runToLineExec(const QString &fileName, int lineNumber);
@@ -96,11 +97,6 @@ public:
     virtual void reloadSourceFiles();
     virtual void reloadFullStack() {}
 
-    WatchModel *watchModel(int type) const;
-
-    bool isDebuggeeHalted() const;
-    bool evaluateExpression(const QString &expression, QString *value, QString *type, QString *errorMessage);
-
 public slots:
     void syncDebuggerPaths();
 
@@ -110,9 +106,8 @@ protected:
 private slots:
     void slotConsoleStubStarted();
     void slotConsoleStubError(const QString &msg);
-    void slotConsoleStubTerminated();
+    void slotConsoleStubTerminated();    
     void warning(const QString &w);
-    void insertWatcher(const WatchData &);
 
 private:
     bool startAttachDebugger(qint64 pid, DebuggerStartMode sm, QString *errorMessage);
@@ -121,7 +116,8 @@ private:
     void killWatchTimer();
     void processTerminated(unsigned long exitCode);
     bool executeDebuggerCommand(const QString &command, QString *errorMessage);
-
+    bool evaluateExpression(const QString &expression, QString *value, QString *type, QString *errorMessage);
+    void evaluateWatcher(WatchData *wd);
     QString editorToolTip(const QString &exp, const QString &function);
 
     CdbDebugEnginePrivate *m_d;
diff --git a/src/plugins/debugger/cdb/cdbdebugengine_p.h b/src/plugins/debugger/cdb/cdbdebugengine_p.h
index 910486aa8b5..23eb5648275 100644
--- a/src/plugins/debugger/cdb/cdbdebugengine_p.h
+++ b/src/plugins/debugger/cdb/cdbdebugengine_p.h
@@ -39,7 +39,6 @@
 
 #include <utils/consoleprocess.h>
 #include <QtCore/QSharedPointer>
-#include <QtCore/QPointer>
 #include <QtCore/QMap>
 
 namespace Debugger {
@@ -50,8 +49,6 @@ class IDebuggerManagerAccessForEngines;
 class WatchHandler;
 class CdbStackFrameContext;
 class CdbStackTraceContext;
-class CdbLocalsModel;
-class CdbWatchModel;
 
 // Thin wrapper around the 'DBEng' debugger engine shared library
 // which is loaded at runtime.
@@ -118,7 +115,7 @@ struct CdbDebugEnginePrivate
 
     bool isDebuggeeRunning() const { return m_watchTimer != -1; }
     void handleDebugEvent();
-    void updateThreadList();
+    void updateThreadList();    
     void updateStackTrace();
     void updateModules();
 
@@ -126,6 +123,7 @@ struct CdbDebugEnginePrivate
     void cleanStackTrace();
     void clearForRun();
     void handleModuleLoad(const QString &);
+    CdbStackFrameContext *getStackFrameContext(int frameIndex, QString *errorMessage) const;
     void clearDisplay();
 
     bool interruptInterferiorProcess(QString *errorMessage);
@@ -139,8 +137,6 @@ struct CdbDebugEnginePrivate
     enum EndDebuggingMode { EndDebuggingDetach, EndDebuggingTerminate, EndDebuggingAuto };
     void endDebugging(EndDebuggingMode em = EndDebuggingAuto);
 
-    void saveLocalsViewState();
-
     static bool executeDebuggerCommand(CIDebugControl *ctrl, const QString &command, QString *errorMessage);
     static bool evaluateExpression(CIDebugControl *ctrl, const QString &expression, DEBUG_VALUE *v, QString *errorMessage);
 
@@ -159,7 +155,7 @@ struct CdbDebugEnginePrivate
     int                     m_watchTimer;
     CdbComInterfaces        m_cif;
     CdbDebugEventCallback   m_debugEventCallBack;
-    CdbDebugOutput          m_debugOutputCallBack;
+    CdbDebugOutput          m_debugOutputCallBack;    
     QSharedPointer<CdbDumperHelper> m_dumper;
 
     CdbDebugEngine* m_engine;
@@ -172,9 +168,6 @@ struct CdbDebugEnginePrivate
 
     DebuggerStartMode m_mode;
     Core::Utils::ConsoleProcess m_consoleStubProc;
-
-    QPointer<CdbLocalsModel> m_localsModel;
-    QPointer<CdbWatchModel> m_watchModel;
 };
 
 // helper functions
diff --git a/src/plugins/debugger/abstractsyncwatchmodel.h b/src/plugins/debugger/cdb/cdbstackframecontext.h
similarity index 52%
rename from src/plugins/debugger/abstractsyncwatchmodel.h
rename to src/plugins/debugger/cdb/cdbstackframecontext.h
index 91573a0602b..f9ba79c9f83 100644
--- a/src/plugins/debugger/abstractsyncwatchmodel.h
+++ b/src/plugins/debugger/cdb/cdbstackframecontext.h
@@ -27,49 +27,49 @@
 **
 **************************************************************************/
 
-#ifndef ABSTRACTSYNCWATCHMODEL_H
-#define ABSTRACTSYNCWATCHMODEL_H
+#ifndef CDBSTACKFRAMECONTEXT_H
+#define CDBSTACKFRAMECONTEXT_H
 
-#include "watchhandler.h"
-#include <QtCore/QPointer>
 #include <QtCore/QList>
-
-QT_BEGIN_NAMESPACE
-class QDebug;
-QT_END_NAMESPACE
+#include <QtCore/QSharedPointer>
 
 namespace Debugger {
 namespace Internal {
 
-/* AbstractSyncWatchModel: To be used by synchonous debuggers.
- * Implements all of WatchModel and provides new virtuals for
- * the debugger to complete items. */
+class WatchData;
+class WatchHandler;
+class CdbSymbolGroupContext;
+class CdbDumperHelper;
+
+/* CdbStackFrameContext manages a symbol group context and
+ * a dumper context. It dispatches calls between the local items
+ * that are handled by the symbol group and those that are handled by the dumpers. */
 
-class AbstractSyncWatchModel : public WatchModel
+class CdbStackFrameContext
 {
-    Q_OBJECT
+    Q_DISABLE_COPY(CdbStackFrameContext)
 public:
-    explicit AbstractSyncWatchModel(WatchHandler *handler, WatchType type, QObject *parent = 0);
-
-    virtual QVariant data(const QModelIndex &index, int role) const;
+    explicit CdbStackFrameContext(const QSharedPointer<CdbDumperHelper> &dumper,
+                                  CdbSymbolGroupContext *symbolContext);
+    ~CdbStackFrameContext();   
 
-    virtual void fetchMore(const QModelIndex &parent);
-    virtual bool canFetchMore(const QModelIndex &parent) const;
+    bool assignValue(const QString &iname, const QString &value,
+                     QString *newValue /* = 0 */, QString *errorMessage);
+    bool editorToolTip(const QString &iname, QString *value, QString *errorMessage);
 
-signals:
-    // Emitted if one of fetchChildren/complete fails.
-    void error(const QString &);
+    bool populateModelInitially(WatchHandler *wh, QString *errorMessage);
 
-protected:
-    // Overwrite these virtuals to fetch children of an item and to complete it
-    virtual bool fetchChildren(WatchItem *wd, QString *errorMessage) = 0;
-    virtual bool complete(WatchItem *wd, QString *errorMessage) = 0;
+    bool completeData(const WatchData &incompleteLocal,
+                      WatchHandler *wh,
+                      QString *errorMessage);
 
 private:
-    mutable QString m_errorMessage;
+    const bool m_useDumpers;
+    const QSharedPointer<CdbDumperHelper> m_dumper;
+    CdbSymbolGroupContext *m_symbolContext;
 };
 
 } // namespace Internal
 } // namespace Debugger
 
-#endif // ABSTRACTSYNCWATCHMODEL_H
+#endif // CDBSTACKFRAMECONTEXT_H
diff --git a/src/plugins/debugger/cdb/cdbstacktracecontext.cpp b/src/plugins/debugger/cdb/cdbstacktracecontext.cpp
index d3d927cd49f..7663f315d0a 100644
--- a/src/plugins/debugger/cdb/cdbstacktracecontext.cpp
+++ b/src/plugins/debugger/cdb/cdbstacktracecontext.cpp
@@ -28,11 +28,11 @@
 **************************************************************************/
 
 #include "cdbstacktracecontext.h"
+#include "cdbstackframecontext.h"
 #include "cdbbreakpoint.h"
 #include "cdbsymbolgroupcontext.h"
 #include "cdbdebugengine_p.h"
 #include "cdbdumperhelper.h"
-#include "debuggeractions.h"
 
 #include <QtCore/QDir>
 #include <QtCore/QTextStream>
@@ -90,7 +90,7 @@ bool CdbStackTraceContext::init(unsigned long frameCount, QString * /*errorMessa
         qDebug() << Q_FUNC_INFO << frameCount;
 
     m_frameContexts.resize(frameCount);
-    qFill(m_frameContexts, static_cast<CdbSymbolGroupContext*>(0));
+    qFill(m_frameContexts, static_cast<CdbStackFrameContext*>(0));
 
     // Convert the DEBUG_STACK_FRAMEs to our StackFrame structure and populate the frames
     WCHAR wszBuf[MAX_PATH];
@@ -145,7 +145,7 @@ static inline QString msgFrameContextFailed(int index, const StackFrame &f, cons
             arg(index).arg(f.function).arg(f.line).arg(f.file, why);
 }
 
-CdbSymbolGroupContext *CdbStackTraceContext::symbolGroupAt(int index, QString *errorMessage)
+CdbStackFrameContext *CdbStackTraceContext::frameContextAt(int index, QString *errorMessage)
 {
     // Create a frame on demand
     if (debugCDB)
@@ -158,7 +158,6 @@ CdbSymbolGroupContext *CdbStackTraceContext::symbolGroupAt(int index, QString *e
     }
     if (m_frameContexts.at(index))
         return m_frameContexts.at(index);
-    // Create COM and wrap
     CIDebugSymbolGroup *sg  = createSymbolGroup(index, errorMessage);
     if (!sg) {
         *errorMessage = msgFrameContextFailed(index, m_frames.at(index), *errorMessage);
@@ -169,8 +168,9 @@ CdbSymbolGroupContext *CdbStackTraceContext::symbolGroupAt(int index, QString *e
         *errorMessage = msgFrameContextFailed(index, m_frames.at(index), *errorMessage);
         return 0;
     }
-    m_frameContexts[index] = sc;
-    return sc;
+    CdbStackFrameContext *fr = new CdbStackFrameContext(m_dumper, sc);
+    m_frameContexts[index] = fr;
+    return fr;
 }
 
 CIDebugSymbolGroup *CdbStackTraceContext::createSymbolGroup(int index, QString *errorMessage)
@@ -198,49 +198,6 @@ CIDebugSymbolGroup *CdbStackTraceContext::createSymbolGroup(int index, QString *
     return sg;
 }
 
-bool CdbStackTraceContext::editorToolTip(int frameIndex,
-                                         const QString &iname,
-                                         QString *value,
-                                         QString *errorMessage)
-{
-    value->clear();
-    // Look up iname in the frame's symbol group.
-    CdbSymbolGroupContext *m_symbolContext = symbolGroupAt(frameIndex, errorMessage);
-    if (!m_symbolContext)
-        return false;
-    unsigned long index;
-    if (!m_symbolContext->lookupPrefix(iname, &index)) {
-        *errorMessage = QString::fromLatin1("%1 not found.").arg(iname);
-        return false;
-    }
-    const WatchData wd = m_symbolContext->symbolAt(index);
-    // Check dumpers. Should actually be just one item.
-    if (theDebuggerBoolSetting(UseDebuggingHelpers) && m_dumper->isEnabled()) {
-        QList<WatchData> result;
-        if (CdbDumperHelper::DumpOk == m_dumper->dumpType(wd, false, 1, &result, errorMessage))  {
-            foreach (const WatchData &dwd, result) {
-                if (!value->isEmpty())
-                    value->append(QLatin1Char('\n'));
-                value->append(dwd.toToolTip());
-            }
-            return true;
-        } // Dumped ok
-    }     // has Dumpers
-    *value = wd.toToolTip();
-    return true;
-}
-
-bool CdbStackTraceContext::assignValue(int frameIndex,
-                                       const QString &iname,
-                                       const QString &value,
-                                       QString *newValue /* = 0 */, QString *errorMessage)
-{
-    if (CdbSymbolGroupContext *symbolContext = symbolGroupAt(frameIndex, errorMessage))
-        return symbolContext->assignValue(iname, value, newValue, errorMessage);
-    return  false;
-}
-
-
 QString CdbStackTraceContext::toString() const
 {
     QString rc;
diff --git a/src/plugins/debugger/cdb/cdbstacktracecontext.h b/src/plugins/debugger/cdb/cdbstacktracecontext.h
index d878472450b..9dfbdf04745 100644
--- a/src/plugins/debugger/cdb/cdbstacktracecontext.h
+++ b/src/plugins/debugger/cdb/cdbstacktracecontext.h
@@ -47,10 +47,11 @@ namespace Internal {
 
 struct CdbComInterfaces;
 class CdbSymbolGroupContext;
+class CdbStackFrameContext;
 class CdbDumperHelper;
 
 /* Context representing a break point stack consisting of several frames.
- * Maintains an on-demand constructed list of CdbSymbolGroupContext
+ * Maintains an on-demand constructed list of CdbStackFrameContext
  * containining the local variables of the stack. */
 
 class CdbStackTraceContext        
@@ -74,17 +75,7 @@ public:
     // Top-Level instruction offset for disassembler
     ULONG64 instructionOffset() const { return m_instructionOffset; }
 
-    CdbSymbolGroupContext *symbolGroupAt(int index, QString *errorMessage);
-
-    // Helper to retrieve an editor tooltip for a frame. Note that
-    // for the current frame, the LocalsModel should be consulted first.
-    bool editorToolTip(int frameIndex,const QString &iname,  QString *value, QString *errorMessage);
-
-    // Assign value in Debugger
-    bool assignValue(int frameIndex,
-                     const QString &iname,
-                     const QString &value,
-                     QString *newValue /* = 0 */, QString *errorMessage);
+    CdbStackFrameContext *frameContextAt(int index, QString *errorMessage);
 
     // Format for logging
     void format(QTextStream &str) const;
@@ -98,7 +89,7 @@ private:
     CdbComInterfaces *m_cif;
 
     DEBUG_STACK_FRAME m_cdbFrames[maxFrames];
-    QVector <CdbSymbolGroupContext*> m_frameContexts;
+    QVector <CdbStackFrameContext*> m_frameContexts;
     QList<StackFrame> m_frames;
     ULONG64 m_instructionOffset;
 };
diff --git a/src/plugins/debugger/cdb/cdbsymbolgroupcontext.cpp b/src/plugins/debugger/cdb/cdbsymbolgroupcontext.cpp
index 94bf9814f62..5d82835f53d 100644
--- a/src/plugins/debugger/cdb/cdbsymbolgroupcontext.cpp
+++ b/src/plugins/debugger/cdb/cdbsymbolgroupcontext.cpp
@@ -406,6 +406,7 @@ WatchData CdbSymbolGroupContext::symbolAt(unsigned long index) const
     const QString value = getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolValueTextWide, index);
     wd.setType(type);
     wd.setValue(fixValue(value));
+    wd.setChildrenNeeded(); // compensate side effects of above setters
     // Figure out children. The SubElement is only a guess unless the symbol,
     // is expanded, so, we leave this as a guess for later updates.
     // If the symbol has children (expanded or not), we leave the 'Children' flag
diff --git a/src/plugins/debugger/cdb/cdbsymbolgroupcontext.h b/src/plugins/debugger/cdb/cdbsymbolgroupcontext.h
index 16b7f5fab61..91ec5fd9240 100644
--- a/src/plugins/debugger/cdb/cdbsymbolgroupcontext.h
+++ b/src/plugins/debugger/cdb/cdbsymbolgroupcontext.h
@@ -81,6 +81,31 @@ public:
     bool assignValue(const QString &iname, const QString &value,
                      QString *newValue /* = 0 */, QString *errorMessage);
 
+    // Initially populate the locals model for a new stackframe.
+    // Write a sequence of WatchData to it, recurse down if the
+    // recursionPredicate agrees. The ignorePredicate can be used
+    // to terminate processing after insertion of an item (if the calling
+    // routine wants to insert another subtree).
+    template <class OutputIterator, class RecursionPredicate, class IgnorePredicate>
+    static bool populateModelInitially(CdbSymbolGroupContext *sg,
+                                       OutputIterator it,
+                                       RecursionPredicate recursionPredicate,
+                                       IgnorePredicate ignorePredicate,
+                                       QString *errorMessage);
+
+    // Complete children of a WatchData item.
+    // Write a sequence of WatchData to it, recurse if the
+    // recursionPredicate agrees. The ignorePredicate can be used
+    // to terminate processing after insertion of an item (if the calling
+    // routine wants to insert another subtree).
+    template <class OutputIterator, class RecursionPredicate, class IgnorePredicate>
+    static bool completeData (CdbSymbolGroupContext *sg,
+                              WatchData incompleteLocal,
+                              OutputIterator it,
+                              RecursionPredicate recursionPredicate,
+                              IgnorePredicate ignorePredicate,
+                              QString *errorMessage);
+
     // Retrieve child symbols of prefix as a sequence of WatchData.
     template <class OutputIterator>
             bool getChildSymbols(const QString &prefix, OutputIterator it, QString *errorMessage);
diff --git a/src/plugins/debugger/cdb/cdbsymbolgroupcontext_tpl.h b/src/plugins/debugger/cdb/cdbsymbolgroupcontext_tpl.h
index 5aa9c35a2fd..ccaba97ee89 100644
--- a/src/plugins/debugger/cdb/cdbsymbolgroupcontext_tpl.h
+++ b/src/plugins/debugger/cdb/cdbsymbolgroupcontext_tpl.h
@@ -66,6 +66,105 @@ bool CdbSymbolGroupContext::getChildSymbols(const QString &prefix, OutputIterato
     return true;
 }
 
+// Insert a symbol (and its first level children depending on forceRecursion)
+// The parent symbol is inserted before the children to make dumper handling
+// simpler. In theory, it can happen that the symbol context indicates
+// children but can expand none, which would lead to invalid parent information
+// (expand icon), though (ignore for simplicity).
+template <class OutputIterator, class RecursionPredicate, class IgnorePredicate>
+bool insertSymbolRecursion(WatchData wd,
+                           CdbSymbolGroupContext *sg,
+                           OutputIterator it,
+                           RecursionPredicate recursionPredicate,
+                           IgnorePredicate ignorePredicate,
+                           QString *errorMessage)
+{
+    // Find out whether to recurse (has children and predicate agrees)
+    const bool hasChildren = wd.hasChildren || wd.isChildrenNeeded();
+    const bool recurse = hasChildren && recursionPredicate(wd);
+    if (debugSgRecursion)
+        qDebug() << "insertSymbolRecursion" << '\n' << wd.iname << "recurse=" << recurse;
+    if (!recurse) {
+        // No further recursion at this level, pretend entry is complete
+        // to the watchmodel for the parent to show (only remaining watchhandler-specific
+        // part here).
+        if (wd.isChildrenNeeded()) {
+            wd.setHasChildren(true);
+            wd.setChildrenUnneeded();
+        }
+        if (debugSgRecursion)
+            qDebug() << " INSERTING non-recursive: " << wd.toString();
+        *it = wd;
+        ++it;
+        return true;
+    }
+    // Recursion: Indicate children unneeded
+    wd.setHasChildren(true);
+    wd.setChildrenUnneeded();
+    if (debugSgRecursion)
+        qDebug() << " INSERTING recursive: " << wd.toString();
+    *it = wd;
+    ++it;
+    // Recurse unless the predicate disagrees
+    if (ignorePredicate(wd))
+        return true;
+    QList<WatchData> watchList;
+    // This implicitly enforces expansion
+    if (!sg->getChildSymbols(wd.iname, WatchDataBackInserter(watchList), errorMessage))
+        return false;
+    const int childCount = watchList.size();
+    for (int c = 0; c < childCount; c++) {
+        const WatchData &cwd = watchList.at(c);
+        if (wd.isValid()) { // We sometimes get empty names for deeply nested data
+            if (!insertSymbolRecursion(cwd, sg, it, recursionPredicate, ignorePredicate, errorMessage))
+                return false;
+        }  else {
+            const QString msg = QString::fromLatin1("WARNING: Skipping invalid child symbol #%2 (type %3) of '%4'.").
+                                arg(QLatin1String(Q_FUNC_INFO)).arg(c).arg(cwd.type, wd.iname);
+            qWarning("%s\n", qPrintable(msg));
+        }
+    }
+    return true;
+}
+
+template <class OutputIterator, class RecursionPredicate, class IgnorePredicate>
+bool CdbSymbolGroupContext::populateModelInitially(CdbSymbolGroupContext *sg,
+                                                   OutputIterator it,
+                                                   RecursionPredicate recursionPredicate,
+                                                   IgnorePredicate ignorePredicate,
+                                                   QString *errorMessage)
+{
+    if (debugSgRecursion)
+        qDebug() << "### CdbSymbolGroupContext::populateModelInitially";
+
+    // Insert root items
+    QList<WatchData> watchList;
+    if (!sg->getChildSymbols(sg->prefix(), WatchDataBackInserter(watchList), errorMessage))
+        return false;
+    // Insert data
+    foreach(const WatchData &wd, watchList)
+        if (!insertSymbolRecursion(wd, sg, it, recursionPredicate, ignorePredicate, errorMessage))
+            return false;
+    return true;
+}
+
+template <class OutputIterator, class RecursionPredicate, class IgnorePredicate>
+bool CdbSymbolGroupContext::completeData(CdbSymbolGroupContext *sg,
+                                         WatchData incompleteLocal,
+                                         OutputIterator it,
+                                         RecursionPredicate recursionPredicate,
+                                         IgnorePredicate ignorePredicate,
+                                         QString *errorMessage)
+{
+    if (debugSgRecursion)
+        qDebug().nospace() << "###>CdbSymbolGroupContext::completeData" << ' ' << incompleteLocal.iname << '\n';
+    // If the symbols are already expanded in the context, they will be re-inserted,
+    // which is not handled for simplicity.
+    if (!insertSymbolRecursion(incompleteLocal, sg, it, recursionPredicate, ignorePredicate, errorMessage))
+        return false;
+    return true;
+}
+
 } // namespace Internal
 } // namespace Debugger
 
diff --git a/src/plugins/debugger/cdb/cdbwatchmodels.cpp b/src/plugins/debugger/cdb/cdbwatchmodels.cpp
deleted file mode 100644
index 0f5bb70846f..00000000000
--- a/src/plugins/debugger/cdb/cdbwatchmodels.cpp
+++ /dev/null
@@ -1,477 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (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 http://www.qtsoftware.com/contact.
-**
-**************************************************************************/
-
-#include "cdbwatchmodels.h"
-#include "cdbdumperhelper.h"
-#include "cdbsymbolgroupcontext.h"
-#include "cdbdebugengine.h"
-#include "watchutils.h"
-#include "debuggeractions.h"
-
-#include <QtCore/QDebug>
-#include <QtCore/QList>
-#include <QtCore/QCoreApplication>
-#include <QtCore/QRegExp>
-
-enum { debugCDBWatchHandling = 0 };
-
-namespace Debugger {
-namespace Internal {
-
-enum { LocalsOwnerSymbolGroup, LocalsOwnerDumper };
-
-static inline QString msgNoStackFrame()
-{
-    return QCoreApplication::translate("CdbWatchModels", "No active stack frame present.");
-}
-
-static inline QString msgUnknown()
-{
-    return QCoreApplication::translate("CdbWatchModels", "<Unknown>");
-}
-
-// Helper to add a sequence of WatchData from the symbol group context to an item
-// without using dumpers.
-
-class SymbolGroupInserter
-{
-public:
-    explicit SymbolGroupInserter(WatchItem *parent) : m_parent(parent) {}
-
-    inline SymbolGroupInserter& operator*() { return *this; }
-    inline SymbolGroupInserter&operator=(const WatchData &wd) {
-        WatchItem *item = new WatchItem(wd);
-        item->source = LocalsOwnerSymbolGroup;
-        m_parent->addChild(item);
-        return *this;
-    }
-    inline SymbolGroupInserter&operator++() { return *this; }
-
-private:
-    WatchItem *m_parent;
-};
-
-// fixDumperResult: When querying an item, the queried item is sometimes returned in
-// incomplete form. Take over values from source, set items with missing addresses to
-// "complete".
-static inline void fixDumperResult(const WatchData &source,
-                                   QList<WatchData> *result)
-{
-    if (debugCDBWatchHandling > 1) {
-        qDebug() << "fixDumperResult for : " << source.toString();
-        foreach (const WatchData &wd, *result)
-            qDebug() << "   " << wd.toString();
-    }
-    const int size = result->size();
-    if (!size)
-        return;
-    WatchData &returned = result->front();
-    if (returned.iname != source.iname)
-        return;
-    if (returned.type.isEmpty())
-        returned.setType(source.type);
-    if (returned.isValueNeeded()) {
-        if (source.isValueKnown()) {
-            returned.setValue(source.value);
-        } else {
-            // Should not happen
-            returned.setValue(msgUnknown());
-            qWarning("%s: No value for %s\n", Q_FUNC_INFO, qPrintable(returned.toString()));
-        }
-    }
-    if (size == 1)
-        return;
-    // Fix the children: If the address is missing, we cannot query any further.
-    const QList<WatchData>::iterator wend = result->end();
-    QList<WatchData>::iterator it = result->begin();
-    for (++it; it != wend; ++it) {
-        WatchData &wd = *it;
-        if (wd.addr.isEmpty() && wd.isSomethingNeeded()) {
-            wd.setAllUnneeded();
-        }
-    }
-}
-
-// Dump an item. If *ptrToDumpedItem == 0, allocate a new item and set it.
-// If it is non-null, the item pointed to will receive the results
-// ("complete" functionality).
-static CdbDumperHelper::DumpResult
-        dumpItem(const QSharedPointer<CdbDumperHelper> dumper,
-                 const WatchData &wd,
-                 WatchItem **ptrToDumpedItem,
-                 int dumperOwnerValue, QString *errorMessage)
-{
-    QList<WatchData> dumperResult;
-    WatchItem *dumpedItem = *ptrToDumpedItem;
-    const CdbDumperHelper::DumpResult rc = dumper->dumpType(wd, true, dumperOwnerValue, &dumperResult, errorMessage);
-    if (debugCDBWatchHandling > 1)
-        qDebug() << "dumper for " << wd.type << " returns " << rc;
-
-    switch (rc) {
-    case CdbDumperHelper::DumpError:
-        return rc;
-    case CdbDumperHelper::DumpNotHandled:
-        errorMessage->clear();
-        return rc;
-    case CdbDumperHelper::DumpOk:
-        break;
-    }
-    // Dumpers omit types for complicated templates
-    fixDumperResult(wd, &dumperResult);
-    // Discard the original item and insert the dumper results
-    if (dumpedItem) {
-        dumpedItem->setData(dumperResult.front());
-    } else {
-        dumpedItem = new WatchItem(dumperResult.front());
-        *ptrToDumpedItem = dumpedItem;
-    }
-    dumperResult.pop_front();
-    foreach(const WatchData &dwd, dumperResult)
-        dumpedItem->addChild(new WatchItem(dwd));
-    return rc;
-}
-
-// Is this a non-null pointer to a dumpeable item with a value
-// "0x4343 class QString *" ? - Insert a fake '*' dereferenced item
-// and run dumpers on it. If that succeeds, insert the fake items owned by dumpers,
-// Note that the symbol context does not create '*' dereferenced items for
-// classes (see note in its header documentation).
-static bool expandPointerToDumpable(const QSharedPointer<CdbDumperHelper> dumper,
-                                    const WatchData &wd,
-                                    WatchItem *parent,
-                                    QString *errorMessage)
-{
-
-
-    if (debugCDBWatchHandling > 1)
-        qDebug() << ">expandPointerToDumpable" << wd.iname;
-
-    WatchItem *derefedWdItem = 0;
-    WatchItem *ptrWd = 0;
-    bool handled = false;
-    do {
-        if (!isPointerType(wd.type))
-            break;
-        const int classPos = wd.value.indexOf(" class ");
-        if (classPos == -1)
-            break;
-        const QString hexAddrS = wd.value.mid(0, classPos);
-        static const QRegExp hexNullPattern(QLatin1String("0x0+"));
-        Q_ASSERT(hexNullPattern.isValid());
-        if (hexNullPattern.exactMatch(hexAddrS))
-            break;
-        const QString type = stripPointerType(wd.value.mid(classPos + 7));
-        WatchData derefedWd;
-        derefedWd.setType(type);
-        derefedWd.setAddress(hexAddrS);
-        derefedWd.name = QString(QLatin1Char('*'));
-        derefedWd.iname = wd.iname + QLatin1String(".*");
-        derefedWd.source = LocalsOwnerDumper;
-        QList<WatchData> dumperResult;
-        const CdbDumperHelper::DumpResult dr = dumpItem(dumper, derefedWd, &derefedWdItem, LocalsOwnerDumper, errorMessage);
-        if (dr != CdbDumperHelper::DumpOk)
-            break;
-        // Insert the pointer item with 1 additional child + its dumper results
-        // Note: formal arguments might already be expanded in the symbol group.
-        ptrWd = new WatchItem(wd);
-        ptrWd->source = LocalsOwnerDumper;
-        ptrWd->setHasChildren(true);
-        ptrWd->setChildrenUnneeded();
-        ptrWd->addChild(derefedWdItem);
-        parent->addChild(ptrWd);
-        handled = true;
-    } while (false);
-    if (!handled) {
-        delete derefedWdItem;
-        delete ptrWd;
-    }
-    if (debugCDBWatchHandling > 1)
-        qDebug() << "<expandPointerToDumpable returns " << handled << *errorMessage;
-    return handled;
-}
-
-// Main routine for inserting an item from the symbol group using the dumpers
-// where applicable.
-static inline bool insertDumpedItem(const QSharedPointer<CdbDumperHelper> &dumper,
-                                    const WatchData &wd,
-                                    WatchItem *parent,
-                                    QString *errorMessage)
-{
-    if (debugCDBWatchHandling > 1)
-        qDebug() << "insertItem=" << wd.toString();
-    // Check pointer to dumpeable, dumpeable, insert accordingly.
-    if (expandPointerToDumpable(dumper, wd, parent, errorMessage))
-        return true;
-    WatchItem *dumpedItem = 0;
-    // Add item owned by Dumper or symbol group on failure.
-    const CdbDumperHelper::DumpResult dr = dumpItem(dumper, wd, &dumpedItem, LocalsOwnerDumper, errorMessage);
-    switch (dr) {
-        case CdbDumperHelper::DumpOk:
-        dumpedItem->parent = parent;
-        parent->children.push_back(dumpedItem);
-        break;
-    case CdbDumperHelper::DumpNotHandled:
-        case CdbDumperHelper::DumpError: {
-        WatchItem *symbolItem = new WatchItem(wd);
-        symbolItem->source = LocalsOwnerSymbolGroup;
-        parent->addChild(symbolItem);
-    }
-        break;
-    }
-    return true;
-}
-
-// Helper to add a sequence of  WatchData from the symbol group context to an item.
-// Checks if the item is dumpable in some way; if so, dump it and use that instead of
-// symbol group.
-class SymbolGroupDumperInserter
-{
-public:
-    explicit SymbolGroupDumperInserter(const QSharedPointer<CdbDumperHelper> &dumper,
-                                       WatchItem *parent,
-                                       QString *errorMessage);
-
-    inline SymbolGroupDumperInserter& operator*() { return *this; }
-    inline SymbolGroupDumperInserter&operator=(const WatchData &wd) {
-        insertDumpedItem(m_dumper, wd, m_parent, m_errorMessage);
-        return *this;
-    }
-    inline SymbolGroupDumperInserter&operator++() { return *this; }
-
-private:
-    const QSharedPointer<CdbDumperHelper> m_dumper;
-    WatchItem *m_parent;
-    QString *m_errorMessage;
-};
-
-SymbolGroupDumperInserter::SymbolGroupDumperInserter(const QSharedPointer<CdbDumperHelper> &dumper,
-                                              WatchItem *parent,
-                                              QString *errorMessage) :
-    m_dumper(dumper),
-    m_parent(parent),
-    m_errorMessage(errorMessage)
-{
-}
-
-// -------------- CdbLocalsModel
-
-CdbLocalsModel::CdbLocalsModel(const QSharedPointer<CdbDumperHelper> &dh,
-                               WatchHandler *handler, WatchType type, QObject *parent) :
-    AbstractSyncWatchModel(handler, type, parent),
-    m_dumperHelper(dh),
-    m_symbolGroupContext(0),
-    m_useDumpers(false)
-{
-}
-
-CdbLocalsModel::~CdbLocalsModel()
-{
-}
-
-bool CdbLocalsModel::fetchChildren(WatchItem *wd, QString *errorMessage)
-{
-    if (!m_symbolGroupContext) {
-        *errorMessage = msgNoStackFrame();
-        return false;
-    }
-    if (debugCDBWatchHandling)
-        qDebug() << "fetchChildren" << wd->iname;
-
-    // Check the owner and call it to expand the item.
-    switch (wd->source) {
-    case LocalsOwnerSymbolGroup:
-        if (m_useDumpers && m_dumperHelper->isEnabled()) {
-            SymbolGroupDumperInserter inserter(m_dumperHelper, wd, errorMessage);
-            return m_symbolGroupContext->getChildSymbols(wd->iname, inserter, errorMessage);
-        } else {
-            return m_symbolGroupContext->getChildSymbols(wd->iname, SymbolGroupInserter(wd), errorMessage);
-        }
-        break;
-    case LocalsOwnerDumper:
-        if (dumpItem(m_dumperHelper, *wd, &wd, LocalsOwnerDumper, errorMessage) == CdbDumperHelper::DumpOk)
-            return true;
-        if (wd->isValueNeeded())
-            wd->setValue(msgUnknown());
-        qWarning("%s: No value for %s\n", Q_FUNC_INFO, qPrintable(wd->toString()));
-        return false;
-    }
-    return false;
-}
-
-bool CdbLocalsModel::complete(WatchItem *wd, QString *errorMessage)
-{
-    if (!m_symbolGroupContext) {
-        *errorMessage = msgNoStackFrame();
-        return false;
-    }
-    if (debugCDBWatchHandling)
-        qDebug() << "complete" << wd->iname;
-    // Might as well fetch children when completing a dumped item.
-    return fetchChildren(wd, errorMessage);
-}
-
-void CdbLocalsModel::setSymbolGroupContext(CdbSymbolGroupContext *s)
-{
-    if (s == m_symbolGroupContext)
-        return;
-    if (debugCDBWatchHandling)
-        qDebug() << ">setSymbolGroupContext" << s;
-    m_symbolGroupContext = s;
-    reinitialize();
-    if (!m_symbolGroupContext)
-        return;
-    // Populate first row
-    WatchItem *item = dummyRoot();
-    QString errorMessage;
-    do {
-        if (m_useDumpers && m_dumperHelper->isEnabled()) {
-            SymbolGroupDumperInserter inserter(m_dumperHelper, item, &errorMessage);
-            if (!m_symbolGroupContext->getChildSymbols(m_symbolGroupContext->prefix(), inserter, &errorMessage)) {
-                break;
-            }
-        } else {
-            if (!m_symbolGroupContext->getChildSymbols(m_symbolGroupContext->prefix(), SymbolGroupInserter(item), &errorMessage))
-                break;
-        }
-        if (item->children.empty())
-            break;
-        reset();
-    } while (false);
-    if (!errorMessage.isEmpty())
-        emit error(errorMessage);
-    if (debugCDBWatchHandling)
-        qDebug() << "<setSymbolGroupContext" << item->children.size() << errorMessage;
-    if (debugCDBWatchHandling > 1)
-        qDebug() << '\n' << *this;
-}
-
-// ---- CdbWatchModel
-
-enum { WatchOwnerNewItem, WatchOwnerExpression, WatchOwnerDumper };
-
-CdbWatchModel::CdbWatchModel(CdbDebugEngine *engine,
-                             const QSharedPointer<CdbDumperHelper> &dh,
-                             WatchHandler *handler,
-                             WatchType type, QObject *parent) :
-   AbstractSyncWatchModel(handler, type, parent),
-   m_dumperHelper(dh),
-   m_engine(engine)
-{
-}
-
-CdbWatchModel::~CdbWatchModel()
-{
-}
-
-bool CdbWatchModel::evaluateWatchExpression(WatchData *wd, QString *errorMessage)
-{
-    QString value;
-    QString type;
-
-    const bool rc = m_engine->evaluateExpression(wd->exp, &value, &type, errorMessage);
-    if (!rc) {
-        wd->setValue(msgUnknown());
-        return false;
-    }
-    wd->setValue(value);
-    wd->setType(type);
-    return true;
-}
-
-bool CdbWatchModel::fetchChildren(WatchItem *wd, QString *errorMessage)
-{
-    if (debugCDBWatchHandling)
-        qDebug() << "Watch:fetchChildren" << wd->iname << wd->source;
-    // We need to be halted.
-    if (!m_engine->isDebuggeeHalted()) {
-        *errorMessage = QCoreApplication::translate("CdbWatchModels", "Can evaluates watches only in halted state.");
-        wd->setValue(msgUnknown());
-        return false;
-    }
-    // New item with address -> dumper.
-    if (wd->source == WatchOwnerNewItem)
-        wd->source = wd->addr.isEmpty() ? WatchOwnerExpression : WatchOwnerDumper;
-    // Expressions
-    if (wd->source == WatchOwnerExpression)
-        return evaluateWatchExpression(wd, errorMessage);
-    // Variables by address
-    if (!m_dumperHelper->isEnabled() || !theDebuggerBoolSetting(UseDebuggingHelpers)) {
-        *errorMessage = QCoreApplication::translate("CdbWatchModels", "Cannot evaluate '%1' due to dumpers being disabled.").arg(wd->name);
-        return false;
-    }
-    return dumpItem(m_dumperHelper, *wd, &wd, WatchOwnerDumper, errorMessage) == CdbDumperHelper::DumpOk;
-}
-
-bool CdbWatchModel::complete(WatchItem *wd, QString *errorMessage)
-{
-    return fetchChildren(wd, errorMessage);
-}
-
-void CdbWatchModel::addWatcher(const WatchData &wd)
-{
-    WatchItem *root = dummyRoot();
-    if (!root)
-        return;
-    const QModelIndex rootIndex = watchIndex(root);
-    beginInsertRows(rootIndex, root->children.size(), root->children.size());
-    root->addChild(new WatchItem(wd));
-    endInsertRows();
-}
-
-void CdbWatchModel::refresh()
-{
-    // Refresh data for a new break
-    WatchItem *root = dummyRoot();
-    if (!root)
-        return;
-    const int childCount = root->children.size();
-    if (!childCount)
-        return;
-    // reset flags, if there children, trigger a reset
-    bool resetRequired = false;
-    for (int i = 0; i < childCount; i++) {
-        WatchItem *topLevel = root->children.at(i);
-        topLevel->setAllNeeded();
-        if (!topLevel->children.empty()) {
-            topLevel->removeChildren();
-            resetRequired = true;
-        }
-    }
-    // notify model
-    if (resetRequired) {
-        reset();
-    } else {
-        const QModelIndex topLeft = watchIndex(root->children.front());
-        const QModelIndex bottomLeft = root->children.size() == 1 ? topLeft : watchIndex(root->children.back());
-        emit dataChanged(topLeft.sibling(0, 1), bottomLeft.sibling(0, columnCount() -1));
-    }
-}
-
-} // namespace Internal
-} // namespace Debugger
diff --git a/src/plugins/debugger/cdb/cdbwatchmodels.h b/src/plugins/debugger/cdb/cdbwatchmodels.h
deleted file mode 100644
index 29c8be80505..00000000000
--- a/src/plugins/debugger/cdb/cdbwatchmodels.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (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 http://www.qtsoftware.com/contact.
-**
-**************************************************************************/
-
-#ifndef CDBWATCHMODELS_H
-#define CDBWATCHMODELS_H
-
-#include "abstractsyncwatchmodel.h"
-#include <QtCore/QSharedPointer>
-
-namespace Debugger {
-namespace Internal {
-
-class CdbSymbolGroupContext;
-class CdbDumperHelper;
-class CdbDebugEngine;
-
-class CdbLocalsModel : public AbstractSyncWatchModel {
-    Q_DISABLE_COPY(CdbLocalsModel)
-    Q_OBJECT
-public:
-    explicit CdbLocalsModel(const QSharedPointer<CdbDumperHelper> &dh,
-                            WatchHandler *handler, WatchType type, QObject *parent = 0);
-    ~CdbLocalsModel();
-
-    // Set a symbolgroup context, thus activating a stack frame.
-    // Set 0 to clear out.
-    void setSymbolGroupContext(CdbSymbolGroupContext *sg = 0);
-    CdbSymbolGroupContext *symbolGroupContext() const { return m_symbolGroupContext; }
-
-    void setUseDumpers(bool d) { m_useDumpers = d; }
-
-protected:
-    virtual bool fetchChildren(WatchItem *wd, QString *errorMessage);
-    virtual bool complete(WatchItem *wd, QString *errorMessage);
-
-private:
-    const QSharedPointer<CdbDumperHelper> m_dumperHelper;
-    CdbSymbolGroupContext *m_symbolGroupContext;
-    bool m_useDumpers;
-};
-
-class CdbWatchModel : public AbstractSyncWatchModel {
-   Q_DISABLE_COPY(CdbWatchModel)
-   Q_OBJECT
-public:
-    explicit CdbWatchModel(CdbDebugEngine *engine,
-                           const QSharedPointer<CdbDumperHelper> &dh,
-                           WatchHandler *handler,
-                           WatchType type, QObject *parent = 0);
-   ~CdbWatchModel();
-
-public slots:
-   void addWatcher(const WatchData &d);
-   void refresh();
-
-protected:
-    virtual bool fetchChildren(WatchItem *wd, QString *errorMessage);
-    virtual bool complete(WatchItem *wd, QString *errorMessage);
-
-private:
-    bool evaluateWatchExpression(WatchData *wd, QString *errorMessage);
-
-   const QSharedPointer<CdbDumperHelper> m_dumperHelper;
-   CdbDebugEngine *m_engine;
-};
-
-} // namespace Internal
-} // namespace Debugger
-
-#endif // CDBWATCHMODELS_H
diff --git a/src/plugins/debugger/debugger.pro b/src/plugins/debugger/debugger.pro
index c74dcdd01f4..25b7c355f07 100644
--- a/src/plugins/debugger/debugger.pro
+++ b/src/plugins/debugger/debugger.pro
@@ -44,8 +44,6 @@ HEADERS += \
     sourcefileswindow.h \
     threadswindow.h \
     watchhandler.h \
-    asyncwatchmodel.h \
-    abstractsyncwatchmodel.h \
     watchwindow.h \
 
 SOURCES += \
@@ -73,8 +71,6 @@ SOURCES += \
     sourcefileswindow.cpp \
     threadswindow.cpp \
     watchhandler.cpp \
-    asyncwatchmodel.cpp \
-    abstractsyncwatchmodel.cpp \
     watchwindow.cpp \
 
 FORMS += attachexternaldialog.ui \
diff --git a/src/plugins/debugger/debuggermanager.cpp b/src/plugins/debugger/debuggermanager.cpp
index 67a9d93efbe..15c586b5bba 100644
--- a/src/plugins/debugger/debuggermanager.cpp
+++ b/src/plugins/debugger/debuggermanager.cpp
@@ -187,8 +187,7 @@ static IDebuggerEngine *tcfEngine = 0;
 
 DebuggerManager::DebuggerManager()
   : m_startParameters(new DebuggerStartParameters),
-    m_inferiorPid(0),
-    m_watchHandler(new WatchHandler)
+    m_inferiorPid(0)
 {
     init();
 }
@@ -232,8 +231,6 @@ void DebuggerManager::init()
     m_sourceFilesWindow = new SourceFilesWindow;
     m_threadsWindow = new ThreadsWindow;
     m_localsWindow = new WatchWindow(WatchWindow::LocalsType);
-    m_watchHandler->init(m_localsWindow);
-
     m_watchersWindow = new WatchWindow(WatchWindow::WatchersType);
     //m_tooltipWindow = new WatchWindow(WatchWindow::TooltipType);
     m_statusTimer = new QTimer(this);
@@ -324,7 +321,14 @@ void DebuggerManager::init()
     m_registerHandler = new RegisterHandler;
     registerView->setModel(m_registerHandler->model());
 
-    // Locals/Watchers
+    // Locals
+    m_watchHandler = new WatchHandler;
+    QTreeView *localsView = qobject_cast<QTreeView *>(m_localsWindow);
+    localsView->setModel(m_watchHandler->model(LocalsWatch));
+
+    // Watchers
+    QTreeView *watchersView = qobject_cast<QTreeView *>(m_watchersWindow);
+    watchersView->setModel(m_watchHandler->model(WatchersWatch));
     connect(m_watchHandler, SIGNAL(sessionValueRequested(QString,QVariant*)),
         this, SIGNAL(sessionValueRequested(QString,QVariant*)));
     connect(m_watchHandler, SIGNAL(setSessionValueRequested(QString,QVariant)),
@@ -333,6 +337,12 @@ void DebuggerManager::init()
         this, SLOT(assignValueInDebugger()), Qt::QueuedConnection);
 
     // Tooltip
+    //QTreeView *tooltipView = qobject_cast<QTreeView *>(m_tooltipWindow);
+    //tooltipView->setModel(m_watchHandler->model(TooltipsWatch));
+
+    connect(m_watchHandler, SIGNAL(watchDataUpdateNeeded(WatchData)),
+        this, SLOT(updateWatchData(WatchData)));
+
     m_continueAction = new QAction(this);
     m_continueAction->setText(tr("Continue"));
     m_continueAction->setIcon(QIcon(":/debugger/images/debugger_continue_small.png"));
@@ -461,34 +471,12 @@ void DebuggerManager::init()
     localsAndWatchers->setStretchFactor(2, 1);
     m_watchDock = createDockForWidget(localsAndWatchers);
 
-    initializeWatchModels(gdbEngine);
-
     setStatus(DebuggerProcessNotReady);
 }
 
-void DebuggerManager::initializeWatchModels(IDebuggerEngine *engine)
-{
-    if (engine == 0)
-        return;
-    WatchModel *localsModel = engine->watchModel(LocalsWatch);
-    m_watchHandler->setModel(LocalsWatch, localsModel);
-    m_localsWindow->setModel(localsModel);
-
-    WatchModel *watchModel = engine->watchModel(WatchersWatch);
-    m_watchHandler->setModel(WatchersWatch, watchModel);
-    m_watchersWindow->setModel(watchModel);
-
-    if (WatchModel *toolTipModel = engine->watchModel(TooltipsWatch)) {
-        m_watchHandler->setModel(TooltipsWatch, toolTipModel);
-    } else {
-        m_watchHandler->setModel(TooltipsWatch, 0);
-    }
-}
-
 QList<Core::IOptionsPage*> DebuggerManager::initializeEngines(unsigned enabledTypeFlags)
 {
     QList<Core::IOptionsPage*> rc;
-    // Initialize watch models so columns show up initially.
     if (enabledTypeFlags & GdbEngineType)
         gdbEngine = createGdbEngine(this, &rc);
     winEngine = createWinEngine(this, (enabledTypeFlags & CdbEngineType), &rc);
@@ -499,12 +487,6 @@ QList<Core::IOptionsPage*> DebuggerManager::initializeEngines(unsigned enabledTy
     m_engine = 0;
     if (Debugger::Constants::Internal::debug)
         qDebug() << Q_FUNC_INFO << gdbEngine << winEngine << scriptEngine << rc.size();
-    if (gdbEngine) {
-        initializeWatchModels(gdbEngine);
-    } else {
-        if (winEngine)
-            initializeWatchModels(winEngine);
-    }
     return rc;
 }
 
@@ -820,6 +802,12 @@ void DebuggerManager::setToolTipExpression(const QPoint &mousePos, TextEditor::I
         m_engine->setToolTipExpression(mousePos, editor, cursorPos);
 }
 
+void DebuggerManager::updateWatchData(const WatchData &data)
+{
+    if (m_engine)
+        m_engine->updateWatchData(data);
+}
+
 QVariant DebuggerManager::sessionValue(const QString &name)
 {
     // this is answered by the plugin
@@ -874,7 +862,7 @@ static IDebuggerEngine *determineDebuggerEngine(const QString &executable,
         return scriptEngine;
     }
 
-#ifndef Q_OS_WIN
+#ifndef Q_OS_WIN    
     Q_UNUSED(settingsIdHint)
     if (!gdbEngine) {
         *errorMessage = msgEngineNotAvailable("Gdb Engine");
@@ -955,7 +943,6 @@ void DebuggerManager::startNewDebugger(DebuggerRunControl *runControl,
         break;
     }
 
-
     if (!m_engine) {
         debuggingFinished();
         // Create Message box with possibility to go to settings
@@ -969,7 +956,6 @@ void DebuggerManager::startNewDebugger(DebuggerRunControl *runControl,
             Core::ICore::instance()->showOptionsDialog(_(Debugger::Constants::DEBUGGER_SETTINGS_CATEGORY), settingsIdHint);
         return;
     }
-    initializeWatchModels(m_engine);
 
     if (Debugger::Constants::Internal::debug)
         qDebug() << m_startParameters->executable << m_engine;
diff --git a/src/plugins/debugger/debuggermanager.h b/src/plugins/debugger/debuggermanager.h
index 3dc8dcb16b9..c153465c884 100644
--- a/src/plugins/debugger/debuggermanager.h
+++ b/src/plugins/debugger/debuggermanager.h
@@ -46,7 +46,6 @@ class QModelIndex;
 class QPoint;
 class QTimer;
 class QWidget;
-class QTreeView;
 class QDebug;
 QT_END_NAMESPACE
 
@@ -308,6 +307,7 @@ public slots:
     void detachDebugger();
 
     void addToWatchWindow();
+    void updateWatchData(const WatchData &data);
 
     void sessionLoaded();
     void sessionUnloaded();
@@ -418,7 +418,6 @@ public:
 private:
     void init();
     void runTest(const QString &fileName);
-    void initializeWatchModels(IDebuggerEngine *engine);
     QDockWidget *createDockForWidget(QWidget *widget);
     Q_SLOT void createNewDock(QWidget *widget);
     void updateDockWidget(QDockWidget *dockWidget);
@@ -484,12 +483,13 @@ private:
 
     QWidget *m_breakWindow;
     QWidget *m_disassemblerWindow;
-    QTreeView *m_localsWindow;
+    QWidget *m_localsWindow;
     QWidget *m_registerWindow;
     QWidget *m_modulesWindow;
+    //QWidget *m_tooltipWindow;
     QWidget *m_stackWindow;
     QWidget *m_threadsWindow;
-    QTreeView *m_watchersWindow;
+    QWidget *m_watchersWindow;
     DebuggerOutputWindow *m_outputWindow;
 
     int m_status;
diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp
index 91fffde641a..e9bbb509566 100644
--- a/src/plugins/debugger/gdb/gdbengine.cpp
+++ b/src/plugins/debugger/gdb/gdbengine.cpp
@@ -46,7 +46,6 @@
 #include "registerhandler.h"
 #include "stackhandler.h"
 #include "watchhandler.h"
-#include "asyncwatchmodel.h"
 #include "sourcefileswindow.h"
 
 #include "debuggerdialogs.h"
@@ -153,8 +152,7 @@ GdbEngine::GdbEngine(DebuggerManager *parent) :
     m_dumperInjectionLoad(false),
 #endif
     q(parent),
-    qq(parent->engineInterface()),
-    m_models(qq->watchHandler())
+    qq(parent->engineInterface())
 {
     m_stubProc.setMode(Core::Utils::ConsoleProcess::Debug);
 #ifdef Q_OS_UNIX
@@ -172,8 +170,6 @@ GdbEngine::~GdbEngine()
 
 void GdbEngine::initializeConnections()
 {
-    connect(qq->watchHandler(), SIGNAL(watcherInserted(WatchData)), &m_models, SLOT(insertWatcher(WatchData)));
-    connect(&m_models, SIGNAL(watchDataUpdateNeeded(WatchData)), this, SLOT(updateWatchData(WatchData)));
     // Gdb Process interaction
     connect(&m_gdbProc, SIGNAL(error(QProcess::ProcessError)),
         this, SLOT(gdbProcError(QProcess::ProcessError)));
@@ -2700,10 +2696,10 @@ static QString tooltipINameForExpression(const QString &exp)
 bool GdbEngine::showToolTip()
 {
     WatchHandler *handler = qq->watchHandler();
-    AsyncWatchModel *model = static_cast<AsyncWatchModel *>(handler->model(TooltipsWatch));
+    WatchModel *model = handler->model(TooltipsWatch);
     QString iname = tooltipINameForExpression(m_toolTipExpression);
     model->setActiveData(iname);
-    WatchItem *item = model->findItemByIName(iname, model->dummyRoot());
+    WatchItem *item = model->findItem(iname, model->dummyRoot());
     if (!item) {
         hideDebuggerToolTip();
         return false;
@@ -2792,7 +2788,7 @@ void GdbEngine::setToolTipExpression(const QPoint &mousePos,
     toolTip.name = exp;
     toolTip.iname = tooltipINameForExpression(exp);
     qq->watchHandler()->removeData(toolTip.iname);
-    m_models.insertData(toolTip);
+    qq->watchHandler()->insertData(toolTip);
 }
 
 
@@ -3150,7 +3146,7 @@ void GdbEngine::rebuildModel()
     PENDING_DEBUG("REBUILDING MODEL");
     emit gdbInputAvailable(LogStatus, _("<Rebuild Watchmodel>"));
     q->showStatusMessage(tr("Finished retrieving data."), 400);
-    m_models.endCycle();
+    qq->watchHandler()->endCycle();
     showToolTip();
 }
 
@@ -3546,7 +3542,7 @@ void GdbEngine::updateLocals()
     PENDING_DEBUG("\nRESET PENDING");
     //m_toolTipCache.clear();
     m_toolTipExpression.clear();
-    m_models.beginCycle();
+    qq->watchHandler()->beginCycle();
 
     QString level = QString::number(currentFrame());
     // '2' is 'list with type and value'
@@ -3600,7 +3596,7 @@ void GdbEngine::handleStackListLocals(const GdbResultRecord &record, const QVari
     locals += m_currentFunctionArgs;
 
     setLocals(locals);
-    m_models.updateWatchers();
+    qq->watchHandler()->updateWatchers();
 }
 
 void GdbEngine::setLocals(const QList<GdbMi> &locals)
@@ -3672,7 +3668,7 @@ void GdbEngine::insertData(const WatchData &data0)
         qDebug() << "BOGUS VALUE:" << data.toString();
         return;
     }
-    m_models.insertData(data);
+    qq->watchHandler()->insertData(data);
 }
 
 void GdbEngine::handleVarListChildrenHelper(const GdbMi &item,
diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h
index 0ad6dc2e90b..41137705879 100644
--- a/src/plugins/debugger/gdb/gdbengine.h
+++ b/src/plugins/debugger/gdb/gdbengine.h
@@ -34,7 +34,6 @@
 #include "gdbmi.h"
 #include "outputcollector.h"
 #include "watchutils.h"
-#include "asyncwatchmodel.h"
 
 #include <consoleprocess.h>
 
@@ -123,8 +122,6 @@ private:
     void loadAllSymbols();
     virtual QList<Symbol> moduleSymbols(const QString &moduleName);
 
-    WatchModel *watchModel(int type) const { return m_models.model(type); }
-
     Q_SLOT void setDebugDebuggingHelpers(const QVariant &on);
     Q_SLOT void setUseDebuggingHelpers(const QVariant &on);
 
@@ -200,7 +197,6 @@ private slots:
     void stubStarted();
     void stubError(const QString &msg);
     void uploadProcError(QProcess::ProcessError error);
-    void updateWatchData(const WatchData &data);
 
 private:
     int terminationIndex(const QByteArray &buffer, int &length);
@@ -328,6 +324,7 @@ private:
     // FIXME: BaseClass. called to improve situation for a watch item
     void updateSubItem(const WatchData &data);
 
+    void updateWatchData(const WatchData &data);
     void rebuildModel();
 
     void insertData(const WatchData &data);
@@ -387,7 +384,6 @@ private:
 
     DebuggerManager * const q;
     IDebuggerManagerAccessForEngines * const qq;
-    AsyncWatchModelMixin m_models;
     // make sure to re-initialize new members in initializeVariables();
 };
 
diff --git a/src/plugins/debugger/idebuggerengine.h b/src/plugins/debugger/idebuggerengine.h
index f99e26bd869..dbbdb143143 100644
--- a/src/plugins/debugger/idebuggerengine.h
+++ b/src/plugins/debugger/idebuggerengine.h
@@ -46,8 +46,6 @@ class ITextEditor;
 namespace Debugger {
 namespace Internal {
 
-class WatchModel;
-
 class Symbol;
 class WatchData;
 struct DebuggerStartParameters;
@@ -62,13 +60,14 @@ public:
     virtual bool startDebugger(const QSharedPointer<DebuggerStartParameters> &startParameters) = 0;
     virtual void exitDebugger() = 0;
     virtual void detachDebugger() {}
+    virtual void updateWatchData(const WatchData &data) = 0;
 
     virtual void stepExec() = 0;
     virtual void stepOutExec() = 0;
     virtual void nextExec() = 0;
     virtual void stepIExec() = 0;
     virtual void nextIExec() = 0;
-
+    
     virtual void continueInferior() = 0;
     virtual void interruptInferior() = 0;
 
@@ -96,8 +95,6 @@ public:
     virtual void reloadFullStack() = 0;
 
     virtual void watchPoint(const QPoint &) {}
-
-    virtual WatchModel *watchModel(int type) const = 0;
 };
 
 } // namespace Internal
diff --git a/src/plugins/debugger/script/scriptengine.cpp b/src/plugins/debugger/script/scriptengine.cpp
index 0096e3a414d..28d20a24cc2 100644
--- a/src/plugins/debugger/script/scriptengine.cpp
+++ b/src/plugins/debugger/script/scriptengine.cpp
@@ -185,13 +185,10 @@ void ScriptAgent::scriptUnload(qint64 scriptId)
 //
 ///////////////////////////////////////////////////////////////////////
 
-ScriptEngine::ScriptEngine(DebuggerManager *parent) :
-    q(parent),
-    qq(parent->engineInterface()),
-    m_models(qq->watchHandler())
+ScriptEngine::ScriptEngine(DebuggerManager *parent)
 {
-    connect(qq->watchHandler(), SIGNAL(watcherInserted(WatchData)), &m_models, SLOT(insertWatcher(WatchData)));
-    connect(&m_models, SIGNAL(watchDataUpdateNeeded(WatchData)), this, SLOT(updateWatchData(WatchData)));
+    q = parent;
+    qq = parent->engineInterface();
     m_scriptEngine = new QScriptEngine(this);
     m_scriptAgent = new ScriptAgent(this, m_scriptEngine);
     m_scriptEngine->setAgent(m_scriptAgent);
@@ -575,7 +572,7 @@ void ScriptEngine::maybeBreakNow(bool byFunction)
 void ScriptEngine::updateLocals()
 {
     QScriptContext *context = m_scriptEngine->currentContext();
-    m_models.beginCycle();
+    qq->watchHandler()->beginCycle();
     //SDEBUG("UPDATE LOCALS");
 
     //
@@ -607,7 +604,7 @@ void ScriptEngine::updateLocals()
     data.iname = "local";
     data.name = "local";
     data.scriptValue = context->activationObject();
-    m_models.insertData(data);
+    qq->watchHandler()->insertData(data);
 
     // FIXME: Use an extra thread. This here is evil
     m_stopped = true;
@@ -682,7 +679,7 @@ void ScriptEngine::updateSubItem(const WatchData &data0)
             data.setType("<unknown>");
             data.setValue("<unknown>");
         }
-        m_models.insertData(data);
+        qq->watchHandler()->insertData(data);
         return;
     }
 
@@ -700,13 +697,13 @@ void ScriptEngine::updateSubItem(const WatchData &data0)
                 data1.setChildrenNeeded();
             else
                 data1.setChildrenUnneeded();
-            m_models.insertData(data1);
+            qq->watchHandler()->insertData(data1);
             ++numChild;
         }
         //SDEBUG("  ... CHILDREN: " << numChild);
         data.setHasChildren(numChild > 0);
         data.setChildrenUnneeded();
-        m_models.insertData(data);
+        qq->watchHandler()->insertData(data);
         return;
     }
 
@@ -719,7 +716,7 @@ void ScriptEngine::updateSubItem(const WatchData &data0)
         }
         data.setHasChildren(numChild > 0);
         //SDEBUG("  ... CHILDCOUNT: " << numChild);
-        m_models.insertData(data);
+        qq->watchHandler()->insertData(data);
         return;
     }
 
diff --git a/src/plugins/debugger/script/scriptengine.h b/src/plugins/debugger/script/scriptengine.h
index bd49d0e1ef1..ae4a434efc0 100644
--- a/src/plugins/debugger/script/scriptengine.h
+++ b/src/plugins/debugger/script/scriptengine.h
@@ -49,7 +49,6 @@ class QScriptValue;
 QT_END_NAMESPACE
 
 #include "idebuggerengine.h"
-#include "asyncwatchmodel.h"
 
 namespace Debugger {
 namespace Internal {
@@ -108,20 +107,14 @@ private:
 
     bool supportsThreads() const { return true; }
     void maybeBreakNow(bool byFunction);
-
+    void updateWatchData(const WatchData &data);
     void updateLocals();
     void updateSubItem(const WatchData &data);
 
-    WatchModel *watchModel(int type) const { return m_models.model(type); }
-
-private slots:
-    void updateWatchData(const WatchData &data);
-
 private:
     friend class ScriptAgent;
     DebuggerManager *q;
     IDebuggerManagerAccessForEngines *qq;
-    AsyncWatchModelMixin m_models;
 
     QScriptEngine *m_scriptEngine;
     QString m_scriptContents;
diff --git a/src/plugins/debugger/tcf/tcfengine.cpp b/src/plugins/debugger/tcf/tcfengine.cpp
index 756f0d80289..b699f40954a 100644
--- a/src/plugins/debugger/tcf/tcfengine.cpp
+++ b/src/plugins/debugger/tcf/tcfengine.cpp
@@ -112,13 +112,11 @@ QString TcfEngine::TcfCommand::toString() const
 //
 ///////////////////////////////////////////////////////////////////////
 
-TcfEngine::TcfEngine(DebuggerManager *parent) :
-    q(parent),
-    qq(parent->engineInterface()),
-    m_models(qq->watchHandler())
+TcfEngine::TcfEngine(DebuggerManager *parent)
 {
-    connect(qq->watchHandler(), SIGNAL(watcherInserted(WatchData)), &m_models, SLOT(insertWatcher(WatchData)));
-    connect(&m_models, SIGNAL(watchDataUpdateNeeded(WatchData)), this, SLOT(updateWatchData(WatchData)));
+    q = parent;
+    qq = parent->engineInterface();
+
     m_congestion = 0;
     m_inAir = 0;
 
diff --git a/src/plugins/debugger/tcf/tcfengine.h b/src/plugins/debugger/tcf/tcfengine.h
index e09097df959..ff5844c436b 100644
--- a/src/plugins/debugger/tcf/tcfengine.h
+++ b/src/plugins/debugger/tcf/tcfengine.h
@@ -30,8 +30,6 @@
 #ifndef DEBUGGER_TCFENGINE_H
 #define DEBUGGER_TCFENGINE_H
 
-#include "asyncwatchmodel.h"
-
 #include <QtCore/QByteArray>
 #include <QtCore/QHash>
 #include <QtCore/QMap>
@@ -114,11 +112,10 @@ private:
 
     bool supportsThreads() const { return true; }
     void maybeBreakNow(bool byFunction);
+    void updateWatchData(const WatchData &data);
     void updateLocals();
     void updateSubItem(const WatchData &data);
 
-    WatchModel *watchModel(int type) const { return m_models.model(type); }
-
     Q_SLOT void socketConnected();
     Q_SLOT void socketDisconnected();
     Q_SLOT void socketError(QAbstractSocket::SocketError);
@@ -131,7 +128,6 @@ private:
 
 private:
     Q_SLOT void startDebugging();
-    Q_SLOT void updateWatchData(const WatchData &data);
 
     typedef void (TcfEngine::*TcfCommandCallback)
         (const JsonValue &record, const QVariant &cookie);
@@ -157,7 +153,7 @@ private:
     QHash<int, TcfCommand> m_cookieForToken;
 
     QQueue<TcfCommand> m_sendQueue;
-
+    
     // timer based congestion control. does not seem to work well.
     void enqueueCommand(const TcfCommand &command);
     Q_SLOT void handleSendTimer();
@@ -170,7 +166,6 @@ private:
 
     DebuggerManager *q;
     IDebuggerManagerAccessForEngines *qq;
-    AsyncWatchModelMixin m_models;
     QTcpSocket *m_socket;
     QByteArray m_inbuffer;
     QList<QByteArray> m_services;
diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp
index c33f8bcc486..bad769c7dbb 100644
--- a/src/plugins/debugger/watchhandler.cpp
+++ b/src/plugins/debugger/watchhandler.cpp
@@ -48,7 +48,6 @@
 #include <QtGui/QLabel>
 #include <QtGui/QToolTip>
 #include <QtGui/QTextEdit>
-#include <QtGui/QTreeView>
 
 #include <ctype.h>
 
@@ -68,13 +67,40 @@
 namespace Debugger {
 namespace Internal {
 
+static const QString strNotInScope =
+        QCoreApplication::translate("Debugger::Internal::WatchData", "<not in scope>");
+
 static int watcherCounter = 0;
+static int generationCounter = 0;
+
 ////////////////////////////////////////////////////////////////////
 //
-// WatchData
+// WatchItem
 //
 ////////////////////////////////////////////////////////////////////
 
+class WatchItem : public WatchData
+{
+public:
+    WatchItem() { parent = 0; fetchTriggered = false; }
+
+    WatchItem(const WatchData &data) : WatchData(data)
+        { parent = 0; fetchTriggered = false; }
+
+    void setData(const WatchData &data)
+        { static_cast<WatchData &>(*this) = data; }
+
+    WatchItem *parent;
+    bool fetchTriggered;      // children fetch has been triggered
+    QList<WatchItem *> children;  // fetched children
+};
+
+////////////////////////////////////////////////////////////////////
+//
+// WatchData
+//
+////////////////////////////////////////////////////////////////////
+   
 WatchData::WatchData() :
     hasChildren(false),
     generation(-1),
@@ -122,7 +148,7 @@ void WatchData::setValue(const QString &value0)
     // column. No need to duplicate it here.
     if (value.startsWith("(" + type + ") 0x"))
         value = value.section(" ", -1, -1);
-
+    
     setValueUnneeded();
 }
 
@@ -246,125 +272,109 @@ QString WatchData::toToolTip() const
     return res;
 }
 
-////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////
 //
-// WatchItem
+// WatchModel
 //
-////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////
 
-WatchItem::WatchItem() :
-    parent(0),
-    fetchTriggered(false)
+WatchModel::WatchModel(WatchHandler *handler, WatchType type)
+    : QAbstractItemModel(handler), m_handler(handler), m_type(type)
 {
-}
+    m_root = new WatchItem;
+    m_root->hasChildren = 1;
+    m_root->state = 0;
+    m_root->name = WatchHandler::tr("Root");
 
-WatchItem::WatchItem(const WatchData &data) :
-    WatchData(data),
-    parent(0),
-    fetchTriggered(false)
-{
-}
+    WatchItem *item = new WatchItem;
 
-void WatchItem::setData(const WatchData &data)
-{
-    static_cast<WatchData &>(*this) = data;
-}
+    switch (m_type) {
+        case LocalsWatch:
+            item->iname = QLatin1String("local");
+            item->name = WatchHandler::tr("Locals");
+            break;
+        case WatchersWatch:
+            item->iname = QLatin1String("watch");
+            item->name = WatchHandler::tr("Watchers");
+            break;
+        case TooltipsWatch:
+            item->iname = QLatin1String("tooltip");
+            item->name = WatchHandler::tr("Tooltip");
+            break;
+    }
+    item->hasChildren = true;
+    item->state = 0;
+    item->parent = m_root;
+    item->fetchTriggered = true;
 
-WatchItem::~WatchItem()
-{
-    qDeleteAll(children);
+    m_root->children.append(item);
 }
 
-void WatchItem::removeChildren()
+WatchItem *WatchModel::dummyRoot() const
 {
-    if (!children.empty()) {
-        qDeleteAll(children);
-        children.clear();
-    }
+    QTC_ASSERT(!m_root->children.isEmpty(), return 0);
+    return m_root->children.front();
 }
 
-void WatchItem::addChild(WatchItem *child)
+void WatchModel::reinitialize()
 {
-    children.push_back(child);
-    child->parent = this;
+    WatchItem *item = dummyRoot();
+    QTC_ASSERT(item, return);
+    QModelIndex index = watchIndex(item);
+    int n = item->children.size();
+    if (n == 0)
+        return;
+    //MODEL_DEBUG("REMOVING " << n << " CHILDREN OF " << item->iname);
+    beginRemoveRows(index, 0, n - 1);
+    qDeleteAll(item->children);
+    item->children.clear();
+    endRemoveRows();
 }
 
-///////////////////////////////////////////////////////////////////////
-//
-// WatchPredicate
-//
-///////////////////////////////////////////////////////////////////////
-
-WatchPredicate::WatchPredicate(Mode mode, const QString &pattern) :
-    m_pattern(pattern),
-    m_mode(mode)
+void WatchModel::removeOutdated()
 {
+    WatchItem *item = dummyRoot();
+    QTC_ASSERT(item, return);
+    foreach (WatchItem *child, item->children)
+        removeOutdatedHelper(child);
+#if DEBUG_MODEL
+#if USE_MODEL_TEST
+    //(void) new ModelTest(this, this);
+#endif
+#endif
 }
 
-bool WatchPredicate::operator()(const WatchData &w) const
+void WatchModel::removeOutdatedHelper(WatchItem *item)
 {
-    switch (m_mode) {
-        case INameMatch:
-        return m_pattern == w.iname;
-        case ExpressionMatch:
-        return m_pattern == w.exp;
+    if (item->generation < generationCounter)
+        removeItem(item);
+    else {
+        foreach (WatchItem *child, item->children)
+            removeOutdatedHelper(child);
+        item->fetchTriggered = false;
     }
-    return false;
-}
-
-///////////////////////////////////////////////////////////////////////
-//
-// WatchModel
-//
-///////////////////////////////////////////////////////////////////////
-
-WatchModel::WatchModel(WatchHandler *handler, WatchType type, QObject *parent) :
-    QAbstractItemModel(parent),
-    m_root(new WatchItem),
-    m_handler(handler),
-    m_type(type)
-{
-    WatchItem *dummyRoot = new WatchItem;
-
-    switch (type) {
-        case LocalsWatch:
-            dummyRoot->iname = QLatin1String("local");
-            dummyRoot->name = WatchHandler::tr("Locals");
-            break;
-        case WatchersWatch:
-            dummyRoot->iname = QLatin1String("watch");
-            dummyRoot->name = WatchHandler::tr("Watchers");
-            break;
-        case TooltipsWatch:
-            dummyRoot->iname = QLatin1String("tooltip");
-            dummyRoot->name = WatchHandler::tr("Tooltip");
-            break;
-        case WatchModelCount:
-            break;
-        }
-    dummyRoot->hasChildren = true;
-    dummyRoot->state = 0;
-
-    m_root->addChild(dummyRoot);
-
-    m_root->hasChildren = 1;
-    m_root->state = 0;
-    m_root->name = WatchHandler::tr("Root");
 }
 
-WatchModel::~WatchModel()
+void WatchModel::removeItem(WatchItem *item)
 {
-    delete m_root;
+    WatchItem *parent = item->parent;
+    QModelIndex index = watchIndex(parent);
+    int n = parent->children.indexOf(item);
+    //MODEL_DEBUG("NEED TO REMOVE: " << item->iname << "AT" << n);
+    beginRemoveRows(index, n, n);
+    parent->children.removeAt(n);
+    endRemoveRows();
 }
 
-QString WatchModel::parentName(const QString &iname)
+static QString parentName(const QString &iname)
 {
-    const int pos = iname.lastIndexOf(QLatin1Char('.'));
+    int pos = iname.lastIndexOf(QLatin1Char('.'));
     if (pos == -1)
         return QString();
     return iname.left(pos);
 }
 
+
 static QString chopConst(QString type)
 {
    while (1) {
@@ -409,7 +419,7 @@ QString niceType(const QString typeIn)
     for (int i = 0; i < 10; ++i) {
         int start = type.indexOf("std::allocator<");
         if (start == -1)
-            break;
+            break; 
         // search for matching '>'
         int pos;
         int level = 0;
@@ -517,10 +527,51 @@ static QString formattedValue(const WatchData &data,
     return data.value;
 }
 
-int WatchModel::columnCount(const QModelIndex &idx) const
+bool WatchModel::canFetchMore(const QModelIndex &index) const
 {
-    Q_UNUSED(idx);
-    return 3;
+    return index.isValid() && !watchItem(index)->fetchTriggered;
+}
+
+void WatchModel::fetchMore(const QModelIndex &index)
+{
+    QTC_ASSERT(index.isValid(), return);
+    QTC_ASSERT(!watchItem(index)->fetchTriggered, return);
+    if (WatchItem *item = watchItem(index)) {
+        item->fetchTriggered = true;
+        WatchData data = *item;
+        data.setChildrenNeeded();
+        emit m_handler->watchDataUpdateNeeded(data);
+    }
+}
+
+QModelIndex WatchModel::index(int row, int column, const QModelIndex &parent) const
+{
+    if (!hasIndex(row, column, parent))
+        return QModelIndex();
+
+    const WatchItem *item = watchItem(parent);
+    QTC_ASSERT(item, return QModelIndex());
+    return createIndex(row, column, (void*)(item->children.at(row)));
+}
+
+QModelIndex WatchModel::parent(const QModelIndex &idx) const
+{
+    if (!idx.isValid())
+        return QModelIndex();
+
+    const WatchItem *item = watchItem(idx);
+    if (!item->parent || item->parent == m_root)
+        return QModelIndex();
+
+    const WatchItem *grandparent = item->parent->parent;
+    if (!grandparent)
+        return QModelIndex();
+
+    for (int i = 0; i < grandparent->children.size(); ++i)
+        if (grandparent->children.at(i) == item->parent)
+            return createIndex(i, 0, (void*) item->parent);
+
+    return QModelIndex();
 }
 
 int WatchModel::rowCount(const QModelIndex &idx) const
@@ -532,18 +583,45 @@ int WatchModel::rowCount(const QModelIndex &idx) const
     return watchItem(idx)->children.size();
 }
 
-bool WatchModel::hasChildren(const QModelIndex &idx) const
+int WatchModel::columnCount(const QModelIndex &idx) const
 {
-    if (const WatchItem *item = watchItem(idx)) {
-        if (!item->children.empty())
-            return true;
-        QTC_ASSERT(item->isHasChildrenKnown(), return false);
-        return item->hasChildren;
+    Q_UNUSED(idx);
+    return 3;
+}
+
+bool WatchModel::hasChildren(const QModelIndex &parent) const
+{
+    WatchItem *item = watchItem(parent);
+    return !item || item->hasChildren;
+}
+
+WatchItem *WatchModel::watchItem(const QModelIndex &idx) const
+{
+    return idx.isValid() 
+        ? static_cast<WatchItem*>(idx.internalPointer()) : m_root;
+}
+
+QModelIndex WatchModel::watchIndex(const WatchItem *item) const
+{
+    return watchIndexHelper(item, m_root, QModelIndex());
+}
+
+QModelIndex WatchModel::watchIndexHelper(const WatchItem *needle, 
+    const WatchItem *parentItem, const QModelIndex &parentIndex) const
+{
+    if (needle == parentItem)
+        return parentIndex;
+    for (int i = parentItem->children.size(); --i >= 0; ) {
+        const WatchItem *childItem = parentItem->children.at(i);
+        QModelIndex childIndex = index(i, 0, parentIndex);
+        QModelIndex idx = watchIndexHelper(needle, childItem, childIndex);
+        if (idx.isValid())
+            return idx;
     }
-    return false;
+    return QModelIndex();
 }
 
-void WatchModel::emitDataChanged(int column, const QModelIndex &parentIndex)
+void WatchModel::emitDataChanged(int column, const QModelIndex &parentIndex) 
 {
     QModelIndex idx1 = index(0, column, parentIndex);
     QModelIndex idx2 = index(rowCount(parentIndex) - 1, column, parentIndex);
@@ -557,16 +635,11 @@ void WatchModel::emitDataChanged(int column, const QModelIndex &parentIndex)
 
 QVariant WatchModel::data(const QModelIndex &idx, int role) const
 {
-    if (const WatchData *wdata = watchItem(idx))
-        return data(*wdata, idx.column(), role);
-    return QVariant();
-}
+    const WatchItem &data = *watchItem(idx);
 
-QVariant WatchModel::data(const WatchData &data, int column, int role) const
-{
     switch (role) {
         case Qt::DisplayRole: {
-            switch (column) {
+            switch (idx.column()) {
                 case 0: return data.name;
                 case 1: return formattedValue(data,
                     m_handler->m_individualFormats[data.iname],
@@ -584,7 +657,7 @@ QVariant WatchModel::data(const WatchData &data, int column, int role) const
             static const QVariant red(QColor(200, 0, 0));
             static const QVariant black(QColor(0, 0, 0));
             static const QVariant gray(QColor(140, 140, 140));
-            switch (column) {
+            switch (idx.column()) {
                 case 0: return black;
                 case 1: return data.valuedisabled ? gray : data.changed ? red : black;
                 case 2: return black;
@@ -605,7 +678,7 @@ QVariant WatchModel::data(const WatchData &data, int column, int role) const
         case ActiveDataRole:
             qDebug() << "ASK FOR" << data.iname;
             return true;
-
+   
         case TypeFormatListRole:
             if (isIntType(data.type))
                 return QStringList() << tr("decimal") << tr("hexadecimal")
@@ -623,14 +696,14 @@ QVariant WatchModel::data(const WatchData &data, int column, int role) const
         }
 
         default:
-            break;
+            break; 
     }
     return QVariant();
 }
 
 bool WatchModel::setData(const QModelIndex &index, const QVariant &value, int role)
 {
-    WatchData &data = *watchItem(index);
+    WatchItem &data = *watchItem(index);
     if (role == ExpandedRole) {
         if (value.toBool())
             m_handler->m_expandedINames.insert(data.iname);
@@ -687,162 +760,75 @@ QVariant WatchModel::headerData(int section, Qt::Orientation orientation, int ro
             case 2: return QString(tr("Type")  + QLatin1String("     "));
         }
     }
-    return QVariant();
-}
-
-void WatchModel::setValueByIName(const QString &iname, const QString &value)
-{
-    if (WatchItem *wd = findItemByIName(iname, dummyRoot())) {
-        if (wd->value != value) {
-            wd->setValue(value);
-            const QModelIndex index = watchIndex(wd);
-            emit dataChanged(index.sibling(0, 1), index.sibling(0, 2));
-        }
-    }
+    return QVariant(); 
 }
 
-void WatchModel::setValueByExpression(const QString &exp, const QString &value)
+static bool iNameSorter(const WatchItem *item1, const WatchItem *item2)
 {
-    if (WatchItem *wd = findItemByExpression(exp, dummyRoot())) {
-        if (wd->value != value) {
-            wd->setValue(value);
-            const QModelIndex index = watchIndex(wd);
-            emit dataChanged(index.sibling(0, 1), index.sibling(0, 2));
-        }
+    QString name1 = item1->iname.section('.', -1);
+    QString name2 = item2->iname.section('.', -1);
+    if (!name1.isEmpty() && !name2.isEmpty()) {
+        if (name1.at(0).isDigit() && name2.at(0).isDigit())
+            return name1.toInt() < name2.toInt();
     }
+    return name1 < name2; 
 }
 
-WatchItem *WatchModel::root() const
+static int findInsertPosition(const QList<WatchItem *> &list, const WatchItem *item)
 {
-    return m_root;
+    QList<WatchItem *>::const_iterator it =
+        qLowerBound(list.begin(), list.end(), item, iNameSorter);
+    return it - list.begin(); 
 }
 
-WatchItem *WatchModel::dummyRoot() const
-{
-    if (!m_root->children.isEmpty())
-        return m_root->children.front();
-    return 0;
-}
-
-void WatchModel::reinitialize()
+void WatchModel::insertData(const WatchData &data)
 {
-    WatchItem *item = dummyRoot();
-    QTC_ASSERT(item, return);
-    const QModelIndex index = watchIndex(item);
-    const int n = item->children.size();
-    if (n == 0)
+    // qDebug() << "WMI:" << data.toString();
+    QTC_ASSERT(!data.iname.isEmpty(), return);
+    WatchItem *parent = findItem(parentName(data.iname), m_root);
+    if (!parent) {
+        WatchData parent;
+        parent.iname = parentName(data.iname);
+        insertData(parent);
+        //MODEL_DEBUG("\nFIXING MISSING PARENT FOR\n" << data.iname);
         return;
-    //MODEL_DEBUG("REMOVING " << n << " CHILDREN OF " << item->iname);
-    beginRemoveRows(index, 0, n - 1);
-    item->removeChildren();
-    endRemoveRows();
-}
-
-void WatchModel::removeItem(WatchItem *itemIn)
-{
-    WatchItem *item = static_cast<WatchItem *>(itemIn);
-    WatchItem *parent = item->parent;
-    const QModelIndex index = watchIndex(parent);
-    const int n = parent->children.indexOf(item);
-    //MODEL_DEBUG("NEED TO REMOVE: " << item->iname << "AT" << n);
-    beginRemoveRows(index, n, n);
-    parent->children.removeAt(n);
-    endRemoveRows();
-}
-
-QModelIndex WatchModel::index(int row, int column, const QModelIndex &parent) const
-{
-    if (!hasIndex(row, column, parent))
-        return QModelIndex();
-
-    const WatchItem *item = watchItem(parent);
-    QTC_ASSERT(item, return QModelIndex());
-    return createIndex(row, column, (void*)(item->children.at(row)));
-}
-
-QModelIndex WatchModel::parent(const QModelIndex &idx) const
-{
-    if (!idx.isValid())
-        return QModelIndex();
-
-    const WatchItem *item = static_cast<WatchItem *>(watchItem(idx));
-    if (!item->parent || item->parent == m_root)
-        return QModelIndex();
-
-    const WatchItem *grandparent = item->parent->parent;
-    if (!grandparent)
-        return QModelIndex();
-
-    for (int i = 0; i < grandparent->children.size(); ++i)
-        if (grandparent->children.at(i) == item->parent)
-            return createIndex(i, 0, (void*) item->parent);
-
-    return QModelIndex();
-}
-
-WatchItem *WatchModel::watchItem(const QModelIndex &idx) const
-
-{
-    return idx.isValid()
-            ? static_cast<WatchItem*>(idx.internalPointer()) : m_root;
-}
-
-QModelIndex WatchModel::watchIndex(const WatchItem *item) const
-{
-    return watchIndexHelper(item, m_root, QModelIndex());
-}
-
-QModelIndex WatchModel::watchIndexHelper(const WatchItem *needle,
-    const WatchItem *parentItem, const QModelIndex &parentIndex) const
-{
-    if (needle == parentItem)
-        return parentIndex;
-    for (int i = parentItem->children.size(); --i >= 0; ) {
-        const WatchItem *childItem = parentItem->children.at(i);
-        QModelIndex childIndex = index(i, 0, parentIndex);
-        QModelIndex idx = watchIndexHelper(needle, childItem, childIndex);
-        if (idx.isValid())
-            return idx;
     }
-    return QModelIndex();
+    QModelIndex index = watchIndex(parent);
+    if (WatchItem *oldItem = findItem(data.iname, parent)) {
+        // overwrite old entry
+        //MODEL_DEBUG("OVERWRITE : " << data.iname << data.value);
+        bool changed = !data.value.isEmpty()
+            && data.value != oldItem->value
+            && data.value != strNotInScope;
+        oldItem->setData(data);
+        oldItem->changed = changed;
+        oldItem->generation = generationCounter;
+        QModelIndex idx = watchIndex(oldItem);
+        emit dataChanged(idx, idx.sibling(idx.row(), 2));
+    } else {
+        // add new entry
+        //MODEL_DEBUG("INSERT : " << data.iname << data.value);
+        WatchItem *item = new WatchItem(data);
+        item->parent = parent;
+        item->generation = generationCounter;
+        item->changed = true;
+        int n = findInsertPosition(parent->children, item);
+        beginInsertRows(index, n, n);
+        parent->children.insert(n, item);
+        endInsertRows();
+    }
 }
 
-static WatchItem *findRecursion(WatchItem *root, const WatchPredicate &p)
+WatchItem *WatchModel::findItem(const QString &iname, WatchItem *root) const
 {
-    if (p(*root))
+    if (root->iname == iname)
         return root;
     for (int i = root->children.size(); --i >= 0; )
-        if (WatchItem *item = findRecursion(root->children.at(i), p))
+        if (WatchItem *item = findItem(iname, root->children.at(i)))
             return item;
     return 0;
 }
 
-WatchItem *WatchModel::findItemByExpression(const QString &exp, WatchItem *root) const
-{
-    return findRecursion(root, WatchPredicate(WatchPredicate::ExpressionMatch, exp));
-}
-
-WatchItem *WatchModel::findItemByIName(const QString &iname, WatchItem *root) const
-{
-    return findRecursion(root, WatchPredicate(WatchPredicate::INameMatch, iname));
-}
-
-static void debugItemRecursion(QDebug d, WatchItem *item, QString indent = QString())
-{
-    qDebug() << (indent + item->toString());
-    if (!item->children.isEmpty()) {
-        indent += QLatin1String("   ");
-        foreach(WatchItem *c, item->children)
-            debugItemRecursion(d, c, indent);
-    }
-}
-
-QDebug operator<<(QDebug d, const WatchModel &wm)
-{
-    if (WatchItem *root = wm.dummyRoot())
-        debugItemRecursion(d.nospace(), root);
-    return d;
-}
 
 ///////////////////////////////////////////////////////////////////////
 //
@@ -850,25 +836,34 @@ QDebug operator<<(QDebug d, const WatchModel &wm)
 //
 ///////////////////////////////////////////////////////////////////////
 
-WatchHandler::WatchHandler() :
-    m_expandPointers(true),
-    m_inChange(false)
+WatchHandler::WatchHandler()
 {
+    m_expandPointers = true;
+    m_inChange = false;
+
+    m_locals = new WatchModel(this, LocalsWatch);
+    m_watchers = new WatchModel(this, WatchersWatch);
+    m_tooltips = new WatchModel(this, TooltipsWatch);
+
     connect(theDebuggerAction(WatchExpression),
         SIGNAL(triggered()), this, SLOT(watchExpression()));
     connect(theDebuggerAction(RemoveWatchExpression),
         SIGNAL(triggered()), this, SLOT(removeWatchExpression()));
-    qFill(m_models, m_models + WatchModelCount, static_cast<WatchModel*>(0));
+}
+
+void WatchHandler::endCycle()
+{
+    m_locals->removeOutdated();
+    m_watchers->removeOutdated();
+    m_tooltips->removeOutdated();
 }
 
 void WatchHandler::cleanup()
 {
     m_expandedINames.clear();
     m_displayedINames.clear();
-    if (m_models[LocalsWatch])
-        m_models[LocalsWatch]->reinitialize();
-    if (m_models[TooltipsWatch])
-        m_models[TooltipsWatch]->reinitialize();
+    m_locals->reinitialize();
+    m_tooltips->reinitialize();
 #if 0
     for (EditWindows::ConstIterator it = m_editWindows.begin();
             it != m_editWindows.end(); ++it) {
@@ -879,12 +874,26 @@ void WatchHandler::cleanup()
 #endif
 }
 
+void WatchHandler::insertData(const WatchData &data)
+{
+    MODEL_DEBUG("INSERTDATA: " << data.toString());
+    QTC_ASSERT(data.isValid(), return);
+    if (data.isSomethingNeeded()) {
+        emit watchDataUpdateNeeded(data);
+    } else {
+        WatchModel *model = modelForIName(data.iname);
+        QTC_ASSERT(model, return);
+        model->insertData(data);
+    }
+}
+
 void WatchHandler::removeData(const QString &iname)
 {
     WatchModel *model = modelForIName(iname);
     if (!model)
         return;
-    if (WatchItem *item = model->findItemByIName(iname, model->root()))
+    WatchItem *item = model->findItem(iname, model->m_root);
+    if (item)
         model->removeItem(item);
 }
 
@@ -909,7 +918,7 @@ void WatchHandler::watchExpression(const QString &exp)
     if (exp.isEmpty() || exp == watcherEditPlaceHolder())
         data.setAllUnneeded();
     data.iname = watcherName(exp);
-    emit watcherInserted(data);
+    insertData(data);
     saveWatchers();
     //emit watchModelUpdateRequested();
 }
@@ -999,11 +1008,33 @@ void WatchHandler::removeWatchExpression(const QString &exp)
 {
     MODEL_DEBUG("REMOVE WATCH: " << exp);
     m_watcherNames.remove(exp);
-    if (WatchModel *model = m_models[WatchersWatch])
-        if (WatchItem *item = model->findItemByExpression(exp, model->root())) {
-            model->removeItem(item);
+    foreach (WatchItem *item, m_watchers->dummyRoot()->children) {
+        if (item->exp == exp) {
+            m_watchers->removeItem(item);
             saveWatchers();
+            break;
         }
+    }
+}
+
+void WatchHandler::beginCycle()
+{
+    ++generationCounter;
+    //m_locals->beginCycle();
+}
+
+void WatchHandler::updateWatchers()
+{
+    //qDebug() << "UPDATE WATCHERS";
+    // copy over all watchers and mark all watchers as incomplete
+    foreach (const QString &exp, m_watcherNames.keys()) {
+        WatchData data;
+        data.iname = watcherName(exp);
+        data.setAllNeeded();
+        data.name = exp;
+        data.exp = exp;
+        insertData(data);
+    }
 }
 
 void WatchHandler::loadWatchers()
@@ -1045,11 +1076,6 @@ void WatchHandler::loadTypeFormats()
     }
 }
 
-QStringList WatchHandler::watcherExpressions() const
-{
-    return m_watcherNames.keys();
-}
-
 void WatchHandler::saveTypeFormats()
 {
     QMap<QString, QVariant> typeFormats;
@@ -1073,61 +1099,44 @@ void WatchHandler::loadSessionData()
 {
     loadWatchers();
     loadTypeFormats();
-    initWatchModel();
-}
-
-void WatchHandler::initWatchModel()
-{
     foreach (const QString &exp, m_watcherNames.keys()) {
         WatchData data;
         data.iname = watcherName(exp);
         data.setAllUnneeded();
         data.name = exp;
         data.exp = exp;
-        emit watcherInserted(data);
+        insertData(data);
     }
 }
 
 WatchModel *WatchHandler::model(WatchType type) const
 {
-    return m_models[type];
-}
-
-void WatchHandler::setModel(WatchType type, WatchModel *model)
-{
-    if (m_models[type] == model)
-        return;
-    if (type == WatchersWatch && m_models[type])
-        saveWatchers();
-    m_models[type] = model;
-    if (type == WatchersWatch)
-        initWatchModel();
+    switch (type) {
+        case LocalsWatch: return m_locals;
+        case WatchersWatch: return m_watchers;
+        case TooltipsWatch: return m_tooltips;
+    }
+    QTC_ASSERT(false, /**/);
+    return 0;
 }
-
-WatchType WatchHandler::watchTypeOfIName(const QString &iname)
+    
+WatchModel *WatchHandler::modelForIName(const QString &iname) const
 {
     if (iname.startsWith(QLatin1String("local.")))
-        return LocalsWatch;
+        return m_locals;
     if (iname.startsWith(QLatin1String("watch.")))
-        return WatchersWatch;
+        return m_watchers;
     if (iname.startsWith(QLatin1String("tooltip")))
-        return TooltipsWatch;
-    return WatchModelCount;
-}
-
-WatchModel *WatchHandler::modelForIName(const QString &iname) const
-{
-    const WatchType t = watchTypeOfIName(iname);
-    if (t == WatchModelCount)
-        return 0;
-    return m_models[t];
+        return m_tooltips;
+    QTC_ASSERT(false, /**/);
+    return 0;
 }
 
 WatchData *WatchHandler::findItem(const QString &iname) const
 {
     const WatchModel *model = modelForIName(iname);
     QTC_ASSERT(model, return 0);
-    return model->findItemByIName(iname, model->root());
+    return model->findItem(iname, model->m_root);
 }
 
 QString WatchHandler::watcherEditPlaceHolder()
@@ -1140,55 +1149,9 @@ void WatchHandler::setFormat(const QString &type, int format)
 {
     m_typeFormats[type] = format;
     saveTypeFormats();
-    for (int m = 0; m < WatchModelCount; m++)
-        m_models[m]->emitDataChanged(1);
-}
-
-void WatchHandler::init(QTreeView *localsView)
-{
-    m_localsView = localsView;
-}
-
-void WatchHandler::saveLocalsViewState(int frame)
-{
-    WatchModel *model = m_models[LocalsWatch];
-    if (!model || !m_localsView)
-        return;
-    LocalsViewStateMap::iterator it = m_localsViewState.find(frame);
-    if (it == m_localsViewState.end())
-        it = m_localsViewState.insert(frame, LocalsViewState());
-
-    const QModelIndex topIndex = m_localsView->indexAt(QPoint(0, 0));
-    it.value().firstVisibleRow = topIndex.isValid() ? topIndex.row() : 0;
-    it.value().expandedINames = m_expandedINames;
-}
-
-void WatchHandler::restoreLocalsViewState(int frame)
-{
-    WatchModel *model = m_models[LocalsWatch];
-    if (!model || !m_localsView)
-        return;
-    int firstVisibleRow = 0;
-    const LocalsViewStateMap::const_iterator it = m_localsViewState.constFind(frame);
-    if (it !=  m_localsViewState.constEnd()) {
-        firstVisibleRow = it.value().firstVisibleRow;
-        m_expandedINames = it.value().expandedINames;
-    }
-    // Loop over and expand valid inames, purge out invalid.
-    WatchItem *root = model->root();
-    for (QSet<QString>::iterator it = m_expandedINames.begin(); it != m_expandedINames.end(); ) {
-        if (const WatchItem *wd = model->findItemByIName(*it, root)) {
-            m_localsView->expand(model->watchIndex(wd));
-            ++it;
-        } else {
-            it = m_expandedINames.erase(it);
-        }
-    }
-    if (firstVisibleRow) {
-        const QModelIndex index = model->index(0, 0).child(firstVisibleRow, 0);
-        if (index.isValid())
-            m_localsView->scrollTo(index, QAbstractItemView::PositionAtTop);
-    }
+    m_locals->emitDataChanged(1);
+    m_watchers->emitDataChanged(1);
+    m_tooltips->emitDataChanged(1);
 }
 
 } // namespace Internal
diff --git a/src/plugins/debugger/watchhandler.h b/src/plugins/debugger/watchhandler.h
index 4b472fab3f4..86e7dff3b07 100644
--- a/src/plugins/debugger/watchhandler.h
+++ b/src/plugins/debugger/watchhandler.h
@@ -32,21 +32,19 @@
 
 #include <QtCore/QPointer>
 #include <QtCore/QObject>
-#include <QtCore/QStringList>
 #include <QtCore/QHash>
 #include <QtCore/QSet>
-#include <QtCore/QAbstractItemModel>
+#include <QtGui/QStandardItem>
+#include <QtGui/QStandardItemModel>
+#include <QtGui/QTreeView>
 #include <QtScript/QScriptValue>
 
-QT_BEGIN_NAMESPACE
-class QTreeView;
-QT_END_NAMESPACE
-
 namespace Debugger {
 namespace Internal {
 
+class WatchItem;
 class WatchHandler;
-enum WatchType { LocalsWatch, WatchersWatch, TooltipsWatch, WatchModelCount };
+enum WatchType { LocalsWatch, WatchersWatch, TooltipsWatch };
 
 class WatchData
 {
@@ -162,95 +160,51 @@ enum DumpableFormat
     PlainFomat, 
 };
 
-class WatchHandler;
-
-// Item used by the model.
-class WatchItem : public WatchData
-{
-    Q_DISABLE_COPY(WatchItem)
-public:
-    WatchItem();
-    explicit WatchItem(const WatchData &data);
-
-    ~WatchItem();
-
-    void setData(const WatchData &data);
-    void addChild(WatchItem *child);
-    void removeChildren();
-
-    WatchItem *parent;
-    bool fetchTriggered;
-    QList<WatchItem*> children;
-};
-
-/* WatchModel: To be used by synchonous debuggers.
- * Implements all of WatchModel and provides new virtuals for
- * the debugger to complete items. */
-
 class WatchModel : public QAbstractItemModel
 {
     Q_OBJECT
-public:
-    explicit WatchModel(WatchHandler *handler, WatchType type, QObject *parent = 0);
-    virtual ~WatchModel();
-
-    virtual QModelIndex index(int, int, const QModelIndex &idx = QModelIndex()) const;
-
-    virtual int columnCount(const QModelIndex &idx= QModelIndex()) const;
-    virtual int rowCount(const QModelIndex &idx) const;
-    virtual bool hasChildren(const QModelIndex &idx) const;
-    virtual QVariant data(const QModelIndex &index, int role) const;
-    virtual bool setData(const QModelIndex &index, const QVariant &value, int role);
-
-    virtual Qt::ItemFlags flags(const QModelIndex &idx) const;
-    virtual QVariant headerData(int section, Qt::Orientation orientation,
-                                int role = Qt::DisplayRole) const;
 
-    virtual QModelIndex parent(const QModelIndex &idx) const;
+private:
+    explicit WatchModel(WatchHandler *handler, WatchType type);
+
+    QVariant data(const QModelIndex &index, int role) const;
+    bool setData(const QModelIndex &index, const QVariant &value, int role);
+    QModelIndex index(int, int, const QModelIndex &idx) const;
+    QModelIndex parent(const QModelIndex &idx) const;
+    int rowCount(const QModelIndex &idx) const;
+    int columnCount(const QModelIndex &idx) const;
+    bool hasChildren(const QModelIndex &idx) const;
+    Qt::ItemFlags flags(const QModelIndex &idx) const;
+    QVariant headerData(int section, Qt::Orientation orientation,
+        int role = Qt::DisplayRole) const;
+    bool canFetchMore(const QModelIndex &parent) const;
+    void fetchMore(const QModelIndex &parent);
+
+    friend class WatchHandler;
+    friend class GdbEngine;
 
     WatchItem *watchItem(const QModelIndex &) const;
     QModelIndex watchIndex(const WatchItem *needle) const;
     QModelIndex watchIndexHelper(const WatchItem *needle,
         const WatchItem *parentItem, const QModelIndex &parentIndex) const;
 
-    WatchItem *findItemByIName(const QString &iname, WatchItem *root) const;
-    WatchItem *findItemByExpression(const QString &iname, WatchItem *root) const;
+    void insertData(const WatchData &data);
+    WatchItem *findItem(const QString &iname, WatchItem *root) const;
     void reinitialize();
-
-    void removeItem(WatchItem *item);
-    WatchItem *root() const;
-
+    void removeOutdated();
+    void removeOutdatedHelper(WatchItem *item);
     WatchItem *dummyRoot() const;
+    void removeItem(WatchItem *item);
+    void setActiveData(const QString &data) { m_activeData = data; }
 
-    void setValueByIName(const QString &iname, const QString &value);
-    void setValueByExpression(const QString &iname, const QString &value);
-
-    void emitDataChanged(int column, const QModelIndex &parentIndex = QModelIndex());
-
-protected:
-    WatchHandler *handler() const { return m_handler; }
-    QVariant data(const WatchData &data, int column, int role) const;
-
-    static QString parentName(const QString &iname);
+    void emitDataChanged(int column,
+        const QModelIndex &parentIndex = QModelIndex());
 
 private:
-    WatchItem *m_root;
     WatchHandler *m_handler;
-    const WatchType m_type;
-};
-
-QDebug operator<<(QDebug d, const WatchModel &wm);
-
-/* A helper predicate for implementing model find routines */
-class WatchPredicate {
-public:
-    enum Mode { INameMatch, ExpressionMatch };
-    explicit WatchPredicate(Mode m, const QString &pattern);
-    bool operator()(const WatchData &w) const;
-
-private:
-    const QString &m_pattern;
-    const Mode m_mode;
+    WatchType m_type;
+    WatchItem *m_root;
+    QString m_activeData;
 };
 
 class WatchHandler : public QObject
@@ -259,25 +213,21 @@ class WatchHandler : public QObject
 
 public:
     WatchHandler();
-    void init(QTreeView *localsView);
-
     WatchModel *model(WatchType type) const;
-    static WatchType watchTypeOfIName(const QString &iname);
     WatchModel *modelForIName(const QString &data) const;
 
-    QStringList watcherExpressions() const;
-    QString watcherName(const QString &exp);
-
-    void setModel(WatchType type, WatchModel *model);
-
 //public slots:
     void cleanup();
     Q_SLOT void watchExpression(); // data in action->data().toString()
     Q_SLOT void watchExpression(const QString &exp);
     Q_SLOT void removeWatchExpression();
     Q_SLOT void removeWatchExpression(const QString &exp);
+    void beginCycle(); // called at begin of updateLocals() cycle
+    void updateWatchers(); // called after locals are fetched
+    void endCycle(); // called after all results have been received
     void showEditValue(const WatchData &data);
 
+    void insertData(const WatchData &data);
     void removeData(const QString &iname);
     WatchData *findItem(const QString &iname) const;
 
@@ -291,32 +241,18 @@ public:
     QSet<QString> expandedINames() const
         { return m_expandedINames; }
 
-    // For debuggers that clean out the locals models between frames:
-    // save/restore the expansion state.
-    Q_SLOT void restoreLocalsViewState(int frame = 0);
-    Q_SLOT void saveLocalsViewState(int frame = 0);
-
     static QString watcherEditPlaceHolder();
 
 signals:
-    void watcherInserted(const WatchData &data);
+    void watchDataUpdateNeeded(const WatchData &data);
     void sessionValueRequested(const QString &name, QVariant *value);
     void setSessionValueRequested(const QString &name, const QVariant &value);
 
 private:
-    friend class WatchModel; // needs formats, expanded inames
-
-    // Per stack-frame locals state
-    struct LocalsViewState {
-        LocalsViewState() : firstVisibleRow(0) {}
-        int firstVisibleRow;
-        QSet<QString> expandedINames;
-    };
-    typedef QMap<int, LocalsViewState> LocalsViewStateMap;
+    friend class WatchModel;
 
     void loadWatchers();
     void saveWatchers();
-    void initWatchModel();
 
     void loadTypeFormats();
     void saveTypeFormats();
@@ -329,16 +265,17 @@ private:
     EditWindows m_editWindows;
 
     QHash<QString, int> m_watcherNames;
+    QString watcherName(const QString &exp);
     QHash<QString, int> m_typeFormats;
     QHash<QString, int> m_individualFormats;
 
     void setDisplayedIName(const QString &iname, bool on);
     QSet<QString> m_expandedINames;  // those expanded in the treeview
     QSet<QString> m_displayedINames; // those with "external" viewers
-    LocalsViewStateMap m_localsViewState;
 
-    WatchModel *m_models[WatchModelCount];
-    QPointer<QTreeView> m_localsView;
+    WatchModel *m_locals;
+    WatchModel *m_watchers;
+    WatchModel *m_tooltips;
 };
 
 } // namespace Internal
diff --git a/src/plugins/debugger/watchutils.cpp b/src/plugins/debugger/watchutils.cpp
index 7eccb04cd9e..83486e899e9 100644
--- a/src/plugins/debugger/watchutils.cpp
+++ b/src/plugins/debugger/watchutils.cpp
@@ -554,22 +554,19 @@ QList<WatchData> QtDumperResult::toWatchData(int source) const
             }
             wchild.setType(dchild.type.isEmpty() ? childType : dchild.type);
             wchild.setAddress(dchild.address);
-            // Child overrides. Note that WatchData::setType sets
-            // childcount = 0 for some known types.
-            if (wchild.isHasChildrenNeeded()) {
-                const int effectiveChildChildCount = dchild.childCount == -1 ?  childChildCount : dchild.childCount;
-                switch (effectiveChildChildCount) {
+            // Child overrides.
+            const int effectiveChildChildCount = dchild.childCount == -1 ?  childChildCount : dchild.childCount;
+            switch (effectiveChildChildCount) {
                 case -1:
-                    wchild.setChildrenNeeded();
-                    wchild.setHasChildrenNeeded();
-                    break;
+                wchild.setChildrenNeeded();
+                wchild.setHasChildrenNeeded();
+                break;
                 case 0:
-                    wchild.setHasChildren(false);
-                    break;
+                wchild.setHasChildren(false);
+                break;
                 default:
-                    wchild.setHasChildren(true);
-                    break;
-                }
+                wchild.setHasChildren(true);
+                break;
             }
         }
     }
diff --git a/src/plugins/debugger/watchwindow.cpp b/src/plugins/debugger/watchwindow.cpp
index 73e9c2bf0b4..0df432ce179 100644
--- a/src/plugins/debugger/watchwindow.cpp
+++ b/src/plugins/debugger/watchwindow.cpp
@@ -327,11 +327,9 @@ void WatchWindow::editItem(const QModelIndex &idx)
     Q_UNUSED(idx); // FIXME
 }
 
-void WatchWindow::setModel(QAbstractItemModel *newModel)
+void WatchWindow::setModel(QAbstractItemModel *model)
 {
-    if (model() == newModel)
-        return;
-    QTreeView::setModel(newModel);
+    QTreeView::setModel(model);
 
     setRootIsDecorated(true);
     header()->setDefaultAlignment(Qt::AlignLeft);
@@ -339,7 +337,7 @@ void WatchWindow::setModel(QAbstractItemModel *newModel)
     if (m_type != LocalsType)
         header()->hide();
 
-    connect(newModel, SIGNAL(layoutChanged()), this, SLOT(resetHelper()));
+    connect(model, SIGNAL(layoutChanged()), this, SLOT(resetHelper()));
 }
 
 void WatchWindow::resetHelper()
-- 
GitLab