diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp
index 85310c37700d0a8e22ca1fb4cda0f63fe23b8521..83082853176b5c917ea8a5cd26b1b247e56ce588 100644
--- a/src/libs/cplusplus/ResolveExpression.cpp
+++ b/src/libs/cplusplus/ResolveExpression.cpp
@@ -235,6 +235,7 @@ void ResolveExpression::addResult(const FullySpecifiedType &ty, Symbol *symbol)
 void ResolveExpression::addResult(const Result &r)
 {
     Result p = r;
+
     if (! p.second)
         p.second = _context.symbol();
 
diff --git a/src/libs/cplusplus/ResolveExpression.h b/src/libs/cplusplus/ResolveExpression.h
index 1538f4c9931fff6735e60d043da9aa08065fcddc..f548e9a15c5f976f5886c088200a5ce661876f84 100644
--- a/src/libs/cplusplus/ResolveExpression.h
+++ b/src/libs/cplusplus/ResolveExpression.h
@@ -123,6 +123,7 @@ private:
     LookupContext _context;
     Semantic sem;
     QList<Result> _results;
+    Symbol *_declSymbol;
 };
 
 class CPLUSPLUS_EXPORT ResolveClass
diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp
index a74a322a6085ab46f4d52c834aa38917eb618abc..244369a1308148b4e2235885c75890a8fd56bf3a 100644
--- a/src/plugins/cppeditor/cppeditor.cpp
+++ b/src/plugins/cppeditor/cppeditor.cpp
@@ -32,6 +32,8 @@
 #include "cppplugin.h"
 #include "cpphighlighter.h"
 
+#include <cpptools/cpptoolsplugin.h>
+
 #include <AST.h>
 #include <Control.h>
 #include <Token.h>
@@ -46,6 +48,7 @@
 #include <SymbolVisitor.h>
 #include <TranslationUnit.h>
 #include <cplusplus/ExpressionUnderCursor.h>
+#include <cplusplus/TypeOfExpression.h>
 #include <cplusplus/LookupContext.h>
 #include <cplusplus/Overview.h>
 #include <cplusplus/OverviewModel.h>
@@ -827,6 +830,51 @@ void CPPEditor::reformatDocument()
     c.insertText(QString::fromUtf8(str.c_str(), str.length()));
 }
 
+void CPPEditor::findReferences()
+{
+    QTextCursor tc = textCursor();
+    m_currentRenameSelection = -1;
+
+    int line, col;
+    convertPosition(tc.position(), &line, &col);
+    ++col;
+
+    tc.movePosition(QTextCursor::EndOfWord);
+
+    ExpressionUnderCursor expressionUnderCursor;
+    const QString code = expressionUnderCursor(tc);
+    qDebug() << "code:" << code;
+
+    Snapshot snapshot = m_modelManager->snapshot();
+    Document::Ptr doc = snapshot.value(file()->fileName());
+
+    TypeOfExpression typeOfExpression;
+    typeOfExpression.setSnapshot(snapshot);
+
+    Symbol *lastVisibleSymbol = doc->findSymbolAt(line, col);
+
+    const QList<TypeOfExpression::Result> results = typeOfExpression(code, doc,
+                                                                     lastVisibleSymbol,
+                                                                     TypeOfExpression::Preprocess);
+
+    if (! results.isEmpty()) {
+        TypeOfExpression::Result result = results.first();
+        Symbol *symbol = result.second;
+        qDebug() << "result:" << symbol->fileName() << symbol->line() << symbol->column();
+        m_modelManager->findReferences(symbol);
+    }
+
+
+#if 0
+        LookupContext context(
+        Overview oo;
+        qDebug() << "==============> filename:" << symbol->fileName()
+                << "name:" << oo(symbol->name());
+        m_modelManager->findReferences(symbol);
+    }
+#endif
+}
+
 void CPPEditor::renameSymbolUnderCursor()
 {
     updateSemanticInfo(m_semanticHighlighter->semanticInfo(currentSource()));
diff --git a/src/plugins/cppeditor/cppeditor.h b/src/plugins/cppeditor/cppeditor.h
index 72e64a11e1dd1a499a06bf923890b82a274b8bcb..90663ed5f035833a4a292b748d3657f11105fa82 100644
--- a/src/plugins/cppeditor/cppeditor.h
+++ b/src/plugins/cppeditor/cppeditor.h
@@ -197,6 +197,7 @@ public Q_SLOTS:
     void switchDeclarationDefinition();
     void jumpToDefinition();
     void renameSymbolUnderCursor();
+    void findReferences();
 
     void moveToPreviousToken();
     void moveToNextToken();
diff --git a/src/plugins/cppeditor/cppeditorconstants.h b/src/plugins/cppeditor/cppeditorconstants.h
index 6b5260719ff60e1226a0664f03a570dbf23359eb..60fb2ff8edd10d07ce922e1858506cf5898b3721 100644
--- a/src/plugins/cppeditor/cppeditorconstants.h
+++ b/src/plugins/cppeditor/cppeditorconstants.h
@@ -39,6 +39,7 @@ const char * const C_CPPEDITOR  = "C++ Editor";
 const char * const CPPEDITOR_KIND = QT_TRANSLATE_NOOP("OpenWith::Editors", "C++ Editor");
 const char * const SWITCH_DECLARATION_DEFINITION = "CppEditor.SwitchDeclarationDefinition";
 const char * const RENAME_SYMBOL_UNDER_CURSOR = "CppEditor.RenameSymbolUnderCursor";
+const char * const FIND_REFERENCES = "CppEditor.FindReferences";
 const char * const JUMP_TO_DEFINITION = "CppEditor.JumpToDefinition";
 
 const char * const HEADER_FILE_TYPE = "CppHeaderFiles";
diff --git a/src/plugins/cppeditor/cppplugin.cpp b/src/plugins/cppeditor/cppplugin.cpp
index 9e267f889689a677c6cc8c522a006babda83ba66..504ed2490a7c18ddf77111275953afdd42d34a7c 100644
--- a/src/plugins/cppeditor/cppplugin.cpp
+++ b/src/plugins/cppeditor/cppplugin.cpp
@@ -220,6 +220,15 @@ bool CppPlugin::initialize(const QStringList & /*arguments*/, QString *errorMess
     am->actionContainer(CppEditor::Constants::M_CONTEXT)->addAction(cmd);
     am->actionContainer(CppTools::Constants::M_TOOLS_CPP)->addAction(cmd);
 
+    if (! qgetenv("QTCREATOR_REFERENCES").isEmpty()) {
+        QAction *findReferencesAction = new QAction(tr("Find References"), this);
+        cmd = am->registerAction(findReferencesAction,
+                                 Constants::FIND_REFERENCES, context);
+        connect(findReferencesAction, SIGNAL(triggered()), this, SLOT(findReferences()));
+        am->actionContainer(CppEditor::Constants::M_CONTEXT)->addAction(cmd);
+        am->actionContainer(CppTools::Constants::M_TOOLS_CPP)->addAction(cmd);
+    }
+
     m_actionHandler = new TextEditor::TextEditorActionHandler(CppEditor::Constants::C_CPPEDITOR,
         TextEditor::TextEditorActionHandler::Format
         | TextEditor::TextEditorActionHandler::UnCommentSelection
@@ -281,4 +290,12 @@ void CppPlugin::renameSymbolUnderCursor()
         editor->renameSymbolUnderCursor();
 }
 
+void CppPlugin::findReferences()
+{
+    Core::EditorManager *em = Core::EditorManager::instance();
+    CPPEditor *editor = qobject_cast<CPPEditor*>(em->currentEditor()->widget());
+    if (editor)
+        editor->findReferences();
+}
+
 Q_EXPORT_PLUGIN(CppPlugin)
diff --git a/src/plugins/cppeditor/cppplugin.h b/src/plugins/cppeditor/cppplugin.h
index 9d46a981f1b2a3b8da9a49269030803ed361dc5e..49e3afba5cb735f6b2b93a48dff3644abd614572 100644
--- a/src/plugins/cppeditor/cppplugin.h
+++ b/src/plugins/cppeditor/cppplugin.h
@@ -74,6 +74,7 @@ private slots:
     void switchDeclarationDefinition();
     void jumpToDefinition();
     void renameSymbolUnderCursor();
+    void findReferences();
 
 private:
     Core::IEditor *createEditor(QWidget *parent);
diff --git a/src/plugins/cpptools/cppfindreferences.cpp b/src/plugins/cpptools/cppfindreferences.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4dc797704a8cc31e06f1aaa4ec3b5c9d06d72bfe
--- /dev/null
+++ b/src/plugins/cpptools/cppfindreferences.cpp
@@ -0,0 +1,295 @@
+/**************************************************************************
+**
+** 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 "cppfindreferences.h"
+#include "cppmodelmanager.h"
+#include "cpptoolsconstants.h"
+
+#include <texteditor/basetexteditor.h>
+#include <find/searchresultwindow.h>
+#include <extensionsystem/pluginmanager.h>
+#include <utils/filesearch.h>
+#include <coreplugin/progressmanager/progressmanager.h>
+#include <coreplugin/icore.h>
+
+#include <ASTVisitor.h>
+#include <AST.h>
+#include <Control.h>
+#include <Literals.h>
+#include <TranslationUnit.h>
+#include <Symbols.h>
+
+#include <cplusplus/CppDocument.h>
+#include <cplusplus/ExpressionUnderCursor.h>
+#include <cplusplus/ResolveExpression.h>
+
+#include <QtCore/QTime>
+#include <QtCore/QtConcurrentRun>
+#include <QtCore/QDir>
+
+#include <qtconcurrent/runextensions.h>
+
+using namespace CppTools::Internal;
+using namespace CPlusPlus;
+
+namespace {
+
+struct Process: protected ASTVisitor
+{
+public:
+    Process(QFutureInterface<Core::Utils::FileSearchResult> &future,
+            Document::Ptr doc, const Snapshot &snapshot)
+            : ASTVisitor(doc->control()),
+              _future(future),
+              _doc(doc),
+              _snapshot(snapshot),
+              _source(_doc->source())
+    { }
+
+    void operator()(Identifier *id, AST *ast)
+    {
+        _id = id;
+        _currentSymbol = _doc->globalNamespace();
+        _exprDoc = Document::create("<references>");
+        accept(ast);
+    }
+
+protected:
+    using ASTVisitor::visit;
+
+    QString matchingLine(const Token &tk) const
+    {
+        const char *beg = _source.constData();
+        const char *cp = beg + tk.offset;
+        for (; cp != beg - 1; --cp) {
+            if (*cp == '\n')
+                break;
+        }
+
+        ++cp;
+
+        const char *lineEnd = cp + 1;
+        for (; *lineEnd; ++lineEnd) {
+            if (*lineEnd == '\n')
+                break;
+        }
+
+        const QString matchingLine = QString::fromUtf8(cp, lineEnd - cp);
+        return matchingLine;
+
+    }
+
+    void reportResult(unsigned tokenIndex)
+    {
+        const Token &tk = tokenAt(tokenIndex);
+        const QString lineText = matchingLine(tk);
+
+        unsigned line, col;
+        getTokenStartPosition(tokenIndex, &line, &col);
+
+        if (col)
+            --col;  // adjust the column position.
+
+        int len = tk.f.length;
+
+        _future.reportResult(Core::Utils::FileSearchResult(QDir::toNativeSeparators(_doc->fileName()),
+                                                           line, lineText, col, len));
+    }
+
+    LookupContext currentContext() const
+    {
+        return LookupContext(_currentSymbol, _exprDoc, _doc, _snapshot);
+    }
+
+    virtual bool visit(ClassSpecifierAST *ast)
+    {
+        _currentSymbol = ast->symbol;
+        return true;
+    }
+
+    virtual bool visit(NamespaceAST *ast)
+    {
+        _currentSymbol = ast->symbol;
+        return true;
+    }
+
+    virtual bool visit(CompoundStatementAST *ast)
+    {
+        _currentSymbol = ast->symbol;
+        return true;
+    }
+
+    virtual bool visit(FunctionDefinitionAST *ast)
+    {
+        _currentSymbol = ast->symbol;
+        return true;
+    }
+
+    virtual bool visit(QualifiedNameAST *ast)
+    {
+        return true;
+    }
+
+    virtual bool visit(SimpleNameAST *ast)
+    {
+        Identifier *id = identifier(ast->identifier_token);
+        if (id == _id) {
+#if 0
+            LookupContext context = currentContext();
+            ResolveExpression resolveExpression(context);
+            QList<ResolveExpression::Result> results = resolveExpression(ast);
+            if (! results.isEmpty()) {
+                ResolveExpression::Result result = results.first();
+                Symbol *resolvedSymbol = result.second;
+                qDebug() << "resolves to:" << resolvedSymbol->fileName() << resolvedSymbol->line();
+            }
+#endif
+            reportResult(ast->identifier_token);
+        }
+
+        return false;
+    }
+
+    virtual bool visit(TemplateIdAST *ast)
+    {
+        Identifier *id = identifier(ast->identifier_token);
+        if (id == _id)
+            reportResult(ast->identifier_token);
+
+        return true;
+    }
+
+private:
+    QFutureInterface<Core::Utils::FileSearchResult> &_future;
+    Identifier *_id;
+    Document::Ptr _doc;
+    Snapshot _snapshot;
+    QByteArray _source;
+    Symbol *_currentSymbol;
+    Document::Ptr _exprDoc;
+};
+
+} // end of anonymous namespace
+
+CppFindReferences::CppFindReferences(CppModelManager *modelManager)
+    : _modelManager(modelManager),
+      _resultWindow(ExtensionSystem::PluginManager::instance()->getObject<Find::SearchResultWindow>())
+{
+    m_watcher.setPendingResultsLimit(1);
+    connect(&m_watcher, SIGNAL(resultReadyAt(int)), this, SLOT(displayResult(int)));
+    connect(&m_watcher, SIGNAL(finished()), this, SLOT(searchFinished()));
+}
+
+CppFindReferences::~CppFindReferences()
+{
+}
+
+static void find_helper(QFutureInterface<Core::Utils::FileSearchResult> &future,
+                        QString word,
+                        QString fileName,
+                        Snapshot snapshot)
+{
+    QTime tm;
+    tm.start();
+    QStringList files(fileName);
+    files += snapshot.dependsOn(fileName);
+    qDebug() << "done in:" << tm.elapsed() << "number of files to parse:" << files.size();
+
+    future.setProgressRange(0, files.size());
+
+    const QByteArray literal = word.toLatin1();
+
+    tm.start();
+    for (int i = 0; i < files.size(); ++i) {
+        const QString &fn = files.at(i);
+        future.setProgressValueAndText(i, QFileInfo(fn).fileName());
+        QFile f(fn);
+        if (! f.open(QFile::ReadOnly))
+            continue;
+
+        const QString source = QTextStream(&f).readAll();
+        const QByteArray preprocessedCode = snapshot.preprocessedCode(source, fn);
+        Document::Ptr doc = snapshot.documentFromSource(preprocessedCode, fn);
+        doc->tokenize();
+
+        Control *control = doc->control();
+        if (Identifier *id = control->findIdentifier(literal.constData(), literal.size())) {
+            doc->check();
+            TranslationUnit *unit = doc->translationUnit();
+            Process process(future, doc, snapshot);
+            process(id, unit->ast());
+        }
+    }
+    future.setProgressValue(files.size());
+}
+
+void CppFindReferences::findAll(const QString &fileName, const QString &text)
+{
+    _resultWindow->clearContents();
+    _resultWindow->popup(true);
+
+    Core::ProgressManager *progressManager = Core::ICore::instance()->progressManager();
+
+    const Snapshot snapshot = _modelManager->snapshot();
+
+    QFuture<Core::Utils::FileSearchResult> result =
+            QtConcurrent::run(&find_helper, text, fileName, snapshot);
+
+    m_watcher.setFuture(result);
+
+    Core::FutureProgress *progress = progressManager->addTask(result, tr("Searching..."),
+                                                              CppTools::Constants::TASK_SEARCH,
+                                                              Core::ProgressManager::CloseOnSuccess);
+
+    connect(progress, SIGNAL(clicked()), _resultWindow, SLOT(popup()));
+}
+
+void CppFindReferences::displayResult(int index)
+{
+    Core::Utils::FileSearchResult result = m_watcher.future().resultAt(index);
+    Find::ResultWindowItem *item = _resultWindow->addResult(result.fileName,
+                                                            result.lineNumber,
+                                                            result.matchingLine,
+                                                            result.matchStart,
+                                                            result.matchLength);
+    if (item)
+        connect(item, SIGNAL(activated(const QString&,int,int)),
+                this, SLOT(openEditor(const QString&,int,int)));
+}
+
+void CppFindReferences::searchFinished()
+{
+    emit changed();
+}
+
+void CppFindReferences::openEditor(const QString &fileName, int line, int column)
+{
+    TextEditor::BaseTextEditor::openEditorAt(fileName, line, column);
+}
+
diff --git a/src/plugins/cpptools/cppfindreferences.h b/src/plugins/cpptools/cppfindreferences.h
new file mode 100644
index 0000000000000000000000000000000000000000..1bd2ec62aa76fb180d926c2ff87d36d46fe6fea1
--- /dev/null
+++ b/src/plugins/cpptools/cppfindreferences.h
@@ -0,0 +1,81 @@
+/**************************************************************************
+**
+** 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 CPPFINDREFERENCES_H
+#define CPPFINDREFERENCES_H
+
+#include <QtCore/QObject>
+#include <QtCore/QPointer>
+#include <QtCore/QFuture>
+#include <QtCore/QFutureWatcher>
+
+namespace Core {
+namespace Utils {
+    class FileSearchResult;
+} // end of namespace Utils
+} // end of namespace Core
+
+namespace Find {
+class SearchResultWindow;
+} // end of namespace Find
+
+namespace CppTools {
+namespace Internal {
+
+class CppModelManager;
+
+class CppFindReferences: public QObject
+{
+    Q_OBJECT
+
+public:
+    CppFindReferences(CppModelManager *modelManager);
+    virtual ~CppFindReferences();
+
+Q_SIGNALS:
+    void changed();
+
+public:
+    void findAll(const QString &fileName, const QString &text);
+
+private Q_SLOTS:
+    void displayResult(int);
+    void searchFinished();
+    void openEditor(const QString&, int, int);
+
+private:
+    QPointer<CppModelManager> _modelManager;
+    Find::SearchResultWindow *_resultWindow;
+    QFutureWatcher<Core::Utils::FileSearchResult> m_watcher;
+};
+
+} // end of namespace Internal
+} // end of namespace CppTools
+
+#endif // CPPFINDREFERENCES_H
diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp
index 77b88f6f9ba9c39992f1d5f66ec09a564ba04b71..6c2ffd35ddbd7620bdd55ec57d9fa9434323c132 100644
--- a/src/plugins/cpptools/cppmodelmanager.cpp
+++ b/src/plugins/cpptools/cppmodelmanager.cpp
@@ -35,6 +35,7 @@
 #include "cppmodelmanager.h"
 #include "cpptoolsconstants.h"
 #include "cpptoolseditorsupport.h"
+#include "cppfindreferences.h"
 
 #include <functional>
 #include <QtConcurrentRun>
@@ -579,6 +580,8 @@ Document::Ptr CppPreprocessor::switchDocument(Document::Ptr doc)
 CppModelManager::CppModelManager(QObject *parent)
     : CppModelManagerInterface(parent)
 {
+    m_findReferences = new CppFindReferences(this);
+
     m_revision = 0;
     m_synchronizer.setCancelOnWait(true);
 
@@ -715,6 +718,14 @@ void CppModelManager::removeEditorSupport(AbstractEditorSupport *editorSupport)
     m_addtionalEditorSupport.remove(editorSupport);
 }
 
+void CppModelManager::findReferences(CPlusPlus::Symbol *symbol)
+{
+    if (Identifier *id = symbol->identifier()) {
+        QString word = QString::fromLatin1(id->chars(), id->size());
+        m_findReferences->findAll(symbol->fileName(), word);
+    }
+}
+
 QMap<QString, QString> CppModelManager::buildWorkingCopyList()
 {
     QMap<QString, QString> workingCopy;
diff --git a/src/plugins/cpptools/cppmodelmanager.h b/src/plugins/cpptools/cppmodelmanager.h
index 09d97593d7bebf51236882586c5b3d48e6f86bbf..69e627a452620c39805bdc5c93e837e6e20ffe78 100644
--- a/src/plugins/cpptools/cppmodelmanager.h
+++ b/src/plugins/cpptools/cppmodelmanager.h
@@ -62,6 +62,7 @@ namespace Internal {
 
 class CppEditorSupport;
 class CppPreprocessor;
+class CppFindReferences;
 
 class CppModelManager : public CppModelManagerInterface
 {
@@ -101,6 +102,8 @@ public:
     virtual void addEditorSupport(AbstractEditorSupport *editorSupport);
     virtual void removeEditorSupport(AbstractEditorSupport *editorSupport);
 
+    virtual void findReferences(CPlusPlus::Symbol *symbol);
+
     void setHeaderSuffixes(const QStringList &suffixes)
     { m_headerSuffixes = suffixes; }
 
@@ -205,6 +208,8 @@ private:
 
     QFutureSynchronizer<void> m_synchronizer;
     unsigned m_revision;
+
+    CppFindReferences *m_findReferences;
 };
 
 } // namespace Internal
diff --git a/src/plugins/cpptools/cppmodelmanagerinterface.h b/src/plugins/cpptools/cppmodelmanagerinterface.h
index 996b9b6621d07aa15b3c7b42ae56bfbcb5e2a082..55b095b89fe21dee56b4aa7fe8ec37aecb9ad2a6 100644
--- a/src/plugins/cpptools/cppmodelmanagerinterface.h
+++ b/src/plugins/cpptools/cppmodelmanagerinterface.h
@@ -94,6 +94,8 @@ public:
 
     virtual void addEditorSupport(AbstractEditorSupport *editorSupport) = 0;
     virtual void removeEditorSupport(AbstractEditorSupport *editorSupport) = 0;
+
+    virtual void findReferences(CPlusPlus::Symbol *symbol) = 0;
 };
 
 class CPPTOOLS_EXPORT AbstractEditorSupport
diff --git a/src/plugins/cpptools/cpptools.pro b/src/plugins/cpptools/cpptools.pro
index 44244feb633e86762fb2e0fb7bd9d5bf8611873b..00e335432fd26216e7a0ed9478530d6f2af6d38f 100644
--- a/src/plugins/cpptools/cpptools.pro
+++ b/src/plugins/cpptools/cpptools.pro
@@ -23,7 +23,8 @@ HEADERS += completionsettingspage.h \
     searchsymbols.h \
     cppdoxygen.h \
     cppfilesettingspage.h \
-    cppsemanticsearch.h
+    cppsemanticsearch.h \
+    cppfindreferences.h
 
 SOURCES += completionsettingspage.cpp \
     cppclassesfilter.cpp \
@@ -38,7 +39,8 @@ SOURCES += completionsettingspage.cpp \
     cppdoxygen.cpp \
     cppfilesettingspage.cpp \
     abstracteditorsupport.cpp \
-    cppsemanticsearch.cpp
+    cppsemanticsearch.cpp \
+    cppfindreferences.cpp
 
 FORMS += completionsettingspage.ui \
     cppfilesettingspage.ui
diff --git a/src/plugins/cpptools/cpptoolsconstants.h b/src/plugins/cpptools/cpptoolsconstants.h
index 3e7708522b3accd7e0a2010d8318842326882063..26fceb9125807d631ecc02f4f6b837dc0898a6e1 100644
--- a/src/plugins/cpptools/cpptoolsconstants.h
+++ b/src/plugins/cpptools/cpptoolsconstants.h
@@ -38,6 +38,7 @@ namespace Constants {
 const char * const M_TOOLS_CPP              = "CppTools.Tools.Menu";
 const char * const SWITCH_HEADER_SOURCE     = "CppTools.SwitchHeaderSource";
 const char * const TASK_INDEX               = "CppTools.Task.Index";
+const char * const TASK_SEARCH              = "CppTools.Task.Search";
 const char * const C_SOURCE_MIMETYPE = "text/x-csrc";
 const char * const C_HEADER_MIMETYPE = "text/x-chdr";
 const char * const CPP_SOURCE_MIMETYPE = "text/x-c++src";
diff --git a/src/plugins/debugger/breakhandler.cpp b/src/plugins/debugger/breakhandler.cpp
index af0af2911739972bb8641224e70773aa148aa4ff..a24f53f8e7daa948ed54334d8e4e3a8c292aa786 100644
--- a/src/plugins/debugger/breakhandler.cpp
+++ b/src/plugins/debugger/breakhandler.cpp
@@ -29,6 +29,7 @@
 
 #include "breakhandler.h"
 
+#include "debuggeractions.h"
 #include "debuggermanager.h"
 #include "stackframe.h"
 
@@ -507,7 +508,8 @@ QVariant BreakHandler::data(const QModelIndex &mi, int role) const
             break;
     }
     if (role == Qt::ToolTipRole)
-        return data->toToolTip();
+        return theDebuggerBoolSetting(UseToolTipsInLocalsView)
+                ? data->toToolTip() : QVariant();
     return QVariant();
 }
 
diff --git a/src/plugins/debugger/cdb/cdbdebugengine.cpp b/src/plugins/debugger/cdb/cdbdebugengine.cpp
index 853a774bb2c08ef0fa39c34903578373fc3cfcc1..b4e9f6fd67b90dfbcf0291fb7179ce46a735a2a2 100644
--- a/src/plugins/debugger/cdb/cdbdebugengine.cpp
+++ b/src/plugins/debugger/cdb/cdbdebugengine.cpp
@@ -1685,25 +1685,21 @@ bool CdbDebugEnginePrivate::setSymbolPaths(const QStringList &s, QString *errorM
     return true;
 }
 
-} // namespace Internal
-} // namespace Debugger
-
 // Accessed by DebuggerManager
-Debugger::Internal::IDebuggerEngine *createWinEngine(Debugger::Internal::DebuggerManager *parent,
-                                                     bool cmdLineEnabled,
-                                                     QList<Core::IOptionsPage*> *opts)
+IDebuggerEngine *createWinEngine(DebuggerManager *parent,
+                                 bool cmdLineEnabled,
+                                 QList<Core::IOptionsPage*> *opts)
 {
     // Create options page
-    QSharedPointer<Debugger::Internal::CdbOptions> options(new Debugger::Internal::CdbOptions);
+    QSharedPointer<CdbOptions> options(new CdbOptions);
     options->fromSettings(Core::ICore::instance()->settings());
-    Debugger::Internal::CdbOptionsPage *optionsPage = new Debugger::Internal::CdbOptionsPage(options);
+    CdbOptionsPage *optionsPage = new CdbOptionsPage(options);
     opts->push_back(optionsPage);
     if (!cmdLineEnabled || !options->enabled)
         return 0;
     // Create engine
     QString errorMessage;
-    Debugger::Internal::IDebuggerEngine *engine =
-            Debugger::Internal::CdbDebugEngine::create(parent, options, &errorMessage);
+    IDebuggerEngine *engine = CdbDebugEngine::create(parent, options, &errorMessage);
     if (!engine) {
         optionsPage->setFailureMessage(errorMessage);
         qWarning("%s\n" ,qPrintable(errorMessage));
@@ -1711,3 +1707,7 @@ Debugger::Internal::IDebuggerEngine *createWinEngine(Debugger::Internal::Debugge
     QObject::connect(optionsPage, SIGNAL(debuggerPathsChanged()), engine, SLOT(syncDebuggerPaths()));
     return engine;
 }
+
+} // namespace Internal
+} // namespace Debugger
+
diff --git a/src/plugins/debugger/commonoptionspage.ui b/src/plugins/debugger/commonoptionspage.ui
index 249ccaca91796341f56fb1df4784116aeca92e54..245515805971b54763a611bb9c919fce3fab3d82 100644
--- a/src/plugins/debugger/commonoptionspage.ui
+++ b/src/plugins/debugger/commonoptionspage.ui
@@ -53,12 +53,22 @@
        </widget>
       </item>
       <item>
-       <widget class="QCheckBox" name="checkBoxUseToolTips">
+       <widget class="QCheckBox" name="checkBoxUseToolTipsInMainEditor">
         <property name="toolTip">
          <string>Checking this will enable tooltips for variable values during debugging. Since this can slow down debugging and does not provide reliable information as it does not use scope information, it is switched off by default.</string>
         </property>
         <property name="text">
-         <string>Use tooltips while debugging</string>
+         <string>Use tooltips in locals view while debugging</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QCheckBox" name="checkBoxUseToolTipsInLocalsView">
+        <property name="toolTip">
+         <string>Checking this will enable tooltips for in the locals view during debugging.</string>
+        </property>
+        <property name="text">
+         <string>Use tooltips in main editor while debugging</string>
         </property>
        </widget>
       </item>
diff --git a/src/plugins/debugger/debuggeractions.cpp b/src/plugins/debugger/debuggeractions.cpp
index d13e3559af87d9c286993e8e415737b16681e754..2c98c9f7c9ebb915ec3ca78b8f942d4fb265185e 100644
--- a/src/plugins/debugger/debuggeractions.cpp
+++ b/src/plugins/debugger/debuggeractions.cpp
@@ -254,10 +254,17 @@ DebuggerSettings *DebuggerSettings::instance()
 
     item = new SavedAction(instance);
     item->setSettingsKey(debugModeGroup, QLatin1String("UseToolTips"));
-    item->setText(tr("Use tooltips when debugging"));
+    item->setText(tr("Use tooltips in main editor when debugging"));
     item->setCheckable(true);
     item->setDefaultValue(false);
-    instance->insertItem(UseToolTips, item);
+    instance->insertItem(UseToolTipsInMainEditor, item);
+
+    item = new SavedAction(instance);
+    item->setSettingsKey(debugModeGroup, QLatin1String("UseToolTipsInLocalsView"));
+    item->setText(tr("Use tooltips in locals view when debugging"));
+    item->setCheckable(true);
+    item->setDefaultValue(false);
+    instance->insertItem(UseToolTipsInLocalsView, item);
 
     item = new SavedAction(instance);
     item->setSettingsKey(debugModeGroup, QLatin1String("ListSourceFiles"));
diff --git a/src/plugins/debugger/debuggeractions.h b/src/plugins/debugger/debuggeractions.h
index 6d9656ffce07227754f4747a95ed2c0c8f9eb86b..07cac69e80bc32423f72ce0935b10444f35a500c 100644
--- a/src/plugins/debugger/debuggeractions.h
+++ b/src/plugins/debugger/debuggeractions.h
@@ -100,7 +100,8 @@ enum DebuggerActionCode
     WatchExpressionInWindow,
     RemoveWatchExpression,
     WatchPoint,
-    UseToolTips,
+    UseToolTipsInMainEditor,
+    UseToolTipsInLocalsView,
     AssignValue,
     AssignType,
 
diff --git a/src/plugins/debugger/debuggerdialogs.cpp b/src/plugins/debugger/debuggerdialogs.cpp
index 3612802085077e495940b9f27873ce2cd84345ac..4796a9b0f19b77b42d2cbbd856472e6861205c38 100644
--- a/src/plugins/debugger/debuggerdialogs.cpp
+++ b/src/plugins/debugger/debuggerdialogs.cpp
@@ -248,6 +248,7 @@ AttachExternalDialog::AttachExternalDialog(QWidget *parent)
     QPushButton *refreshButton = new QPushButton(tr("Refresh"));
     connect(refreshButton, SIGNAL(clicked()), this, SLOT(rebuildProcessList()));
     m_ui->buttonBox->addButton(refreshButton, QDialogButtonBox::ActionRole);
+    m_ui->filterLineEdit->setFocus(Qt::TabFocusReason);
 
     // Do not use activated, will be single click in Oxygen
     connect(m_ui->procView, SIGNAL(doubleClicked(QModelIndex)),
diff --git a/src/plugins/debugger/debuggermanager.cpp b/src/plugins/debugger/debuggermanager.cpp
index 8c5c75fdb2d2b12e0189781f9b48bf11ca8c9569..903407750c0d3d1e315c2289d43165ff0442b704 100644
--- a/src/plugins/debugger/debuggermanager.cpp
+++ b/src/plugins/debugger/debuggermanager.cpp
@@ -82,11 +82,17 @@
 #include <QtGui/QToolButton>
 #include <QtGui/QToolTip>
 
+namespace Debugger {
+namespace Internal {
 
-// The creation functions take a list of options pages they can add to.
-// This allows for having a "enabled" toggle on the page indepently
-// of the engine.
-using namespace Debugger::Internal;
+IDebuggerEngine *createGdbEngine(DebuggerManager *parent);
+IDebuggerEngine *createScriptEngine(DebuggerManager *parent);
+IDebuggerEngine *createTcfEngine(DebuggerManager *parent);
+
+// The createWinEngine function takes a list of options pages it can add to.
+// This allows for having a "enabled" toggle on the page independently
+// of the engine. That's good for not enabling the related ActiveX control
+// unnecessarily.
 
 IDebuggerEngine *createWinEngine(DebuggerManager *, bool /* cmdLineEnabled */, QList<Core::IOptionsPage*> *)
 #ifdef CDB_ENABLED
@@ -94,14 +100,6 @@ IDebuggerEngine *createWinEngine(DebuggerManager *, bool /* cmdLineEnabled */, Q
 #else
 { return 0; }
 #endif
-IDebuggerEngine *createScriptEngine(DebuggerManager *parent, QList<Core::IOptionsPage*> *);
-IDebuggerEngine *createTcfEngine(DebuggerManager *parent, QList<Core::IOptionsPage*> *);
-
-
-namespace Debugger {
-namespace Internal {
-
-IDebuggerEngine *createGdbEngine(DebuggerManager *parent);
 
 
 QDebug operator<<(QDebug str, const DebuggerStartParameters &p)
@@ -369,10 +367,8 @@ void DebuggerManager::init()
     m_reverseDirectionAction->setChecked(false);
     //m_reverseDirectionAction->setIcon(QIcon(":/debugger/images/debugger_stepoverproc_small.png"));
 
-    // For usuage hints oin focus{In,Out}
     connect(m_continueAction, SIGNAL(triggered()),
         this, SLOT(continueExec()));
-
     connect(m_stopAction, SIGNAL(triggered()),
         this, SLOT(interruptDebuggingRequest()));
     connect(m_resetAction, SIGNAL(triggered()),
@@ -443,15 +439,24 @@ void DebuggerManager::init()
 QList<Core::IOptionsPage*> DebuggerManager::initializeEngines(unsigned enabledTypeFlags)
 {
     QList<Core::IOptionsPage*> rc;
+
     if (enabledTypeFlags & GdbEngineType) {
         gdbEngine = createGdbEngine(this);
         gdbEngine->addOptionPages(&rc);
     }
+
     winEngine = createWinEngine(this, (enabledTypeFlags & CdbEngineType), &rc);
-    if (enabledTypeFlags & ScriptEngineType)
-        scriptEngine = createScriptEngine(this, &rc);
-    if (enabledTypeFlags & TcfEngineType)
-        tcfEngine = createTcfEngine(this, &rc);
+
+    if (enabledTypeFlags & ScriptEngineType) {
+        scriptEngine = createScriptEngine(this);
+        scriptEngine->addOptionPages(&rc);
+    }
+
+    if (enabledTypeFlags & TcfEngineType) {
+        tcfEngine = createTcfEngine(this);
+        tcfEngine->addOptionPages(&rc);
+    }
+
     m_engine = 0;
     if (Debugger::Constants::Internal::debug)
         qDebug() << Q_FUNC_INFO << gdbEngine << winEngine << scriptEngine << rc.size();
@@ -764,6 +769,9 @@ static IDebuggerEngine *determineDebuggerEngine(const QString &executable,
 
     return gdbEngine;
 #else
+    // A remote executable?
+    if (!executable.endsWith(_(".exe")))
+        return gdbEngine;
     // If a file has PDB files, it has been compiled by VS.
     QStringList pdbFiles;
     if (!getPDBFiles(executable, &pdbFiles, errorMessage))
@@ -1095,7 +1103,7 @@ static bool isAllowedTransition(int from, int to)
 {
     return (from == -1)
       || (from == DebuggerProcessNotReady && to == DebuggerProcessStartingUp)
-      //|| (from == DebuggerProcessStartingUp && to == DebuggerInferiorStopped)
+      || (from == DebuggerProcessStartingUp && to == DebuggerInferiorStopped)
       || (from == DebuggerInferiorStopped && to == DebuggerInferiorRunningRequested)
       || (from == DebuggerInferiorRunningRequested && to == DebuggerInferiorRunning)
       || (from == DebuggerInferiorRunning && to == DebuggerInferiorStopRequested)
diff --git a/src/plugins/debugger/debuggermanager.h b/src/plugins/debugger/debuggermanager.h
index 29052449c9e8ba05aa55fc732c65c7393275399c..bf51de7822d0a2940b47904ca7095221630be0d6 100644
--- a/src/plugins/debugger/debuggermanager.h
+++ b/src/plugins/debugger/debuggermanager.h
@@ -366,6 +366,7 @@ private:
     ThreadsHandler *threadsHandler() { return m_threadsHandler; }
     WatchHandler *watchHandler() { return m_watchHandler; }
     SourceFilesWindow *sourceFileWindow() { return m_sourceFilesWindow; }
+    QWidget *threadsWindow() const { return m_threadsWindow; }
 
     void notifyInferiorStopped();
     void notifyInferiorRunningRequested();
@@ -376,20 +377,16 @@ private:
 
     void cleanupViews();
 
-    //
-    // Implementation of IDebuggerManagerAccessForDebugMode
-    //
-    QWidget *threadsWindow() const { return m_threadsWindow; }
-
-    virtual bool qtDumperLibraryEnabled() const;
-    virtual QString qtDumperLibraryName() const;
-    virtual QStringList qtDumperLibraryLocations() const;
-    virtual void showQtDumperLibraryWarning(const QString &details = QString());
-    virtual bool isReverseDebugging() const;
-
     //
     // internal implementation
     //
+    bool qtDumperLibraryEnabled() const;
+    QString qtDumperLibraryName() const;
+    QStringList qtDumperLibraryLocations() const;
+    void showQtDumperLibraryWarning(const QString &details = QString());
+    bool isReverseDebugging() const;
+    QAbstractItemModel *threadsModel();
+
     Q_SLOT void loadSessionData();
     Q_SLOT void saveSessionData();
     Q_SLOT void dumpLog();
@@ -397,7 +394,6 @@ private:
 public:
     // stuff in this block should be made private by moving it to
     // one of the interfaces
-    QAbstractItemModel *threadsModel();
     int status() const { return m_status; }
     // FIXME: hide this in the engines?
     //DebuggerStartMode startMode() const;
@@ -471,14 +467,12 @@ private:
     QAction *m_watchAction;
     QAction *m_breakAction;
     QAction *m_sepAction;
-    //QActio *m_stepByInstructionAction;
     QAction *m_reverseDirectionAction;
 
     QWidget *m_breakWindow;
     QWidget *m_localsWindow;
     QWidget *m_registerWindow;
     QWidget *m_modulesWindow;
-    //QWidget *m_tooltipWindow;
     QWidget *m_stackWindow;
     QWidget *m_threadsWindow;
     QWidget *m_watchersWindow;
diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp
index 24e06712b96255419e695cdfad2cf1de85cde87c..f01d9b569d04c1ff0561f8453525396bc9f42ec1 100644
--- a/src/plugins/debugger/debuggerplugin.cpp
+++ b/src/plugins/debugger/debuggerplugin.cpp
@@ -292,8 +292,10 @@ QWidget *CommonOptionsPage::createPage(QWidget *parent)
         m_ui.checkBoxUseMessageBoxForSignals);
     m_group.insert(theDebuggerAction(SkipKnownFrames),
         m_ui.checkBoxSkipKnownFrames);
-    m_group.insert(theDebuggerAction(UseToolTips),
-        m_ui.checkBoxUseToolTips);
+    m_group.insert(theDebuggerAction(UseToolTipsInMainEditor),
+        m_ui.checkBoxUseToolTipsInMainEditor);
+    m_group.insert(theDebuggerAction(UseToolTipsInLocalsView),
+        m_ui.checkBoxUseToolTipsInLocalsView);
     m_group.insert(theDebuggerAction(EnableReverseDebugging), 
         m_ui.checkBoxEnableReverseDebugging);
     m_group.insert(theDebuggerAction(MaximalStackDepth), 
@@ -1036,7 +1038,8 @@ void DebuggerPlugin::requestMark(TextEditor::ITextEditor *editor, int lineNumber
 void DebuggerPlugin::showToolTip(TextEditor::ITextEditor *editor,
     const QPoint &point, int pos)
 {
-    if (!theDebuggerBoolSetting(UseToolTips) || m_manager->status() == DebuggerProcessNotReady)
+    if (!theDebuggerBoolSetting(UseToolTipsInMainEditor)
+            || m_manager->status() == DebuggerProcessNotReady)
         return;
 
     m_manager->setToolTipExpression(point, editor, pos);
@@ -1229,7 +1232,7 @@ void DebuggerPlugin::attachExternalApplication(qint64 pid, const QString &crashP
     const DebuggerStartParametersPtr sp(new DebuggerStartParameters);
     sp->attachPID = pid;
     sp->crashParameter = crashParameter;
-    sp->startMode = crashParameter.isEmpty() ?  AttachExternal : AttachCrashedExternal;
+    sp->startMode = crashParameter.isEmpty() ? AttachExternal : AttachCrashedExternal;
     RunConfigurationPtr rc = activeRunConfiguration();
     if (rc.isNull())
         rc = DebuggerRunner::createDefaultRunConfiguration();
diff --git a/src/plugins/debugger/gdb/attachgdbadapter.cpp b/src/plugins/debugger/gdb/attachgdbadapter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6b0e702e14b5711f3067e3b5204bacc32ffa2a55
--- /dev/null
+++ b/src/plugins/debugger/gdb/attachgdbadapter.cpp
@@ -0,0 +1,205 @@
+/**************************************************************************
+**
+** 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://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "attachgdbadapter.h"
+
+#include "debuggeractions.h"
+#include "gdbengine.h"
+#include "procinterrupt.h"
+
+#include <utils/qtcassert.h>
+
+
+namespace Debugger {
+namespace Internal {
+
+#define STRINGIFY_INTERNAL(x) #x
+#define STRINGIFY(x) STRINGIFY_INTERNAL(x)
+#define CB(callback) \
+    static_cast<GdbEngine::AdapterCallback>(&AttachGdbAdapter::callback), \
+    STRINGIFY(callback)
+
+///////////////////////////////////////////////////////////////////////
+//
+// AttachGdbAdapter
+//
+///////////////////////////////////////////////////////////////////////
+
+AttachGdbAdapter::AttachGdbAdapter(GdbEngine *engine, QObject *parent)
+    : AbstractGdbAdapter(engine, parent)
+{
+    QTC_ASSERT(state() == AdapterNotRunning, qDebug() << state());
+    connect(&m_gdbProc, SIGNAL(error(QProcess::ProcessError)),
+        this, SIGNAL(error(QProcess::ProcessError)));
+    connect(&m_gdbProc, SIGNAL(readyReadStandardOutput()),
+        this, SIGNAL(readyReadStandardOutput()));
+    connect(&m_gdbProc, SIGNAL(readyReadStandardError()),
+        this, SIGNAL(readyReadStandardError()));
+    connect(&m_gdbProc, SIGNAL(started()),
+        this, SLOT(handleGdbStarted()));
+    connect(&m_gdbProc, SIGNAL(finished(int, QProcess::ExitStatus)),
+        this, SLOT(handleGdbFinished(int, QProcess::ExitStatus)));
+}
+
+void AttachGdbAdapter::startAdapter()
+{
+    QTC_ASSERT(state() == AdapterNotRunning, qDebug() << state());
+    setState(AdapterStarting);
+    debugMessage(_("TRYING TO START ADAPTER"));
+
+    QStringList gdbArgs;
+    gdbArgs.prepend(_("mi"));
+    gdbArgs.prepend(_("-i"));
+
+    if (!m_engine->m_outputCollector.listen()) {
+        emit adapterStartFailed(tr("Cannot set up communication with child process: %1")
+                .arg(m_engine->m_outputCollector.errorString()));
+        return;
+    }
+    gdbArgs.prepend(_("--tty=") + m_engine->m_outputCollector.serverName());
+
+    if (!startParameters().workingDir.isEmpty())
+        setWorkingDirectory(startParameters().workingDir);
+    if (!startParameters().environment.isEmpty())
+        setEnvironment(startParameters().environment);
+
+    QString location = theDebuggerStringSetting(GdbLocation);
+    m_gdbProc.start(location, gdbArgs);
+}
+
+void AttachGdbAdapter::handleGdbStarted()
+{
+    QTC_ASSERT(state() == AdapterStarting, qDebug() << state());
+    setState(AdapterStarted);
+    emit adapterStarted();
+}
+
+void AttachGdbAdapter::prepareInferior()
+{
+    const qint64 pid = startParameters().attachPID;
+    QTC_ASSERT(state() == AdapterStarted, qDebug() << state());
+    setState(InferiorPreparing);
+    qDebug() << "USING " << pid;
+    m_engine->postCommand(_("attach %1").arg(pid), CB(handleAttach));
+    // Task 254674 does not want to remove them
+    //qq->breakHandler()->removeAllBreakpoints();
+}
+
+void AttachGdbAdapter::handleAttach(const GdbResultRecord &response, const QVariant &)
+{
+    QTC_ASSERT(state() == InferiorPreparing, qDebug() << state());
+    if (response.resultClass == GdbResultDone) {
+        setState(InferiorPrepared);
+        emit inferiorPrepared();
+    } else if (response.resultClass == GdbResultError) {
+        QString msg = __(response.data.findChild("msg").data());
+        setState(InferiorPreparationFailed);
+        emit inferiorPreparationFailed(msg);
+    }
+}
+
+void AttachGdbAdapter::startInferior()
+{
+    QTC_ASSERT(state() == InferiorPrepared, qDebug() << state());
+    setState(InferiorStarting);
+    m_engine->postCommand(_("-exec-continue"), CB(handleContinue));
+}
+
+void AttachGdbAdapter::handleContinue(const GdbResultRecord &response, const QVariant &)
+{
+    QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
+    if (response.resultClass == GdbResultRunning) {
+        setState(InferiorStarted);
+        emit inferiorStarted();
+    } else {
+        QTC_ASSERT(response.resultClass == GdbResultError, /**/);
+        const QByteArray &msg = response.data.findChild("msg").data();
+        setState(InferiorStartFailed);
+        emit inferiorStartFailed(msg);
+    }
+}
+
+void AttachGdbAdapter::interruptInferior()
+{
+    debugMessage(_("TRYING TO INTERUPT INFERIOR"));
+    const qint64 pid = startParameters().attachPID;
+    if (!interruptProcess(pid))
+        debugMessage(_("CANNOT INTERRUPT %1").arg(pid));
+}
+
+void AttachGdbAdapter::shutdown()
+{
+    if (state() == InferiorStarted) {
+        setState(InferiorShuttingDown);
+        m_engine->postCommand(_("detach"), CB(handleDetach));
+        return;
+    }
+
+    if (state() == InferiorShutDown) {
+        setState(AdapterShuttingDown);
+        m_engine->postCommand(_("-gdb-exit"), CB(handleExit));
+        return;
+    }
+    QTC_ASSERT(state() == AdapterNotRunning, qDebug() << state());
+}
+
+void AttachGdbAdapter::handleDetach(const GdbResultRecord &response, const QVariant &)
+{
+    if (response.resultClass == GdbResultDone) {
+        setState(InferiorShutDown);
+        emit inferiorShutDown();
+        shutdown(); // re-iterate...
+    } else if (response.resultClass == GdbResultError) {
+        QString msg = tr("Inferior process could not be stopped:\n") +
+            __(response.data.findChild("msg").data());
+        setState(InferiorShutdownFailed);
+        emit inferiorShutdownFailed(msg);
+    }
+}
+
+void AttachGdbAdapter::handleExit(const GdbResultRecord &response, const QVariant &)
+{
+    if (response.resultClass == GdbResultDone) {
+        // don't set state here, this will be handled in handleGdbFinished()
+    } else if (response.resultClass == GdbResultError) {
+        QString msg = tr("Gdb process could not be stopped:\n") +
+            __(response.data.findChild("msg").data());
+        emit adapterShutdownFailed(msg);
+    }
+}
+
+void AttachGdbAdapter::handleGdbFinished(int, QProcess::ExitStatus)
+{
+    debugMessage(_("GDB PROESS FINISHED"));
+    setState(AdapterNotRunning);
+    emit adapterShutDown();
+}
+
+} // namespace Internal
+} // namespace Debugger
diff --git a/src/plugins/debugger/gdb/attachgdbadapter.h b/src/plugins/debugger/gdb/attachgdbadapter.h
new file mode 100644
index 0000000000000000000000000000000000000000..6bedcbfc0029d3568ff180c6afea4f7acf116a37
--- /dev/null
+++ b/src/plugins/debugger/gdb/attachgdbadapter.h
@@ -0,0 +1,84 @@
+/**************************************************************************
+**
+** 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://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef DEBUGGER_ATTACHGDBADAPTER_H
+#define DEBUGGER_ATTACHGDBADAPTER_H
+
+#include "abstractgdbadapter.h"
+#include "gdbengine.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QProcess>
+
+namespace Debugger {
+namespace Internal {
+
+///////////////////////////////////////////////////////////////////////
+//
+// AttachGdbAdapter
+//
+///////////////////////////////////////////////////////////////////////
+
+class AttachGdbAdapter : public AbstractGdbAdapter
+{
+    Q_OBJECT
+
+public:
+    AttachGdbAdapter(GdbEngine *engine, QObject *parent = 0);
+
+private:
+    QByteArray readAllStandardError() { return m_gdbProc.readAllStandardError(); }
+    QByteArray readAllStandardOutput() { return m_gdbProc.readAllStandardOutput(); }
+    qint64 write(const char *data) { return m_gdbProc.write(data); }
+    void setWorkingDirectory(const QString &dir) { m_gdbProc.setWorkingDirectory(dir); }
+    void setEnvironment(const QStringList &env) { m_gdbProc.setEnvironment(env); }
+    bool isTrkAdapter() const { return false; }
+
+    void startAdapter();
+    void prepareInferior();
+    void startInferior();
+    void interruptInferior();
+    void shutdown();
+
+    void handleAttach(const GdbResultRecord &, const QVariant &);
+    void handleContinue(const GdbResultRecord &, const QVariant &);
+    void handleDetach(const GdbResultRecord &, const QVariant &);
+    void handleExit(const GdbResultRecord &, const QVariant &);
+
+    void debugMessage(const QString &msg) { m_engine->debugMessage(msg); }
+    Q_SLOT void handleGdbFinished(int, QProcess::ExitStatus);
+    Q_SLOT void handleGdbStarted();
+
+    QProcess m_gdbProc;
+};
+
+} // namespace Internal
+} // namespace Debugger
+
+#endif // DEBUGGER_ATTACHDBADAPTER_H
diff --git a/src/plugins/debugger/gdb/coregdbadapter.cpp b/src/plugins/debugger/gdb/coregdbadapter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d5817633572230d4f67c7393895ec9a0d7c2ae3a
--- /dev/null
+++ b/src/plugins/debugger/gdb/coregdbadapter.cpp
@@ -0,0 +1,192 @@
+/**************************************************************************
+**
+** 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://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "coregdbadapter.h"
+
+#include "debuggeractions.h"
+#include "gdbengine.h"
+
+#include <utils/qtcassert.h>
+
+#include <QtCore/QFileInfo>
+
+namespace Debugger {
+namespace Internal {
+
+#define STRINGIFY_INTERNAL(x) #x
+#define STRINGIFY(x) STRINGIFY_INTERNAL(x)
+#define CB(callback) \
+    static_cast<GdbEngine::AdapterCallback>(&CoreGdbAdapter::callback), \
+    STRINGIFY(callback)
+
+///////////////////////////////////////////////////////////////////////
+//
+// CoreGdbAdapter
+//
+///////////////////////////////////////////////////////////////////////
+
+CoreGdbAdapter::CoreGdbAdapter(GdbEngine *engine, QObject *parent)
+    : AbstractGdbAdapter(engine, parent)
+{
+    QTC_ASSERT(state() == AdapterNotRunning, qDebug() << state());
+    connect(&m_gdbProc, SIGNAL(error(QProcess::ProcessError)),
+        this, SIGNAL(error(QProcess::ProcessError)));
+    connect(&m_gdbProc, SIGNAL(readyReadStandardOutput()),
+        this, SIGNAL(readyReadStandardOutput()));
+    connect(&m_gdbProc, SIGNAL(readyReadStandardError()),
+        this, SIGNAL(readyReadStandardError()));
+    connect(&m_gdbProc, SIGNAL(started()),
+        this, SLOT(handleGdbStarted()));
+    connect(&m_gdbProc, SIGNAL(finished(int, QProcess::ExitStatus)),
+        this, SLOT(handleGdbFinished(int, QProcess::ExitStatus)));
+}
+
+void CoreGdbAdapter::startAdapter()
+{
+    QTC_ASSERT(state() == AdapterNotRunning, qDebug() << state());
+    setState(AdapterStarting);
+    debugMessage(_("TRYING TO START ADAPTER"));
+
+    QStringList gdbArgs;
+    gdbArgs.prepend(_("mi"));
+    gdbArgs.prepend(_("-i"));
+
+    if (!m_engine->m_outputCollector.listen()) {
+        emit adapterStartFailed(tr("Cannot set up communication with child process: %1")
+                .arg(m_engine->m_outputCollector.errorString()));
+        return;
+    }
+    gdbArgs.prepend(_("--tty=") + m_engine->m_outputCollector.serverName());
+
+    if (!startParameters().workingDir.isEmpty())
+        setWorkingDirectory(startParameters().workingDir);
+    if (!startParameters().environment.isEmpty())
+        setEnvironment(startParameters().environment);
+
+    QString location = theDebuggerStringSetting(GdbLocation);
+    m_gdbProc.start(location, gdbArgs);
+}
+
+void CoreGdbAdapter::handleGdbStarted()
+{
+    QTC_ASSERT(state() == AdapterStarting, qDebug() << state());
+    setState(AdapterStarted);
+    emit adapterStarted();
+}
+
+void CoreGdbAdapter::prepareInferior()
+{
+    QTC_ASSERT(state() == AdapterStarted, qDebug() << state());
+    setState(InferiorPreparing);
+    if (!startParameters().processArgs.isEmpty())
+        m_engine->postCommand(_("-exec-arguments ")
+            + startParameters().processArgs.join(_(" ")));
+    QFileInfo fi(m_engine->startParameters().executable);
+    m_engine->postCommand(_("-file-exec-and-symbols \"%1\"").arg(fi.absoluteFilePath()),
+        CB(handleFileExecAndSymbols));
+}
+
+void CoreGdbAdapter::handleFileExecAndSymbols(const GdbResultRecord &response, const QVariant &)
+{
+    QTC_ASSERT(state() == InferiorPreparing, qDebug() << state());
+    if (response.resultClass == GdbResultDone) {
+        //m_breakHandler->clearBreakMarkers();
+        setState(InferiorPrepared);
+        emit inferiorPrepared();
+    } else if (response.resultClass == GdbResultError) {
+        QString msg = tr("Starting executable failed:\n") +
+            __(response.data.findChild("msg").data());
+        setState(InferiorPreparationFailed);
+        emit inferiorPreparationFailed(msg);
+    }
+}
+
+void CoreGdbAdapter::startInferior()
+{
+    QTC_ASSERT(state() == InferiorPrepared, qDebug() << state());
+    setState(InferiorStarting);
+    QFileInfo fi(startParameters().executable);
+    QString fileName = _c('"') + fi.absoluteFilePath() + _c('"');
+    QFileInfo fi2(startParameters().coreFile);
+    // quoting core name below fails in gdb 6.8-debian
+    QString coreName = fi2.absoluteFilePath();
+    m_engine->postCommand(_("target core ") + coreName, CB(handleTargetCore));
+}
+
+void CoreGdbAdapter::handleTargetCore(const GdbResultRecord &response, const QVariant &)
+{
+    QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
+    if (response.resultClass == GdbResultDone) {
+        setState(InferiorStarted);
+        emit inferiorStarted();
+        m_engine->updateAll();
+    } else {
+        QTC_ASSERT(response.resultClass == GdbResultError, /**/);
+        const QByteArray &msg = response.data.findChild("msg").data();
+        setState(InferiorStartFailed);
+        emit inferiorStartFailed(msg);
+    }
+}
+
+void CoreGdbAdapter::interruptInferior()
+{
+    // A core should never 'run'
+    QTC_ASSERT(false, /**/);
+}
+
+void CoreGdbAdapter::shutdown()
+{
+    if (state() == InferiorStarted || state() == InferiorShutDown) {
+        setState(AdapterShuttingDown);
+        m_engine->postCommand(_("-gdb-exit"), CB(handleExit));
+        return;
+    }
+    QTC_ASSERT(state() == AdapterNotRunning, qDebug() << state());
+}
+
+void CoreGdbAdapter::handleExit(const GdbResultRecord &response, const QVariant &)
+{
+    if (response.resultClass == GdbResultDone) {
+        // don't set state here, this will be handled in handleGdbFinished()
+    } else if (response.resultClass == GdbResultError) {
+        QString msg = tr("Gdb process could not be stopped:\n") +
+            __(response.data.findChild("msg").data());
+        emit adapterShutdownFailed(msg);
+    }
+}
+
+void CoreGdbAdapter::handleGdbFinished(int, QProcess::ExitStatus)
+{
+    debugMessage(_("GDB PROESS FINISHED"));
+    setState(AdapterNotRunning);
+    emit adapterShutDown();
+}
+
+} // namespace Internal
+} // namespace Debugger
diff --git a/src/plugins/debugger/gdb/coregdbadapter.h b/src/plugins/debugger/gdb/coregdbadapter.h
new file mode 100644
index 0000000000000000000000000000000000000000..152c9bebf5701d5cee7a55338159556dd4d70202
--- /dev/null
+++ b/src/plugins/debugger/gdb/coregdbadapter.h
@@ -0,0 +1,83 @@
+/**************************************************************************
+**
+** 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://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef DEBUGGER_COREGDBADAPTER_H
+#define DEBUGGER_COREGDBADAPTER_H
+
+#include "abstractgdbadapter.h"
+#include "gdbengine.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QProcess>
+
+namespace Debugger {
+namespace Internal {
+
+///////////////////////////////////////////////////////////////////////
+//
+// CoreGdbAdapter
+//
+///////////////////////////////////////////////////////////////////////
+
+class CoreGdbAdapter : public AbstractGdbAdapter
+{
+    Q_OBJECT
+
+public:
+    CoreGdbAdapter(GdbEngine *engine, QObject *parent = 0);
+
+private:
+    QByteArray readAllStandardError() { return m_gdbProc.readAllStandardError(); }
+    QByteArray readAllStandardOutput() { return m_gdbProc.readAllStandardOutput(); }
+    qint64 write(const char *data) { return m_gdbProc.write(data); }
+    void setWorkingDirectory(const QString &dir) { m_gdbProc.setWorkingDirectory(dir); }
+    void setEnvironment(const QStringList &env) { m_gdbProc.setEnvironment(env); }
+    bool isTrkAdapter() const { return false; }
+
+    void startAdapter();
+    void prepareInferior();
+    void startInferior();
+    void interruptInferior();
+    void shutdown();
+
+    void handleFileExecAndSymbols(const GdbResultRecord &, const QVariant &);
+    void handleTargetCore(const GdbResultRecord &response, const QVariant &);
+    void handleExit(const GdbResultRecord &, const QVariant &);
+
+    void debugMessage(const QString &msg) { m_engine->debugMessage(msg); }
+    Q_SLOT void handleGdbFinished(int, QProcess::ExitStatus);
+    Q_SLOT void handleGdbStarted();
+
+    QProcess m_gdbProc;
+};
+
+} // namespace Internal
+} // namespace Debugger
+
+#endif // DEBUGGER_COREDBADAPTER_H
diff --git a/src/plugins/debugger/gdb/gdb.pri b/src/plugins/debugger/gdb/gdb.pri
index 77a3a42d885684d088bdd28fc4dbcc1a21fb7858..344f724eebd09448c9835c8a39464fc26cd1f7f6 100644
--- a/src/plugins/debugger/gdb/gdb.pri
+++ b/src/plugins/debugger/gdb/gdb.pri
@@ -1,27 +1,31 @@
 include(../../../shared/trk/trk.pri)
 
 HEADERS += \
-    $$PWD/abstractgdbadapter.h \
-    $$PWD/plaingdbadapter.h \
     $$PWD/gdbmi.h \
     $$PWD/gdbengine.h \
     $$PWD/gdboptionspage.h \
-    $$PWD/remotegdbadapter.h \
-    $$PWD/trkgdbadapter.h \
     $$PWD/trkoptions.h \
     $$PWD/trkoptionswidget.h \
-    $$PWD/trkoptionspage.h
+    $$PWD/trkoptionspage.h \
+    $$PWD/abstractgdbadapter.h \
+    $$PWD/attachgdbadapter.h \
+    $$PWD/coregdbadapter.h \
+    $$PWD/plaingdbadapter.h \
+    $$PWD/remotegdbadapter.h \
+    $$PWD/trkgdbadapter.h \
 
 SOURCES += \
     $$PWD/gdbmi.cpp \
     $$PWD/gdbengine.cpp \
     $$PWD/gdboptionspage.cpp \
-    $$PWD/plaingdbadapter.cpp \
-    $$PWD/remotegdbadapter.cpp \
     $$PWD/trkoptions.cpp \
     $$PWD/trkoptionswidget.cpp \
     $$PWD/trkoptionspage.cpp \
-    $$PWD/trkgdbadapter.cpp
+    $$PWD/attachgdbadapter.cpp \
+    $$PWD/coregdbadapter.cpp \
+    $$PWD/plaingdbadapter.cpp \
+    $$PWD/remotegdbadapter.cpp \
+    $$PWD/trkgdbadapter.cpp \
 
 FORMS +=  $$PWD/gdboptionspage.ui \
 $$PWD/trkoptionswidget.ui
diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp
index 7f88fb9e0363f09d04ba2968f680f5b87905eb90..ae532e2da6936edcfc2a0d40162f9efed125c92e 100644
--- a/src/plugins/debugger/gdb/gdbengine.cpp
+++ b/src/plugins/debugger/gdb/gdbengine.cpp
@@ -33,9 +33,12 @@
 #include "gdboptionspage.h"
 #include "trkoptions.h"
 #include "trkoptionspage.h"
+
+#include "attachgdbadapter.h"
+#include "coregdbadapter.h"
 #include "plaingdbadapter.h"
-#include "trkgdbadapter.h"
 #include "remotegdbadapter.h"
+#include "trkgdbadapter.h"
 
 #include "watchutils.h"
 #include "debuggeractions.h"
@@ -44,7 +47,6 @@
 #include "debuggermanager.h"
 #include "debuggertooltip.h"
 #include "gdbmi.h"
-#include "procinterrupt.h"
 
 #include "breakhandler.h"
 #include "moduleshandler.h"
@@ -178,7 +180,9 @@ GdbEngine::GdbEngine(DebuggerManager *parent) :
     options->fromSettings(Core::ICore::instance()->settings());
     m_plainAdapter = new PlainGdbAdapter(this);
     m_trkAdapter = new TrkGdbAdapter(this, options);
-    m_remoteAdapter = 0; // FIXME
+    m_remoteAdapter = new RemoteGdbAdapter(this);
+    m_coreAdapter = new CoreGdbAdapter(this);
+    m_attachAdapter = new AttachGdbAdapter(this);
 
     // Output
     connect(&m_outputCollector, SIGNAL(byteDelivery(QByteArray)),
@@ -193,14 +197,29 @@ GdbEngine::GdbEngine(DebuggerManager *parent) :
     connect(this, SIGNAL(applicationOutputAvailable(QString)),
         m_manager, SLOT(showApplicationOutput(QString)),
         Qt::QueuedConnection);
+}
 
-    // FIXME: These trigger even if the engine is not active
+void GdbEngine::connectDebuggingHelperActions()
+{
     connect(theDebuggerAction(UseDebuggingHelpers), SIGNAL(valueChanged(QVariant)),
-        this, SLOT(setUseDebuggingHelpers(QVariant)));
+            this, SLOT(setUseDebuggingHelpers(QVariant)));
     connect(theDebuggerAction(DebugDebuggingHelpers), SIGNAL(valueChanged(QVariant)),
-        this, SLOT(setDebugDebuggingHelpers(QVariant)));
+            this, SLOT(setDebugDebuggingHelpers(QVariant)));
     connect(theDebuggerAction(RecheckDebuggingHelpers), SIGNAL(triggered()),
-        this, SLOT(recheckDebuggingHelperAvailability()));
+            this, SLOT(recheckDebuggingHelperAvailability()));
+}
+   
+void GdbEngine::disconnectDebuggingHelperActions()
+{
+    disconnect(theDebuggerAction(UseDebuggingHelpers), 0, this, 0);
+    disconnect(theDebuggerAction(DebugDebuggingHelpers), 0, this, 0);
+    disconnect(theDebuggerAction(RecheckDebuggingHelpers), 0, this, 0);
+}
+
+DebuggerStartMode GdbEngine::startMode() const
+{
+    QTC_ASSERT(!m_startParameters.isNull(), return NoStartMode);
+    return m_startParameters->startMode;
 }
 
 GdbEngine::~GdbEngine()
@@ -214,6 +233,8 @@ GdbEngine::~GdbEngine()
     delete m_plainAdapter;
     delete m_trkAdapter;
     delete m_remoteAdapter;
+    delete m_coreAdapter;
+    delete m_attachAdapter;
 }
 
 void GdbEngine::connectAdapter()
@@ -306,7 +327,6 @@ void GdbEngine::initializeVariables()
     m_outputCodec = QTextCodec::codecForLocale();
     m_pendingRequests = 0;
     m_continuationAfterDone = 0;
-    m_waitingForFirstBreakpointToBeHit = false;
     m_commandsToRunOnTemporaryBreak.clear();
     m_cookieForToken.clear();
     m_customOutputForToken.clear();
@@ -529,13 +549,27 @@ void GdbEngine::handleResponse(const QByteArray &buff)
         }
 
         case '~': {
-            static QRegExp re(_("New .hread 0x[0-9a-f]* \\(LWP ([0-9]*)\\)"));
             QByteArray data = GdbMi::parseCString(from, to);
             m_pendingConsoleStreamOutput += data;
-            if (re.indexIn(_(data)) != -1)
-                maybeHandleInferiorPidChanged(re.cap(1));
+
+            // Parse pid from noise.
+            if (!inferiorPid()) {
+                // Linux/Mac gdb: [New [Tt]hread 0x545 (LWP 4554)]
+                static QRegExp re1(_("New .hread 0x[0-9a-f]+ \\(LWP ([0-9]*)\\)"));
+                // MinGW 6.8: [New thread 2437.0x435345]
+                static QRegExp re2(_("New .hread ([0-9]+)\\.0x[0-9a-f]*"));
+                QTC_ASSERT(re1.isValid() && re2.isValid(), return);
+                if (re1.indexIn(_(data)) != -1)
+                    maybeHandleInferiorPidChanged(re1.cap(1));
+                else if (re2.indexIn(_(data)) != -1)
+                    maybeHandleInferiorPidChanged(re2.cap(1));
+            }
+
+            // Show some messages to give the impression something happens.
             if (data.startsWith("Reading symbols from "))
-                showStatusMessage(tr("Reading %1...").arg(_(data.mid(21))));
+                showStatusMessage(tr("Reading %1...").arg(_(data.mid(21))), 1000);
+            if (data.startsWith("[New "))
+                showStatusMessage(_(data), 1000);
             break;
         }
 
@@ -666,6 +700,7 @@ void GdbEngine::interruptInferior()
         return;
     }
 
+    debugMessage(_("TRYING TO INTERUPT INFERIOR"));
     m_gdbAdapter->interruptInferior();
 }
 
@@ -780,7 +815,6 @@ void GdbEngine::handleResultRecord(const GdbResultRecord &record)
 {
     //qDebug() << "TOKEN:" << record.token
     //    << " ACCEPTABLE:" << m_oldestAcceptableToken;
-    //qDebug() << "";
     //qDebug() << "\nRESULT" << record.token << record.toString();
 
     int token = record.token;
@@ -791,7 +825,7 @@ void GdbEngine::handleResultRecord(const GdbResultRecord &record)
         // In theory this should not happen, in practice it does.
         debugMessage(_("COOKIE FOR TOKEN %1 ALREADY EATEN. "
             "TWO RESPONSES FOR ONE COMMAND?").arg(token));
-        // handle a case known to occur on Linux/gdb 6.8 when debugging moc
+        // Handle a case known to occur on Linux/gdb 6.8 when debugging moc
         // with helpers enabled. In this case we get a second response with
         // msg="Cannot find new threads: generic error"
         if (record.resultClass == GdbResultError) {
@@ -800,8 +834,6 @@ void GdbEngine::handleResultRecord(const GdbResultRecord &record)
                 tr("Executable failed"), QString::fromLocal8Bit(msg));
             showStatusMessage(tr("Process failed to start."));
             exitDebugger();
-            //qq->notifyInferiorStopped();
-            //qq->notifyInferiorExited();
         }
         return;
     }
@@ -826,8 +858,6 @@ void GdbEngine::handleResultRecord(const GdbResultRecord &record)
         << "\n record: " << record.toString();
 #endif
 
-    // << "\n data: " << record.data.toString(true);
-
     if (cmd.callback)
         (this->*cmd.callback)(record, cmd.cookie);
     if (cmd.adapterCallback)
@@ -872,14 +902,15 @@ void GdbEngine::executeDebuggerCommand(const QString &command)
     m_gdbAdapter->write(command.toLatin1() + "\r\n");
 }
 
-void GdbEngine::handleTargetCore(const GdbResultRecord &, const QVariant &)
+// called from CoreAdapter and AttachAdapter
+void GdbEngine::updateAll()
 {
     qq->notifyInferiorStopped();
     showStatusMessage(tr("Core file loaded."));
     m_manager->resetLocation();
     tryLoadDebuggingHelpers();
     qq->stackHandler()->setCurrentIndex(0);
-    updateLocals(); // Quick shot
+    updateLocals(); 
     reloadStack();
     if (supportsThreads())
         postCommand(_("-thread-list-ids"), WatchUpdate, CB(handleStackListThreads), 0);
@@ -903,7 +934,6 @@ void GdbEngine::handleQuerySources(const GdbResultRecord &record, const QVariant
             full = QDir::cleanPath(full);
             #endif
             if (fullName.isValid() && QFileInfo(full).isReadable()) {
-                //qDebug() << "STORING 2:" << fileName << full;
                 m_shortToFullName[fileName] = full;
                 m_fullToShortName[full] = fileName;
             }
@@ -1096,21 +1126,6 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data)
         return;
     }
 
-    //MAC: bool isFirstStop = data.findChild("bkptno").data() == "1";
-    //!MAC: startSymbolName == data.findChild("frame").findChild("func")
-    if (m_waitingForFirstBreakpointToBeHit) {
-        m_waitingForFirstBreakpointToBeHit = false;
-
-        // If the executable dies already that early we might get something
-        // like >49*stopped,reason="exited",exit-code="0177"
-        // This is handled now above.
-
-        qq->notifyInferiorStopped();
-        handleAqcuiredInferior();
-// FIXME:        m_continuationAfterDone = true;
-        return;
-    }
-
     if (!m_commandsToRunOnTemporaryBreak.isEmpty()) {
         QTC_ASSERT(status() == DebuggerInferiorStopRequested,
             qDebug() << "STATUS:" << status())
@@ -1201,7 +1216,7 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data)
 #if 1
     // FIXME: remove this special case as soon as there's a real
     // reason given when the temporary breakpoint is hit.
-    // reight now we get:
+    // right now we get:
     // 14*stopped,thread-id="1",frame={addr="0x0000000000403ce4",
     // func="foo",args=[{name="str",value="@0x7fff0f450460"}],
     // file="main.cpp",fullname="/tmp/g/main.cpp",line="37"}
@@ -1343,11 +1358,13 @@ void GdbEngine::handleStop2(const GdbMi &data)
     qq->stackHandler()->setCurrentIndex(0);
     updateLocals(); // Quick shot
 
-    int currentId = data.findChild("thread-id").data().toInt();
-
     reloadStack();
-    if (supportsThreads())
-        postCommand(_("-thread-list-ids"), WatchUpdate, CB(handleStackListThreads), currentId);
+
+    if (supportsThreads()) {
+        int currentId = data.findChild("thread-id").data().toInt();
+        postCommand(_("-thread-list-ids"), WatchUpdate,
+            CB(handleStackListThreads), currentId);
+    }
 
     //
     // Registers
@@ -1408,23 +1425,6 @@ void GdbEngine::handleFileExecAndSymbols(const GdbResultRecord &response, const
     }
 }
 
-#if 0
-void GdbEngine::handleExecRun(const GdbResultRecord &response, const QVariant &)
-{
-    if (response.resultClass == GdbResultRunning) {
-        qq->notifyInferiorRunning();
-    } else {
-        QTC_ASSERT(response.resultClass == GdbResultError, /**/);
-        const QByteArray &msg = response.data.findChild("msg").data();
-        showMessageBox(QMessageBox::Critical, tr("Starting executable failed",
-            QString::fromLocal8Bit(msg)));
-        QTC_ASSERT(status() == DebuggerInferiorRunning, /**/);
-        //interruptInferior();
-        qq->notifyInferiorExited();
-    }
-}
-#endif
-
 void GdbEngine::handleExecContinue(const GdbResultRecord &response, const QVariant &)
 {
     if (response.resultClass == GdbResultRunning) {
@@ -1438,10 +1438,9 @@ void GdbEngine::handleExecContinue(const GdbResultRecord &response, const QVaria
             //  "Leaving function..."));
             //stepOutExec();
         } else {
-            showMessageBox(QMessageBox::Critical, tr("Starting executable failed"),
-                QString::fromLocal8Bit(msg));
+            showMessageBox(QMessageBox::Critical, tr("Error"),
+                tr("Starting executable failed:\n") + QString::fromLocal8Bit(msg));
             QTC_ASSERT(status() == DebuggerInferiorRunning, /**/);
-            //interruptInferior();
             qq->notifyInferiorExited();
         }
     }
@@ -1449,7 +1448,6 @@ void GdbEngine::handleExecContinue(const GdbResultRecord &response, const QVaria
 
 QString GdbEngine::fullName(const QString &fileName)
 {
-    //QString absName = m_manager->currentWorkingDirectory() + "/" + file; ??
     if (fileName.isEmpty())
         return QString();
     QString full = m_shortToFullName.value(fileName, QString());
@@ -1493,21 +1491,18 @@ void GdbEngine::shutdown()
 
 void GdbEngine::detachDebugger()
 {
-    postCommand(_("detach"), CB(handleDetach));
+    QTC_ASSERT(startMode() == AttachExternal, /**/);
+    shutdown();
 }
 
 void GdbEngine::exitDebugger()
 {
+    disconnectDebuggingHelperActions();
     m_outputCollector.shutdown();
     initializeVariables();
     m_gdbAdapter->shutdown();
 }
 
-void GdbEngine::handleDetach(const GdbResultRecord &, const QVariant &)
-{
-    exitDebugger();
-}
-
 int GdbEngine::currentFrame() const
 {
     return qq->stackHandler()->currentIndex();
@@ -1522,12 +1517,20 @@ void GdbEngine::startDebugger(const DebuggerStartParametersPtr &sp)
     //QTC_ASSERT(m_gdbAdapter == 0, delete m_gdbAdapter; m_gdbAdapter = 0);
 
     m_startParameters = sp;
+    if (startModeAllowsDumpers())
+        connectDebuggingHelperActions();
 
     if (m_gdbAdapter)
         disconnectAdapter();
 
     if (sp->executable.endsWith(_(".sym")))
         m_gdbAdapter = m_trkAdapter;
+    else if (sp->startMode == AttachCore)
+        m_gdbAdapter = m_coreAdapter;
+    else if (sp->startMode == StartRemote)
+        m_gdbAdapter = m_remoteAdapter;
+    else if (sp->startMode == AttachExternal)
+        m_gdbAdapter = m_attachAdapter;
     else 
         m_gdbAdapter = m_plainAdapter;
 
@@ -1583,31 +1586,6 @@ void GdbEngine::continueInferior()
 }
 
 #if 0
-void GdbEngine::handleAttach(const GdbResultRecord &, const QVariant &)
-{
-    qq->notifyInferiorStopped();
-    showStatusMessage(tr("Attached to running process. Stopped."));
-    handleAqcuiredInferior();
-
-    m_manager->resetLocation();
-    recheckDebuggingHelperAvailability();
-
-    //
-    // Stack
-    //
-    qq->stackHandler()->setCurrentIndex(0);
-    updateLocals(); // Quick shot
-
-    reloadStack();
-    if (supportsThreads())
-        postCommand(_("-thread-list-ids"), WatchUpdate, CB(handleStackListThreads), 0);
-
-    //
-    // Registers
-    //
-    qq->reloadRegisters();
-}
-
 void GdbEngine::handleSetTargetAsync(const GdbResultRecord &record, const QVariant &)
 {
     if (record.resultClass == GdbResultDone) {
@@ -1681,7 +1659,7 @@ void GdbEngine::nextExec()
     if (qq->isReverseDebugging())
         postCommand(_("-reverse-next"), CB(handleExecContinue));
     else {
-#if 0
+#if 1
         postCommand(_("-exec-next"), CB(handleExecContinue));
 #else
         postCommand(_("tbreak %1:%2").arg(QFileInfo(lastFile).fileName())
@@ -3838,9 +3816,8 @@ void GdbEngine::recheckDebuggingHelperAvailability()
 
 bool GdbEngine::startModeAllowsDumpers() const
 {
-    return startMode() == StartInternal
-        || startMode() == StartExternal
-        || startMode() == AttachExternal;
+    const DebuggerStartMode m = startMode();
+    return m == StartInternal || m == StartExternal || m == AttachExternal;
 }
 
 void GdbEngine::watchPoint(const QPoint &pnt)
@@ -4082,12 +4059,13 @@ void GdbEngine::handleAdapterStartFailed(const QString &msg)
 void GdbEngine::handleAdapterStarted()
 {
     debugMessage(_("ADAPTER SUCCESSFULLY STARTED, PREPARING INFERIOR"));
+    qq->notifyInferiorStopped();
     m_gdbAdapter->prepareInferior();
 }
 
 void GdbEngine::handleInferiorPreparationFailed(const QString &msg)
 {
-    debugMessage(_("INFERIOR PREPARATION FAILD"));
+    debugMessage(_("INFERIOR PREPARATION FAILED"));
     showMessageBox(QMessageBox::Critical,
         tr("Inferior start preparation failed"), msg);
     shutdown();
@@ -4097,6 +4075,7 @@ void GdbEngine::handleInferiorPreparationFailed(const QString &msg)
 
 void GdbEngine::handleInferiorPrepared()
 {
+    debugMessage(_("INFERIOR PREPARED"));
     // FIXME: Check that inferior is in "stopped" state
     qq->notifyInferiorStopped();
     showStatusMessage(tr("Inferior prepared for startup."));
@@ -4183,15 +4162,6 @@ void GdbEngine::handleInferiorPrepared()
         postCommand(_("attach %1").arg(m_startParameters->attachPID), CB(handleAttach));
         // Task 254674 does not want to remove them
         //qq->breakHandler()->removeAllBreakpoints();
-    } else if (startMode() == AttachCore) {
-        QFileInfo fi(m_startParameters->executable);
-        QString fileName = _c('"') + fi.absoluteFilePath() + _c('"');
-        QFileInfo fi2(m_startParameters->coreFile);
-        // quoting core name below fails in gdb 6.8-debian
-        QString coreName = fi2.absoluteFilePath();
-        postCommand(_("-file-exec-and-symbols ") + fileName, CB(handleFileExecAndSymbols));
-        postCommand(_("target core ") + coreName, CB(handleTargetCore));
-        qq->breakHandler()->removeAllBreakpoints();
     } else if (startMode() == StartRemote) {
         postCommand(_("set architecture %1").arg(m_startParameters->remoteArchitecture));
         qq->breakHandler()->setAllPending();
@@ -4224,7 +4194,7 @@ void GdbEngine::handleInferiorPrepared()
 
 void GdbEngine::handleInitialBreakpointsSet()
 {
-    showStatusMessage(tr("Finishing initial breakpoint setting."));
+    showStatusMessage(tr("Initial breakpoint setting finished."), 1000);
     qq->notifyInferiorRunningRequested();
     m_gdbAdapter->startInferior();
 }
@@ -4232,14 +4202,14 @@ void GdbEngine::handleInitialBreakpointsSet()
 void GdbEngine::handleInferiorStartFailed(const QString &msg)
 {
     debugMessage(_("INFERIOR START FAILED"));
-    showMessageBox(QMessageBox::Critical, tr("Error"),
-        tr("Inferior start failed:\n") + msg);
+    showMessageBox(QMessageBox::Critical, tr("Inferior start failed"), msg);
     qq->notifyInferiorExited();
     m_manager->exitDebugger();
 }
 
 void GdbEngine::handleInferiorStarted()
 {
+    debugMessage(_("INFERIOR STARTED"));
     qq->notifyInferiorRunning();
 }
 
@@ -4251,8 +4221,8 @@ void GdbEngine::handleInferiorShutDown()
 void GdbEngine::handleInferiorShutdownFailed(const QString &msg)
 {
     debugMessage(_("INFERIOR SHUTDOWN FAILED"));
-    showMessageBox(QMessageBox::Critical, tr("Error"),
-        tr("Inferior shutdown failed:\n") + msg);
+    showMessageBox(QMessageBox::Critical,
+        tr("Inferior shutdown failed"), msg);
     qq->notifyInferiorExited();
     m_manager->exitDebugger();
 }
@@ -4266,8 +4236,8 @@ void GdbEngine::handleAdapterShutDown()
 void GdbEngine::handleAdapterShutdownFailed(const QString &msg)
 {
     debugMessage(_("ADAPTER SHUTDOWN FAILED"));
-    showMessageBox(QMessageBox::Critical, tr("Error"),
-        tr("Inferior shutdown failed:\n") + msg);
+    showMessageBox(QMessageBox::Critical,
+        tr("Inferior shutdown failed"), msg);
     qq->notifyInferiorExited();
 }
 
diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h
index bc25ffbf3e8722e70287abbfac0e63ed40c0827c..d39546f9b812f3ea9b4194f91323cc0bd63b9d5b 100644
--- a/src/plugins/debugger/gdb/gdbengine.h
+++ b/src/plugins/debugger/gdb/gdbengine.h
@@ -62,12 +62,14 @@ class IDebuggerManagerAccessForEngines;
 class GdbResultRecord;
 class GdbMi;
 
-class WatchData;
 class BreakpointData;
+class WatchData;
 
+class AttachGdbAdapter;
+class CoreGdbAdapter;
 class PlainGdbAdapter;
-class TrkGdbAdapter;
 class RemoteGdbAdapter;
+class TrkGdbAdapter;
 
 enum DebuggingHelperState
 {
@@ -91,9 +93,11 @@ signals:
     void applicationOutputAvailable(const QString &output);
 
 private:
+    friend class AttachGdbAdapter;
+    friend class CoreGdbAdapter;
     friend class PlainGdbAdapter;
-    friend class TrkGdbAdapter;
     friend class RemoteGdbAdapter;
+    friend class TrkGdbAdapter;
 
     //
     // IDebuggerEngine implementation
@@ -224,6 +228,7 @@ private:
     void postCommandHelper(const GdbCommand &cmd);
     void setTokenBarrier();
 
+    void updateAll();
     void updateLocals();
 
 private slots:
@@ -249,7 +254,6 @@ private:
     int terminationIndex(const QByteArray &buffer, int &length);
     void handleResponse(const QByteArray &buff);
     void handleStart(const GdbResultRecord &response, const QVariant &);
-    //void handleAttach(const GdbResultRecord &, const QVariant &);
     void handleAqcuiredInferior();
     void handleAsyncOutput(const GdbMi &data);
     void handleStop1(const GdbResultRecord &, const QVariant &cookie);
@@ -258,7 +262,6 @@ private:
     void handleResultRecord(const GdbResultRecord &response);
     void handleFileExecAndSymbols(const GdbResultRecord &response, const QVariant &);
     void handleExecContinue(const GdbResultRecord &response, const QVariant &);
-    //void handleExecRun(const GdbResultRecord &response, const QVariant &);
     void handleExecJumpToLine(const GdbResultRecord &response, const QVariant &);
     void handleExecRunToFunction(const GdbResultRecord &response, const QVariant &);
     void handleInfoShared(const GdbResultRecord &response, const QVariant &);
@@ -267,9 +270,7 @@ private:
     void handleShowVersion(const GdbResultRecord &response, const QVariant &);
     void handleQueryPwd(const GdbResultRecord &response, const QVariant &);
     void handleQuerySources(const GdbResultRecord &response, const QVariant &);
-    void handleTargetCore(const GdbResultRecord &, const QVariant &);
     void handleExit(const GdbResultRecord &, const QVariant &);
-    void handleDetach(const GdbResultRecord &, const QVariant &);
     //void handleSetTargetAsync(const GdbResultRecord &, const QVariant &);
     //void handleTargetRemote(const GdbResultRecord &, const QVariant &);
     void handleWatchPoint(const GdbResultRecord &, const QVariant &);
@@ -281,7 +282,7 @@ private:
         { m_manager->showStatusMessage(msg, timeout); }
     int status() const { return m_manager->status(); }
     QMainWindow *mainWindow() const { return m_manager->mainWindow(); }
-    DebuggerStartMode startMode() const { return m_startParameters->startMode; }
+    DebuggerStartMode startMode() const;
     qint64 inferiorPid() const { return m_manager->inferiorPid(); }
 
     void handleChildren(const WatchData &parent, const GdbMi &child,
@@ -293,8 +294,6 @@ private:
 
     QByteArray m_inbuffer;
 
-    AbstractGdbAdapter *m_gdbAdapter;
-
     QHash<int, GdbCommand> m_cookieForToken;
     QHash<int, QByteArray> m_customOutputForToken;
 
@@ -412,6 +411,8 @@ private:
     void setWatchDataType(WatchData &data, const GdbMi &mi);
     void setWatchDataDisplayedType(WatchData &data, const GdbMi &mi);
     void setLocals(const QList<GdbMi> &locals);
+    void connectDebuggingHelperActions();
+    void disconnectDebuggingHelperActions();
    
     bool startModeAllowsDumpers() const;
     QString parseDisassembler(const GdbMi &lines);
@@ -431,7 +432,6 @@ private:
     Continuation m_continuationAfterDone;
     void handleInitialBreakpointsSet();
 
-    bool m_waitingForFirstBreakpointToBeHit;
     bool m_modulesListOutdated;
 
     QList<GdbCommand> m_commandsToRunOnTemporaryBreak;
@@ -441,10 +441,13 @@ private:
     DebuggerStartParametersPtr m_startParameters;
     // make sure to re-initialize new members in initializeVariables();
 
-    // only one of those is active at a given time
-    PlainGdbAdapter *m_plainAdapter;
-    TrkGdbAdapter *m_trkAdapter;
-    RemoteGdbAdapter *m_remoteAdapter;
+    // only one of those is active at a given time, available in m_gdbAdapter
+    AbstractGdbAdapter *m_gdbAdapter;  // pointer to one listed below
+    AttachGdbAdapter *m_attachAdapter; // owned
+    CoreGdbAdapter *m_coreAdapter;     // owned
+    PlainGdbAdapter *m_plainAdapter;   // owned
+    RemoteGdbAdapter *m_remoteAdapter; // owned
+    TrkGdbAdapter *m_trkAdapter;       // owned
     
 public:
     void showMessageBox(int icon, const QString &title, const QString &text);
diff --git a/src/plugins/debugger/gdb/plaingdbadapter.cpp b/src/plugins/debugger/gdb/plaingdbadapter.cpp
index 68630fff7a73afa0b016ff4c065e361cfcba5f62..fee4c3974c9f0ae967727b15c4b9abeaa3a10bee 100644
--- a/src/plugins/debugger/gdb/plaingdbadapter.cpp
+++ b/src/plugins/debugger/gdb/plaingdbadapter.cpp
@@ -225,11 +225,6 @@ void PlainGdbAdapter::startInferior()
 void PlainGdbAdapter::interruptInferior()
 {
     debugMessage(_("TRYING TO INTERUPT INFERIOR"));
-    if (m_engine->startMode() == StartRemote) {
-        m_engine->postCommand(_("-exec-interrupt"));
-        return;
-    }
-
     const qint64 attachedPID = m_engine->inferiorPid();
     if (attachedPID <= 0) {
         debugMessage(_("TRYING TO INTERRUPT INFERIOR BEFORE PID WAS OBTAINED"));
diff --git a/src/plugins/debugger/gdb/remotegdbadapter.cpp b/src/plugins/debugger/gdb/remotegdbadapter.cpp
index 85aaaa318223e24aeb1f7ff7164f8c77ebebe5c1..beed13ac93115b95569c5f78a320bd8a572cb9ea 100644
--- a/src/plugins/debugger/gdb/remotegdbadapter.cpp
+++ b/src/plugins/debugger/gdb/remotegdbadapter.cpp
@@ -31,10 +31,8 @@
 
 #include "debuggeractions.h"
 #include "gdbengine.h"
-#include "procinterrupt.h"
 
 #include <utils/qtcassert.h>
-#include <coreplugin/icore.h>
 
 #include <QtCore/QFileInfo>
 #include <QtGui/QMessageBox>
@@ -77,12 +75,11 @@ RemoteGdbAdapter::RemoteGdbAdapter(GdbEngine *engine, QObject *parent)
         this, SLOT(readUploadStandardError()));
 }
 
-void RemoteGdbAdapter::startAdapter(const DebuggerStartParametersPtr &sp)
+void RemoteGdbAdapter::startAdapter()
 {
     QTC_ASSERT(state() == AdapterNotRunning, qDebug() << state());
     setState(AdapterStarting);
     debugMessage(_("TRYING TO START ADAPTER"));
-    m_startParameters = sp;
 
     QStringList gdbArgs;
     gdbArgs.prepend(_("mi"));
@@ -95,25 +92,25 @@ void RemoteGdbAdapter::startAdapter(const DebuggerStartParametersPtr &sp)
     }
     gdbArgs.prepend(_("--tty=") + m_engine->m_outputCollector.serverName());
 
-    if (!m_startParameters->workingDir.isEmpty())
-        setWorkingDirectory(m_startParameters->workingDir);
-    if (!m_startParameters->environment.isEmpty())
-        setEnvironment(m_startParameters->environment);
+    if (!startParameters().workingDir.isEmpty())
+        setWorkingDirectory(startParameters().workingDir);
+    if (!startParameters().environment.isEmpty())
+        setEnvironment(startParameters().environment);
 
     QString location = theDebuggerStringSetting(GdbLocation);
 
 /*  
     // FIXME: make asynchroneouis
     // Start the remote server
-    if (m_startParameters->serverStartScript.isEmpty()) {
+    if (startParameters().serverStartScript.isEmpty()) {
         showStatusMessage(_("No server start script given. "
             "Assuming server runs already."));
     } else {
-        if (!m_startParameters->workingDir.isEmpty())
-            m_uploadProc.setWorkingDirectory(m_startParameters->workingDir);
-        if (!m_startParameters->environment.isEmpty())
-            m_uploadProc.setEnvironment(m_startParameters->environment);
-        m_uploadProc.start(_("/bin/sh ") + m_startParameters->serverStartScript);
+        if (!startParameters().workingDir.isEmpty())
+            m_uploadProc.setWorkingDirectory(startParameters().workingDir);
+        if (!startParameters().environment.isEmpty())
+            m_uploadProc.setEnvironment(startParameters().environment);
+        m_uploadProc.start(_("/bin/sh ") + startParameters().serverStartScript);
         m_uploadProc.waitForStarted();
     }
 */
@@ -182,9 +179,9 @@ void RemoteGdbAdapter::prepareInferior()
 {
     QTC_ASSERT(state() == AdapterStarted, qDebug() << state());
     setState(InferiorPreparing);
-    if (!m_startParameters->processArgs.isEmpty())
+    if (!startParameters().processArgs.isEmpty())
         m_engine->postCommand(_("-exec-arguments ")
-            + m_startParameters->processArgs.join(_(" ")));
+            + startParameters().processArgs.join(_(" ")));
     QFileInfo fi(m_engine->startParameters().executable);
     m_engine->postCommand(_("-file-exec-and-symbols \"%1\"").arg(fi.absoluteFilePath()),
         CB(handleFileExecAndSymbols));
@@ -230,20 +227,7 @@ void RemoteGdbAdapter::handleExecRun(const GdbResultRecord &response, const QVar
 
 void RemoteGdbAdapter::interruptInferior()
 {
-    debugMessage(_("TRYING TO INTERUPT INFERIOR"));
-    if (m_engine->startMode() == StartRemote) {
-        m_engine->postCommand(_("-exec-interrupt"));
-        return;
-    }
-
-    const qint64 attachedPID = m_engine->inferiorPid();
-    if (attachedPID <= 0) {
-        debugMessage(_("TRYING TO INTERRUPT INFERIOR BEFORE PID WAS OBTAINED"));
-        return;
-    }
-
-    if (!interruptProcess(attachedPID))
-        debugMessage(_("CANNOT INTERRUPT %1").arg(attachedPID));
+    m_engine->postCommand(_("-exec-interrupt"));
 }
 
 void RemoteGdbAdapter::shutdown()
diff --git a/src/plugins/debugger/gdb/remotegdbadapter.h b/src/plugins/debugger/gdb/remotegdbadapter.h
index 054d782fef8798e1d2572da273a4ee5fd9ec3166..cd15b87e5996648f1579ca2b07d54173eb93498e 100644
--- a/src/plugins/debugger/gdb/remotegdbadapter.h
+++ b/src/plugins/debugger/gdb/remotegdbadapter.h
@@ -52,6 +52,7 @@ class RemoteGdbAdapter : public AbstractGdbAdapter
 public:
     RemoteGdbAdapter(GdbEngine *engine, QObject *parent = 0);
 
+private:
     QByteArray readAllStandardError() { return m_gdbProc.readAllStandardError(); }
     QByteArray readAllStandardOutput() { return m_gdbProc.readAllStandardOutput(); }
     qint64 write(const char *data) { return m_gdbProc.write(data); }
@@ -59,17 +60,16 @@ public:
     void setEnvironment(const QStringList &env) { m_gdbProc.setEnvironment(env); }
     bool isTrkAdapter() const { return false; }
 
-    void startAdapter(const DebuggerStartParametersPtr &sp);
+    void startAdapter();
     void prepareInferior();
     void startInferior();
     void interruptInferior();
     void shutdown();
 
-    void readUploadStandardOutput();
-    void readUploadStandardError();
-    void uploadProcError(QProcess::ProcessError error);
+    Q_SLOT void readUploadStandardOutput();
+    Q_SLOT void readUploadStandardError();
+    Q_SLOT void uploadProcError(QProcess::ProcessError error);
 
-private:
     void handleFileExecAndSymbols(const GdbResultRecord &, const QVariant &);
     void handleKill(const GdbResultRecord &, const QVariant &);
     void handleExit(const GdbResultRecord &, const QVariant &);
@@ -80,7 +80,6 @@ private:
     Q_SLOT void handleGdbStarted();
 
     QProcess m_gdbProc;
-    DebuggerStartParametersPtr m_startParameters;
     QProcess m_uploadProc;
 };
 
diff --git a/src/plugins/debugger/script/scriptengine.cpp b/src/plugins/debugger/script/scriptengine.cpp
index d73dc189b62f6e8e845cb93a8c4afab85e5f4241..7f1caec3560b8de532bb950c60af6cf920b5077b 100644
--- a/src/plugins/debugger/script/scriptengine.cpp
+++ b/src/plugins/debugger/script/scriptengine.cpp
@@ -65,10 +65,6 @@
 #include <QtScript/QScriptValue>
 #include <QtScript/QScriptValueIterator>
 
-using namespace Debugger;
-using namespace Debugger::Internal;
-using namespace Debugger::Constants;
-
 //#define DEBUG_SCRIPT 1
 #if DEBUG_SCRIPT
 #   define SDEBUG(s) qDebug() << s
@@ -77,13 +73,17 @@ using namespace Debugger::Constants;
 #endif
 # define XSDEBUG(s) qDebug() << s
 
+
+namespace Debugger {
+namespace Internal {
+
 ///////////////////////////////////////////////////////////////////////
 //
 // ScriptEngine
 //
 ///////////////////////////////////////////////////////////////////////
 
-class Debugger::Internal::ScriptAgent : public QScriptEngineAgent
+class ScriptAgent : public QScriptEngineAgent
 {
 public:
     ScriptAgent(ScriptEngine *debugger, QScriptEngine *script);
@@ -733,8 +733,10 @@ void ScriptEngine::updateSubItem(const WatchData &data0)
     QTC_ASSERT(false, return);
 }
 
-IDebuggerEngine *createScriptEngine(DebuggerManager *parent, QList<Core::IOptionsPage*> *)
+IDebuggerEngine *createScriptEngine(DebuggerManager *parent)
 {
     return new ScriptEngine(parent);
 }
 
+} // namespace Internal
+} // namespace Debugger
diff --git a/src/plugins/debugger/tcf/tcfengine.cpp b/src/plugins/debugger/tcf/tcfengine.cpp
index fe0eebf96a9e6b0bbfdd792addb4625b4b2964d1..cc88654ee2d717083922d4781810a11f9cd07e38 100644
--- a/src/plugins/debugger/tcf/tcfengine.cpp
+++ b/src/plugins/debugger/tcf/tcfengine.cpp
@@ -57,11 +57,6 @@
 
 #include <QtNetwork/QTcpSocket>
 
-
-using namespace Debugger;
-using namespace Debugger::Internal;
-using namespace Debugger::Constants;
-
 #define DEBUG_TCF 1
 #if DEBUG_TCF
 #   define SDEBUG(s) qDebug() << s
@@ -74,7 +69,9 @@ using namespace Debugger::Constants;
 #define STRINGIFY(x) STRINGIFY_INTERNAL(x)
 #define CB(callback) &TcfEngine::callback, STRINGIFY(callback)
 
-QByteArray C(const QByteArray &ba1,
+//#define USE_CONGESTION_CONTROL
+
+static QByteArray C(const QByteArray &ba1,
     const QByteArray &ba2 = QByteArray(),
     const QByteArray &ba3 = QByteArray(),
     const QByteArray &ba4 = QByteArray(),
@@ -88,9 +85,8 @@ QByteArray C(const QByteArray &ba1,
     return result;
 }
 
-
-//#define USE_CONGESTION_CONTROL
-
+namespace Debugger {
+namespace Internal {
 
 ///////////////////////////////////////////////////////////////////////
 //
@@ -571,8 +567,10 @@ void TcfEngine::updateSubItem(const WatchData &data0)
     QTC_ASSERT(false, return);
 }
 
-IDebuggerEngine *createTcfEngine(DebuggerManager *parent, QList<Core::IOptionsPage*> *)
+IDebuggerEngine *createTcfEngine(DebuggerManager *parent)
 {
     return new TcfEngine(parent);
 }
 
+} // namespace Internal
+} // namespace Debugger
diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp
index ac52e47baa369ee5055bf947f5c70d1d0daa5af5..8f6bba03ac1e8ca28516d28b71faa4a488d44d0e 100644
--- a/src/plugins/debugger/watchhandler.cpp
+++ b/src/plugins/debugger/watchhandler.cpp
@@ -702,7 +702,8 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const
         }
 
         case Qt::ToolTipRole:
-            return data.toToolTip();
+            return theDebuggerBoolSetting(UseToolTipsInLocalsView)
+                ? data.toToolTip() : QVariant();
 
         case Qt::ForegroundRole: {
             static const QVariant red(QColor(200, 0, 0));
diff --git a/src/plugins/duieditor/duidocument.cpp b/src/plugins/duieditor/duidocument.cpp
index 0fb00d48c5066b81c3752d84eb1743c6425d4603..f3b1761e56237c24e00dcb46fd448ad7d9890679 100644
--- a/src/plugins/duieditor/duidocument.cpp
+++ b/src/plugins/duieditor/duidocument.cpp
@@ -60,6 +60,8 @@ DuiDocument::~DuiDocument()
 
     if (_pool)
         delete _pool;
+
+    qDeleteAll(_ids.values());
 }
 
 DuiDocument::Ptr DuiDocument::create(const QString &fileName)
@@ -109,7 +111,7 @@ bool DuiDocument::parse()
 
     if (_parsedCorrectly && _program) {
         Internal::IdCollector collect;
-        _ids = collect(_program);
+        _ids = collect(_fileName, _program);
     }
 
     return _parsedCorrectly;
diff --git a/src/plugins/duieditor/duidocument.h b/src/plugins/duieditor/duidocument.h
index 86c88d1b62286fcfc965f56d9ec8d69e2a67da60..94fa1af681f168ae4503f766277088e68977495f 100644
--- a/src/plugins/duieditor/duidocument.h
+++ b/src/plugins/duieditor/duidocument.h
@@ -36,9 +36,9 @@
 #include <QtCore/QString>
 
 #include "duieditor_global.h"
-
 #include "qmljsengine_p.h"
 #include "qmljsastfwd_p.h"
+#include "qmlsymbol.h"
 
 namespace DuiEditor {
 
@@ -47,7 +47,7 @@ class DUIEDITOR_EXPORT DuiDocument
 public:
     typedef QSharedPointer<DuiDocument> Ptr;
     typedef QList<DuiDocument::Ptr> PtrList;
-    typedef QMap<QString, QPair<QmlJS::AST::SourceLocation, QmlJS::AST::Node*> > IdTable;
+    typedef QMap<QString, QmlIdSymbol*> IdTable;
 
 protected:
     DuiDocument(const QString &fileName);
diff --git a/src/plugins/duieditor/duieditor.cpp b/src/plugins/duieditor/duieditor.cpp
index 088d323cddc26f31ef0c985242588a3667acb700..2d37da2534095ae51e12f87fe52e818347048b0c 100644
--- a/src/plugins/duieditor/duieditor.cpp
+++ b/src/plugins/duieditor/duieditor.cpp
@@ -39,11 +39,10 @@
 #include "qmljsengine_p.h"
 #include "qmlexpressionundercursor.h"
 #include "qmllookupcontext.h"
-#include "resolveqmlexpression.h"
+#include "qmlresolveexpression.h"
 #include "rewriter_p.h"
 
 #include "idcollector.h"
-#include "navigationtokenfinder.h"
 
 #include <coreplugin/icore.h>
 #include <coreplugin/actionmanager/actionmanager.h>
@@ -57,7 +56,6 @@
 #include <utils/uncommentselection.h>
 
 #include <QtCore/QTimer>
-#include <QtCore/QtDebug>
 
 #include <QtGui/QMenu>
 #include <QtGui/QComboBox>
@@ -704,7 +702,7 @@ void ScriptEditor::createToolBar(ScriptEditorEditable *editable)
     toolBar->insertWidget(actions.first(), m_methodCombo);
 }
 
-TextEditor::BaseTextEditor::Link ScriptEditor::findLinkAt(const QTextCursor &cursor, bool resolveTarget)
+TextEditor::BaseTextEditor::Link ScriptEditor::findLinkAt(const QTextCursor &cursor, bool /*resolveTarget*/)
 {
     Link link;
 
@@ -716,34 +714,25 @@ TextEditor::BaseTextEditor::Link ScriptEditor::findLinkAt(const QTextCursor &cur
     if (!doc)
         return link;
 
-    NavigationTokenFinder finder;
-    finder(doc, cursor.position(), snapshot);
-    if (finder.targetFound()) {
-        link.fileName = finder.fileName();
-        link.pos = finder.linkPosition();
-        link.length = finder.linkLength();
+    QmlExpressionUnderCursor expressionUnderCursor;
+    expressionUnderCursor(cursor, doc->program());
 
-        if (resolveTarget) {
-            link.line = finder.targetLine();
-            link.column = finder.targetColumn() - 1;
-        }
-    }
+    QmlLookupContext context(expressionUnderCursor.expressionScopes(), doc, snapshot);
+    QmlResolveExpression resolve(context);
+    QmlSymbol *symbol = resolve(expressionUnderCursor.expressionNode());
 
-//    QmlExpressionUnderCursor expressionUnderCursor;
-//    expressionUnderCursor(cursor, doc->program());
-//
-//    QmlLookupContext context(expressionUnderCursor.expressionScopes(),
-//                             expressionUnderCursor.expressionNode(),
-//                             doc, snapshot);
-//
-//    ResolveQmlExpression resolve(context);
-//    if (QmlLookupContext::Symbol *symbol = resolve(expressionUnderCursor.expressionNode())) {
-//        if (UiObjectMember *member = static_cast<UiObjectMember *>(symbol)) { // ### FIXME: don't use static_cast<>
-//            const int begin = member->firstSourceLocation().begin();
-//            const int end = member->lastSourceLocation().end();
-//            qDebug() << doc->source().mid(begin, end - begin);
-//        }
-//    }
+    if (!symbol)
+        return link;
+
+    if (const QmlSymbolFromFile *target = symbol->asSymbolFromFile()) {
+        link.pos = expressionUnderCursor.expressionOffset();
+        link.length = expressionUnderCursor.expressionLength();
+        link.fileName = target->fileName();
+        link.line = target->line();
+        link.column = target->column();
+        if (link.column > 0)
+            --link.column;
+    }
 
     return link;
 }
diff --git a/src/plugins/duieditor/duieditor.pro b/src/plugins/duieditor/duieditor.pro
index fc1ffaf4034fb4870ec9dced4b7e51d0c38858a4..7dd25ac1107a892d1099ce720d883c83274652ea 100644
--- a/src/plugins/duieditor/duieditor.pro
+++ b/src/plugins/duieditor/duieditor.pro
@@ -22,11 +22,11 @@ HEADERS += duieditor.h \
     duieditor_global.h \
     duimodelmanager.h \
     duicodeformatter.h \
-    navigationtokenfinder.h \
     idcollector.h \
     qmlexpressionundercursor.h \
     qmllookupcontext.h \
-    resolveqmlexpression.h
+    qmlresolveexpression.h \
+    qmlsymbol.h
 SOURCES += duieditor.cpp \
     duieditorfactory.cpp \
     duieditorplugin.cpp \
@@ -39,9 +39,9 @@ SOURCES += duieditor.cpp \
     duimodelmanagerinterface.cpp \
     duimodelmanager.cpp \
     duicodeformatter.cpp \
-    navigationtokenfinder.cpp \
     idcollector.cpp \
     qmlexpressionundercursor.cpp \
     qmllookupcontext.cpp \
-    resolveqmlexpression.cpp
+    qmlresolveexpression.cpp \
+    qmlsymbol.cpp
 RESOURCES += duieditor.qrc
diff --git a/src/plugins/duieditor/idcollector.cpp b/src/plugins/duieditor/idcollector.cpp
index 97536aa7193fcbbea3aa8d34526df9972ad313cb..509fdc09b91fc9695397f7699502bb3f876433f3 100644
--- a/src/plugins/duieditor/idcollector.cpp
+++ b/src/plugins/duieditor/idcollector.cpp
@@ -4,10 +4,12 @@
 
 using namespace QmlJS;
 using namespace QmlJS::AST;
+using namespace DuiEditor;
 using namespace DuiEditor::Internal;
 
-QMap<QString, QPair<QmlJS::AST::SourceLocation, QmlJS::AST::Node*> > IdCollector::operator()(QmlJS::AST::UiProgram *ast)
+QMap<QString, QmlIdSymbol*> IdCollector::operator()(const QString &fileName, QmlJS::AST::UiProgram *ast)
 {
+    _fileName = fileName;
     _ids.clear();
 
     Node::accept(ast, this);
@@ -42,15 +44,21 @@ bool IdCollector::visit(QmlJS::AST::UiScriptBinding *ast)
     if (!(ast->qualifiedId->next) && ast->qualifiedId->name->asString() == "id")
         if (ExpressionStatement *e = cast<ExpressionStatement*>(ast->statement))
             if (IdentifierExpression *i = cast<IdentifierExpression*>(e->expression))
-                addId(i->name, i->identifierToken);
+                addId(i->name->asString(), ast);
 
     return false;
 }
 
-void IdCollector::addId(QmlJS::NameId* id, const QmlJS::AST::SourceLocation &idLocation)
+void IdCollector::addId(const QString &id, QmlJS::AST::UiScriptBinding *ast)
 {
-    const QString idString = id->asString();
+    if (!_ids.contains(id)) {
+        Node *parent = _scopes.top();
 
-    if (!_ids.contains(idString))
-        _ids[idString] = qMakePair(idLocation, _scopes.top());
+        if (UiObjectBinding *binding = cast<UiObjectBinding*>(parent))
+            _ids[id] = new QmlIdSymbol(_fileName, ast, QmlSymbolFromFile(_fileName, binding));
+        else if (UiObjectDefinition *definition = cast<UiObjectDefinition*>(parent))
+            _ids[id] = new QmlIdSymbol(_fileName, ast, QmlSymbolFromFile(_fileName, definition));
+        else
+            Q_ASSERT(!"Unknown parent for id");
+    }
 }
diff --git a/src/plugins/duieditor/idcollector.h b/src/plugins/duieditor/idcollector.h
index 91e2a1fed86bde082d0ccad59fc1788aa6bdaeda..17a7c547b92459d97b97e79b66f36736818a58cd 100644
--- a/src/plugins/duieditor/idcollector.h
+++ b/src/plugins/duieditor/idcollector.h
@@ -7,8 +7,7 @@
 #include <QString>
 
 #include "qmljsastvisitor_p.h"
-
-namespace QmlJS { class NameId; }
+#include "qmlsymbol.h"
 
 namespace DuiEditor {
 namespace Internal {
@@ -16,7 +15,7 @@ namespace Internal {
 class IdCollector: protected QmlJS::AST::Visitor
 {
 public:
-    QMap<QString, QPair<QmlJS::AST::SourceLocation, QmlJS::AST::Node*> > operator()(QmlJS::AST::UiProgram *ast);
+    QMap<QString, QmlIdSymbol*> operator()(const QString &fileName, QmlJS::AST::UiProgram *ast);
 
 protected:
     virtual bool visit(QmlJS::AST::UiObjectBinding *ast);
@@ -27,10 +26,11 @@ protected:
     virtual void endVisit(QmlJS::AST::UiObjectDefinition *);
 
 private:
-    void addId(QmlJS::NameId* id, const QmlJS::AST::SourceLocation &idLocation);
+    void addId(const QString &id, QmlJS::AST::UiScriptBinding *ast);
 
 private:
-    QMap<QString, QPair<QmlJS::AST::SourceLocation, QmlJS::AST::Node*> > _ids;
+    QString _fileName;
+    QMap<QString, QmlIdSymbol*> _ids;
     QStack<QmlJS::AST::Node *> _scopes;
 };
 
diff --git a/src/plugins/duieditor/navigationtokenfinder.h b/src/plugins/duieditor/navigationtokenfinder.h
deleted file mode 100644
index a79b8adcda0736a5736d90805fa3453759fe7542..0000000000000000000000000000000000000000
--- a/src/plugins/duieditor/navigationtokenfinder.h
+++ /dev/null
@@ -1,75 +0,0 @@
-#ifndef NAVIGATIONTOKENFINDER_H
-#define NAVIGATIONTOKENFINDER_H
-
-#include <QMap>
-#include <QStack>
-#include <QString>
-#include <QStringList>
-
-#include "duidocument.h"
-#include "qmljsastvisitor_p.h"
-
-namespace QmlJS {
-    class NameId;
-} // namespace QmlJS
-
-namespace DuiEditor {
-namespace Internal {
-
-class NavigationTokenFinder: protected QmlJS::AST::Visitor
-{
-public:
-    void operator()(const DuiDocument::Ptr &doc, int position, const Snapshot &snapshot);
-
-    bool targetFound() const { return _targetLine != -1; }
-    bool linkFound() const { return _linkPosition != -1; }
-
-    int linkPosition() const { return _linkPosition; }
-    int linkLength() const { return _linkLength; }
-    QString fileName() const { return _fileName; }
-    int targetLine() const { return _targetLine; }
-    int targetColumn() const { return _targetColumn; }
-
-protected:
-    virtual bool visit(QmlJS::AST::Block *ast);
-    virtual bool visit(QmlJS::AST::FieldMemberExpression *ast);
-    virtual bool visit(QmlJS::AST::IdentifierExpression *ast);
-    virtual bool visit(QmlJS::AST::UiArrayBinding *ast);
-    virtual bool visit(QmlJS::AST::UiImportList *);
-    virtual bool visit(QmlJS::AST::UiPublicMember *ast);
-    virtual bool visit(QmlJS::AST::UiObjectBinding *ast);
-    virtual bool visit(QmlJS::AST::UiObjectDefinition *ast);
-    virtual bool visit(QmlJS::AST::UiScriptBinding *ast);
-    virtual bool visit(QmlJS::AST::UiSourceElement *ast);
-
-    virtual void endVisit(QmlJS::AST::Block *);
-    virtual void endVisit(QmlJS::AST::UiObjectBinding *);
-    virtual void endVisit(QmlJS::AST::UiObjectDefinition *);
-
-private:
-    void checkType(QmlJS::AST::UiQualifiedId *ast);
-    bool findInJS(const QStringList &qualifiedId, QmlJS::AST::Block *block);
-    bool findProperty(const QStringList &qualifiedId, QmlJS::AST::UiQualifiedId *typeId, QmlJS::AST::UiObjectMemberList *ast, int scopeLevel);
-    void findAsId(const QStringList &qualifiedId);
-    void findDeclaration(const QStringList &qualifiedId, int scopeLevel);
-    void findDeclaration(const QStringList &id);
-    void findTypeDeclaration(const QStringList &id);
-    void rememberLocation(const QmlJS::AST::SourceLocation &loc);
-    DuiDocument::Ptr findCustomType(const QStringList& qualifiedId) const;
-
-private:
-    quint32 _pos;
-    DuiDocument::Ptr _doc;
-    Snapshot _snapshot;
-    int _linkPosition;
-    int _linkLength;
-    QString _fileName;
-    int _targetLine;
-    int _targetColumn;
-    QStack<QmlJS::AST::Node*> _scopes;
-};
-
-} // namespace Internal
-} // namespace DuiEditor
-
-#endif // NAVIGATIONTOKENFINDER_H
diff --git a/src/plugins/duieditor/qmlexpressionundercursor.cpp b/src/plugins/duieditor/qmlexpressionundercursor.cpp
index 18df851ff078d618ba12e349d4ef33c5d5fd49e7..463f93ce61c211f09a6b5feae97a2edeb7afa7a3 100644
--- a/src/plugins/duieditor/qmlexpressionundercursor.cpp
+++ b/src/plugins/duieditor/qmlexpressionundercursor.cpp
@@ -19,6 +19,8 @@ void QmlExpressionUnderCursor::operator()(const QTextCursor &cursor,
 {
     _pos = cursor.position();
     _expressionNode = 0;
+    _expressionOffset = -1;
+    _expressionLength = -1;
     _scopes.clear();
 
     if (program)
@@ -37,11 +39,40 @@ void QmlExpressionUnderCursor::endVisit(QmlJS::AST::Block *)
     _scopes.pop();
 }
 
+bool QmlExpressionUnderCursor::visit(QmlJS::AST::FieldMemberExpression *ast)
+{
+    if (ast->identifierToken.offset <= _pos && _pos <= ast->identifierToken.end()) {
+        _expressionNode = ast;
+        _expressionOffset = ast->identifierToken.offset;
+        _expressionLength = ast->identifierToken.length;
+        _expressionScopes = _scopes;
+    }
+
+    return true;
+}
+
+bool QmlExpressionUnderCursor::visit(QmlJS::AST::IdentifierExpression *ast)
+{
+    if (ast->firstSourceLocation().offset <= _pos && _pos <= ast->lastSourceLocation().end()) {
+        _expressionNode = ast;
+        _expressionOffset = ast->firstSourceLocation().offset;
+        _expressionLength = ast->lastSourceLocation().end() - _expressionOffset;
+        _expressionScopes = _scopes;
+    }
+
+    return false;
+}
+
 bool QmlExpressionUnderCursor::visit(QmlJS::AST::UiObjectBinding *ast)
 {
+    Node::accept(ast->qualifiedId, this);
+    Node::accept(ast->qualifiedTypeNameId, this);
+
     _scopes.push(ast);
 
-    return true;
+    Node::accept(ast->initializer, this);
+
+    return false;
 }
 
 void QmlExpressionUnderCursor::endVisit(QmlJS::AST::UiObjectBinding *)
@@ -51,9 +82,13 @@ void QmlExpressionUnderCursor::endVisit(QmlJS::AST::UiObjectBinding *)
 
 bool QmlExpressionUnderCursor::visit(QmlJS::AST::UiObjectDefinition *ast)
 {
+    Node::accept(ast->qualifiedTypeNameId, this);
+
     _scopes.push(ast);
 
-    return true;
+    Node::accept(ast->initializer, this);
+
+    return false;
 }
 
 void QmlExpressionUnderCursor::endVisit(QmlJS::AST::UiObjectDefinition *)
@@ -61,12 +96,29 @@ void QmlExpressionUnderCursor::endVisit(QmlJS::AST::UiObjectDefinition *)
     _scopes.pop();
 }
 
-bool QmlExpressionUnderCursor::visit(QmlJS::AST::UiScriptBinding *ast)
+bool QmlExpressionUnderCursor::visit(QmlJS::AST::UiQualifiedId *ast)
 {
-    if (ast->firstSourceLocation().offset <= _pos && _pos <= ast->lastSourceLocation().end()) {
-        _expressionNode = ast;
-        _expressionScopes = _scopes;
+    if (ast->identifierToken.offset <= _pos) {
+        for (UiQualifiedId *iter = ast; iter; iter = iter->next) {
+            if (_pos <= iter->identifierToken.end()) {
+                // found it
+                _expressionNode = ast;
+                _expressionOffset = ast->identifierToken.offset;
+
+                for (UiQualifiedId *iter2 = ast; iter2; iter2 = iter2->next) {
+                    _expressionLength = iter2->identifierToken.end() - _expressionOffset;
+                }
+
+                _expressionScopes = _scopes;
+                break;
+            }
+        }
     }
 
     return false;
 }
+
+bool QmlExpressionUnderCursor::visit(QmlJS::AST::UiImport * /*ast*/)
+{
+    return false;
+}
diff --git a/src/plugins/duieditor/qmlexpressionundercursor.h b/src/plugins/duieditor/qmlexpressionundercursor.h
index 37dab1846236e57908eb637065c46aacd727630d..4642e54e3b010fa1a54074bd6a9af1b1aed743e0 100644
--- a/src/plugins/duieditor/qmlexpressionundercursor.h
+++ b/src/plugins/duieditor/qmlexpressionundercursor.h
@@ -22,11 +22,20 @@ public:
     QmlJS::AST::Node *expressionNode() const
     { return _expressionNode; }
 
+    int expressionOffset() const
+    { return _expressionOffset; }
+
+    int expressionLength() const
+    { return _expressionLength; }
+
 protected:
     virtual bool visit(QmlJS::AST::Block *ast);
+    virtual bool visit(QmlJS::AST::FieldMemberExpression *ast);
+    virtual bool visit(QmlJS::AST::IdentifierExpression *ast);
+    virtual bool visit(QmlJS::AST::UiImport *ast);
     virtual bool visit(QmlJS::AST::UiObjectBinding *ast);
     virtual bool visit(QmlJS::AST::UiObjectDefinition *ast);
-    virtual bool visit(QmlJS::AST::UiScriptBinding *ast);
+    virtual bool visit(QmlJS::AST::UiQualifiedId *ast);
 
     virtual void endVisit(QmlJS::AST::Block *);
     virtual void endVisit(QmlJS::AST::UiObjectBinding *);
@@ -36,6 +45,8 @@ private:
     QStack<QmlJS::AST::Node *> _scopes;
     QStack<QmlJS::AST::Node *> _expressionScopes;
     QmlJS::AST::Node *_expressionNode;
+    int _expressionOffset;
+    int _expressionLength;
     quint32 _pos;
 };
 
diff --git a/src/plugins/duieditor/qmllookupcontext.cpp b/src/plugins/duieditor/qmllookupcontext.cpp
index e967c342655f96ab9bcfdfadd35ee74a531aadf0..1847f35536179aa335b2b709c7d23e876cfb1c51 100644
--- a/src/plugins/duieditor/qmllookupcontext.cpp
+++ b/src/plugins/duieditor/qmllookupcontext.cpp
@@ -3,7 +3,7 @@
 
 #include "qmlexpressionundercursor.h"
 #include "qmllookupcontext.h"
-#include "resolveqmlexpression.h"
+#include "qmlresolveexpression.h"
 
 using namespace DuiEditor;
 using namespace DuiEditor::Internal;
@@ -11,28 +11,160 @@ using namespace QmlJS;
 using namespace QmlJS::AST;
 
 QmlLookupContext::QmlLookupContext(const QStack<QmlJS::AST::Node *> &scopes,
-                                   QmlJS::AST::Node *expressionNode,
                                    const DuiDocument::Ptr &doc,
                                    const Snapshot &snapshot):
         _scopes(scopes),
-        _expressionNode(expressionNode),
         _doc(doc),
         _snapshot(snapshot)
 {
 }
 
-QmlLookupContext::Symbol *QmlLookupContext::resolve(const QString &name) const
+QmlLookupContext::~QmlLookupContext()
 {
-    // ### TODO: look at property definitions
+    qDeleteAll(_temporarySymbols);
+}
+
+QmlSymbol *QmlLookupContext::resolve(const QString &name)
+{
+    // look at property definitions
+    if (QmlSymbol *propertySymbol = resolveProperty(name, _scopes.top(), _doc->fileName()))
+        return propertySymbol;
+
+    if (name == "parent") {
+        for (int i = _scopes.size() - 2; i >= 0; --i) {
+            Node *scope = _scopes.at(i);
+
+            if (UiObjectDefinition *definition = cast<UiObjectDefinition*>(scope))
+                return createSymbol(_doc->fileName(), definition);
+            else if (UiObjectBinding *binding = cast<UiObjectBinding*>(scope))
+                return createSymbol(_doc->fileName(), binding);
+        }
+
+        return 0;
+    }
 
     // look at the ids.
-    foreach (DuiDocument::Ptr doc, _snapshot) {
-        const DuiDocument::IdTable ids = doc->ids();
-        const QPair<SourceLocation, Node *> use = ids.value(name);
+    const DuiDocument::IdTable ids = _doc->ids();
+
+    if (ids.contains(name))
+        return ids[name];
+    else
+        return 0;
+}
+
+QmlSymbol *QmlLookupContext::createSymbol(const QString &fileName, QmlJS::AST::UiObjectMember *node)
+{
+    QmlSymbol *symbol = new QmlSymbolFromFile(fileName, node);
+    _temporarySymbols.append(symbol);
+    return symbol;
+}
 
-        if (Node *node = use.second)
-            return node;
+QmlSymbol *QmlLookupContext::resolveType(const QString &name, const QString &fileName)
+{
+    // TODO: handle import-as.
+    DuiDocument::Ptr document = _snapshot[fileName];
+    if (document.isNull())
+        return 0;
+
+    UiProgram *prog = document->program();
+    if (!prog)
+        return 0;
+
+    UiImportList *imports = prog->imports;
+    if (!imports)
+        return 0;
+
+    for (UiImportList *iter = imports; iter; iter = iter->next) {
+        UiImport *import = iter->import;
+        if (!import)
+            continue;
+
+        if (!(import->fileName))
+            continue;
+
+        const QString path = import->fileName->asString();
+
+        const QMap<QString, DuiDocument::Ptr> importedTypes = _snapshot.componentsDefinedByImportedDocuments(document, path);
+        if (importedTypes.contains(name)) {
+            DuiDocument::Ptr importedDoc = importedTypes.value(name);
+
+            UiProgram *importedProgram = importedDoc->program();
+            if (importedProgram && importedProgram->members && importedProgram->members->member)
+                return createSymbol(importedDoc->fileName(), importedProgram->members->member);
+        }
     }
 
     return 0;
 }
+
+QmlSymbol *QmlLookupContext::resolveProperty(const QString &name, Node *scope, const QString &fileName)
+{
+    UiQualifiedId *typeName = 0;
+
+    if (UiObjectBinding *binding = cast<UiObjectBinding*>(scope)) {
+        if (QmlSymbol *symbol = resolveProperty(name, binding->initializer, fileName))
+            return symbol;
+        else
+            typeName = binding->qualifiedTypeNameId;
+    } else if (UiObjectDefinition *definition = cast<UiObjectDefinition*>(scope)) {
+        if (QmlSymbol *symbol = resolveProperty(name, definition->initializer, fileName))
+            return symbol;
+        else
+            typeName = definition->qualifiedTypeNameId;
+    } // TODO: extend this to handle (JavaScript) block scopes.
+
+    if (typeName == 0)
+        return 0;
+
+    QmlSymbol *typeSymbol = resolveType(toString(typeName), fileName);
+    if (typeSymbol && typeSymbol->isSymbolFromFile()) {
+        return resolveProperty(name, typeSymbol->asSymbolFromFile()->node(), typeSymbol->asSymbolFromFile()->fileName());
+    }
+
+    return 0;
+}
+
+QmlSymbol *QmlLookupContext::resolveProperty(const QString &name, QmlJS::AST::UiObjectInitializer *initializer, const QString &fileName)
+{
+    if (!initializer)
+        return 0;
+
+    for (UiObjectMemberList *iter = initializer->members; iter; iter = iter->next) {
+        UiObjectMember *member = iter->member;
+        if (!member)
+            continue;
+
+        if (UiPublicMember *publicMember = cast<UiPublicMember*>(member)) {
+            if (name == publicMember->name->asString())
+                return createSymbol(fileName, publicMember);
+        } else if (UiObjectBinding *objectBinding = cast<UiObjectBinding*>(member)) {
+            if (name == toString(objectBinding->qualifiedId))
+                return createSymbol(fileName, objectBinding);
+        } else if (UiArrayBinding *arrayBinding = cast<UiArrayBinding*>(member)) {
+            if (name == toString(arrayBinding->qualifiedId))
+                return createSymbol(fileName, arrayBinding);
+        } else if (UiScriptBinding *scriptBinding = cast<UiScriptBinding*>(member)) {
+            if (name == toString(scriptBinding->qualifiedId))
+                return createSymbol(fileName, scriptBinding);
+        }
+    }
+
+    return 0;
+}
+
+QString QmlLookupContext::toString(UiQualifiedId *id)
+{
+    QString str;
+
+    for (UiQualifiedId *iter = id; iter; iter = iter->next) {
+        if (!(iter->name))
+            continue;
+
+        str.append(iter->name->asString());
+
+        if (iter->next)
+            str.append('.');
+    }
+
+    return str;
+}
diff --git a/src/plugins/duieditor/qmllookupcontext.h b/src/plugins/duieditor/qmllookupcontext.h
index 44f50c2eb0173843ccac4e58ebb91c77d810f783..4813f37e30cbea332daf8cf68ea86a8d9e2bd3ec 100644
--- a/src/plugins/duieditor/qmllookupcontext.h
+++ b/src/plugins/duieditor/qmllookupcontext.h
@@ -5,6 +5,7 @@
 
 #include "duidocument.h"
 #include "qmljsastvisitor_p.h"
+#include "qmlsymbol.h"
 
 namespace DuiEditor {
 namespace Internal {
@@ -13,19 +14,33 @@ class QmlLookupContext
 {
 public:
     QmlLookupContext(const QStack<QmlJS::AST::Node *> &scopes,
-                     QmlJS::AST::Node *expressionNode,
                      const DuiDocument::Ptr &doc,
                      const Snapshot &snapshot);
+    ~QmlLookupContext();
 
-    typedef QmlJS::AST::Node Symbol; // ### FIXME: this needs to be a class.
+    QmlSymbol *resolve(const QString &name);
+    QmlSymbol *resolveType(const QString &name)
+    { return resolveType(name, _doc->fileName()); }
+    QmlSymbol *resolveType(QmlJS::AST::UiQualifiedId *name)
+    { return resolveType(toString(name), _doc->fileName()); }
 
-    Symbol *resolve(const QString &name) const;
+    DuiDocument::Ptr document() const
+    { return _doc; }
+
+private:
+    QmlSymbol *createSymbol(const QString &fileName, QmlJS::AST::UiObjectMember *node);
+
+    QmlSymbol *resolveType(const QString &name, const QString &fileName);
+    QmlSymbol *resolveProperty(const QString &name, QmlJS::AST::Node *scope, const QString &fileName);
+    QmlSymbol *resolveProperty(const QString &name, QmlJS::AST::UiObjectInitializer *initializer, const QString &fileName);
+
+    static QString toString(QmlJS::AST::UiQualifiedId *id);
 
 private:
     QStack<QmlJS::AST::Node *> _scopes;
-    QmlJS::AST::Node *_expressionNode;
     DuiDocument::Ptr _doc;
     Snapshot _snapshot;
+    QList<QmlSymbol*> _temporarySymbols;
 };
 
 } // namespace Internal
diff --git a/src/plugins/duieditor/qmlresolveexpression.cpp b/src/plugins/duieditor/qmlresolveexpression.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..02fc21daa7f4004d9f69dacf25e4789b32324795
--- /dev/null
+++ b/src/plugins/duieditor/qmlresolveexpression.cpp
@@ -0,0 +1,130 @@
+#include "qmljsast_p.h"
+#include "qmljsengine_p.h"
+#include "qmlresolveexpression.h"
+
+using namespace DuiEditor;
+using namespace DuiEditor::Internal;
+using namespace QmlJS;
+using namespace QmlJS::AST;
+
+QmlResolveExpression::QmlResolveExpression(const QmlLookupContext &context)
+    : _context(context), _value(0)
+{
+}
+
+QmlResolveExpression::~QmlResolveExpression()
+{
+    qDeleteAll(_temporarySymbols);
+}
+
+QmlSymbol *QmlResolveExpression::typeOf(Node *node)
+{
+    QmlSymbol *previousValue = switchValue(0);
+    if (node)
+        node->accept(this);
+    return switchValue(previousValue);
+}
+
+
+QmlSymbol *QmlResolveExpression::switchValue(QmlSymbol *value)
+{
+    QmlSymbol *previousValue = _value;
+    _value = value;
+    return previousValue;
+}
+
+bool QmlResolveExpression::visit(IdentifierExpression *ast)
+{
+    const QString name = ast->name->asString();
+    _value = _context.resolve(name);
+    return false;
+}
+
+static inline bool matches(UiQualifiedId *candidate, const QString &wanted)
+{
+    if (!candidate)
+        return false;
+
+    if (!(candidate->name))
+        return false;
+
+    if (candidate->next)
+        return false; // TODO: verify this!
+
+    return wanted == candidate->name->asString();
+}
+
+bool QmlResolveExpression::visit(FieldMemberExpression *ast)
+{
+    const QString memberName = ast->name->asString();
+
+    const QmlSymbol *base = typeOf(ast->base);
+    if (!base)
+        return false;
+
+    if (base->isIdSymbol())
+        base = base->asIdSymbol()->parentNode();
+
+    UiObjectMemberList *members = 0;
+
+    if (const QmlSymbolFromFile *symbol = base->asSymbolFromFile()) {
+        Node *node = symbol->node();
+
+        if (UiObjectBinding *binding = cast<UiObjectBinding*>(node)) {
+            if (binding->initializer)
+                members = binding->initializer->members;
+        } else if (UiObjectDefinition *definition = cast<UiObjectDefinition*>(node)) {
+            if (definition->initializer)
+                members = definition->initializer->members;
+        }
+    }
+
+    for (UiObjectMemberList *it = members; it; it = it->next) {
+        UiObjectMember *member = it->member;
+
+        if (UiPublicMember *publicMember = cast<UiPublicMember *>(member)) {
+            if (publicMember->name && publicMember->name->asString() == memberName) {
+                _value = createPropertyDefinitionSymbol(publicMember);
+                break; // we're done.
+            }
+        } else if (UiObjectBinding *objectBinding = cast<UiObjectBinding*>(member)) {
+            if (matches(objectBinding->qualifiedId, memberName)) {
+                _value = createSymbolFromFile(objectBinding);
+                break; // we're done
+            }
+        } else if (UiScriptBinding *scriptBinding = cast<UiScriptBinding*>(member)) {
+            if (matches(scriptBinding->qualifiedId, memberName)) {
+                _value = createSymbolFromFile(scriptBinding);
+                break; // we're done
+            }
+        } else if (UiArrayBinding *arrayBinding = cast<UiArrayBinding*>(member)) {
+            if (matches(arrayBinding->qualifiedId, memberName)) {
+                _value = createSymbolFromFile(arrayBinding);
+                break; // we're done
+            }
+        }
+    }
+
+    return false;
+}
+
+bool QmlResolveExpression::visit(QmlJS::AST::UiQualifiedId *ast)
+{
+    _value = _context.resolveType(ast);
+
+    return false;
+}
+
+QmlPropertyDefinitionSymbol *QmlResolveExpression::createPropertyDefinitionSymbol(QmlJS::AST::UiPublicMember *ast)
+{
+    QmlPropertyDefinitionSymbol *symbol = new QmlPropertyDefinitionSymbol(_context.document()->fileName(), ast);
+    _temporarySymbols.append(symbol);
+    return symbol;
+}
+
+QmlSymbolFromFile *QmlResolveExpression::createSymbolFromFile(QmlJS::AST::UiObjectMember *ast)
+{
+    QmlSymbolFromFile *symbol = new QmlSymbolFromFile(_context.document()->fileName(), ast);
+    _temporarySymbols.append(symbol);
+    return symbol;
+}
diff --git a/src/plugins/duieditor/qmlresolveexpression.h b/src/plugins/duieditor/qmlresolveexpression.h
new file mode 100644
index 0000000000000000000000000000000000000000..0a568aa0c753ad999bd45ab17db77e02ff76b39e
--- /dev/null
+++ b/src/plugins/duieditor/qmlresolveexpression.h
@@ -0,0 +1,43 @@
+#ifndef QMLRESOLVEEXPRESSION_H
+#define QMLRESOLVEEXPRESSION_H
+
+#include "qmljsastvisitor_p.h"
+#include "qmllookupcontext.h"
+#include "qmlsymbol.h"
+
+namespace DuiEditor {
+namespace Internal {
+
+class QmlResolveExpression: protected QmlJS::AST::Visitor
+{
+public:
+    QmlResolveExpression(const QmlLookupContext &context);
+    ~QmlResolveExpression();
+
+    QmlSymbol *operator()(QmlJS::AST::Node *node)
+    { return typeOf(node); }
+
+protected:
+    using QmlJS::AST::Visitor::visit;
+
+    QmlSymbol *typeOf(QmlJS::AST::Node *node);
+    QmlSymbol *switchValue(QmlSymbol *symbol);
+
+    virtual bool visit(QmlJS::AST::FieldMemberExpression *ast);
+    virtual bool visit(QmlJS::AST::IdentifierExpression *ast);
+    virtual bool visit(QmlJS::AST::UiQualifiedId *ast);
+
+private:
+    QmlPropertyDefinitionSymbol *createPropertyDefinitionSymbol(QmlJS::AST::UiPublicMember *ast);
+    QmlSymbolFromFile *createSymbolFromFile(QmlJS::AST::UiObjectMember *ast);
+
+private:
+    QmlLookupContext _context;
+    QList<QmlSymbol*> _temporarySymbols;
+    QmlSymbol *_value;
+};
+
+} // namespace Internal
+} // namespace DuiEditor
+
+#endif // QMLRESOLVEEXPRESSION_H
diff --git a/src/plugins/duieditor/qmlsymbol.cpp b/src/plugins/duieditor/qmlsymbol.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..196262ff2f58b04482bf4ec0f268d205035f8eb2
--- /dev/null
+++ b/src/plugins/duieditor/qmlsymbol.cpp
@@ -0,0 +1,87 @@
+#include "qmljsast_p.h"
+#include "qmlsymbol.h"
+
+using namespace DuiEditor;
+using namespace QmlJS;
+using namespace QmlJS::AST;
+
+QmlSymbol::~QmlSymbol()
+{
+}
+
+bool QmlSymbol::isBuildInSymbol() const
+{ return asBuildInSymbol() != 0; }
+
+bool QmlSymbol::isSymbolFromFile() const
+{ return asSymbolFromFile() != 0; }
+
+bool QmlSymbol::isIdSymbol() const
+{ return asIdSymbol() != 0; }
+
+QmlBuildInSymbol const *QmlSymbol::asBuildInSymbol() const
+{ return 0; }
+
+QmlSymbolFromFile const *QmlSymbol::asSymbolFromFile() const
+{ return 0; }
+
+QmlIdSymbol const *QmlSymbol::asIdSymbol() const
+{ return 0; }
+
+QmlBuildInSymbol::~QmlBuildInSymbol()
+{}
+
+QmlBuildInSymbol const* QmlBuildInSymbol::asBuildInSymbol() const
+{ return this; }
+
+QmlSymbolFromFile::QmlSymbolFromFile(const QString &fileName, QmlJS::AST::UiObjectMember *node):
+        _fileName(fileName),
+        _node(node)
+{}
+
+QmlSymbolFromFile::~QmlSymbolFromFile()
+{}
+
+const QmlSymbolFromFile *QmlSymbolFromFile::asSymbolFromFile() const
+{ return this; }
+
+int QmlSymbolFromFile::line() const
+{ return _node->firstSourceLocation().startLine; }
+
+int QmlSymbolFromFile::column() const
+{ return _node->firstSourceLocation().startColumn; }
+
+QmlIdSymbol::QmlIdSymbol(const QString &fileName, QmlJS::AST::UiScriptBinding *idNode, const QmlSymbolFromFile &parentNode):
+        QmlSymbolFromFile(fileName, idNode),
+        _parentNode(parentNode)
+{}
+
+QmlIdSymbol::~QmlIdSymbol()
+{}
+
+QmlIdSymbol const *QmlIdSymbol::asIdSymbol() const
+{ return this; }
+
+int QmlIdSymbol::line() const
+{ return idNode()->statement->firstSourceLocation().startLine; }
+
+int QmlIdSymbol::column() const
+{ return idNode()->statement->firstSourceLocation().startColumn; }
+
+QmlJS::AST::UiScriptBinding *QmlIdSymbol::idNode() const
+{ return cast<UiScriptBinding*>(node()); }
+
+QmlPropertyDefinitionSymbol::QmlPropertyDefinitionSymbol(const QString &fileName, QmlJS::AST::UiPublicMember *propertyNode):
+        QmlSymbolFromFile(fileName, propertyNode)
+{}
+
+QmlPropertyDefinitionSymbol::~QmlPropertyDefinitionSymbol()
+{}
+
+int QmlPropertyDefinitionSymbol::line() const
+{ return propertyNode()->identifierToken.startLine; }
+
+int QmlPropertyDefinitionSymbol::column() const
+{ return propertyNode()->identifierToken.startColumn; }
+
+QmlJS::AST::UiPublicMember *QmlPropertyDefinitionSymbol::propertyNode() const
+{ return cast<UiPublicMember*>(node()); }
diff --git a/src/plugins/duieditor/qmlsymbol.h b/src/plugins/duieditor/qmlsymbol.h
new file mode 100644
index 0000000000000000000000000000000000000000..48509e6f6247e002090bb388911fa1107b0b2026
--- /dev/null
+++ b/src/plugins/duieditor/qmlsymbol.h
@@ -0,0 +1,92 @@
+#ifndef QMLSYMBOL_H
+#define QMLSYMBOL_H
+
+#include <QString>
+
+#include "qmljsastfwd_p.h"
+
+namespace DuiEditor {
+
+class QmlSymbol
+{
+public:
+    virtual ~QmlSymbol() = 0;
+
+    bool isBuildInSymbol() const;
+    bool isSymbolFromFile() const;
+    bool isIdSymbol() const;
+
+    virtual class QmlBuildInSymbol const *asBuildInSymbol() const;
+    virtual class QmlSymbolFromFile const *asSymbolFromFile() const;
+    virtual class QmlIdSymbol const *asIdSymbol() const;
+};
+
+class QmlBuildInSymbol: public QmlSymbol
+{
+public:
+    virtual ~QmlBuildInSymbol();
+
+    virtual QmlBuildInSymbol const *asBuildInSymbol() const;
+
+private:
+};
+
+class QmlSymbolFromFile: public QmlSymbol
+{
+public:
+    QmlSymbolFromFile(const QString &fileName, QmlJS::AST::UiObjectMember *node);
+    virtual ~QmlSymbolFromFile();
+
+    virtual QmlSymbolFromFile const *asSymbolFromFile() const;
+
+    QString fileName() const
+    { return _fileName; }
+
+    virtual int line() const;
+    virtual int column() const;
+
+    QmlJS::AST::UiObjectMember *node() const
+    { return _node; }
+
+private:
+    QString _fileName;
+    QmlJS::AST::UiObjectMember *_node;
+};
+
+class QmlIdSymbol: public QmlSymbolFromFile
+{
+public:
+    QmlIdSymbol(const QString &fileName, QmlJS::AST::UiScriptBinding *idNode, const QmlSymbolFromFile &parentNode);
+    virtual ~QmlIdSymbol();
+
+    QmlIdSymbol const *asIdSymbol() const;
+
+    virtual int line() const;
+    virtual int column() const;
+
+    QmlSymbolFromFile const *parentNode() const
+    { return &_parentNode; }
+
+private:
+    QmlJS::AST::UiScriptBinding *idNode() const;
+
+private:
+    QmlSymbolFromFile _parentNode;
+};
+
+class QmlPropertyDefinitionSymbol: public QmlSymbolFromFile
+{
+public:
+    QmlPropertyDefinitionSymbol(const QString &fileName, QmlJS::AST::UiPublicMember *propertyNode);
+    virtual ~QmlPropertyDefinitionSymbol();
+
+    virtual int line() const;
+    virtual int column() const;
+
+private:
+    QmlJS::AST::UiPublicMember *propertyNode() const;
+};
+
+} // namespace DuiEditor
+
+#endif // QMLSYMBOL_H
diff --git a/src/plugins/duieditor/resolveqmlexpression.cpp b/src/plugins/duieditor/resolveqmlexpression.cpp
deleted file mode 100644
index 38311ac30a3812869b15b481e253042414615e24..0000000000000000000000000000000000000000
--- a/src/plugins/duieditor/resolveqmlexpression.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-#include "qmljsast_p.h"
-#include "qmljsengine_p.h"
-#include "resolveqmlexpression.h"
-
-using namespace DuiEditor;
-using namespace DuiEditor::Internal;
-using namespace QmlJS;
-using namespace QmlJS::AST;
-
-ResolveQmlExpression::ResolveQmlExpression(const QmlLookupContext &context)
-    : _context(context), _value(0)
-{
-}
-
-QmlLookupContext::Symbol *ResolveQmlExpression::typeOf(Node *node)
-{
-    QmlLookupContext::Symbol *previousValue = switchValue(0);
-    if (node)
-        node->accept(this);
-    return switchValue(previousValue);
-}
-
-
-QmlLookupContext::Symbol *ResolveQmlExpression::switchValue(QmlLookupContext::Symbol *value)
-{
-    QmlLookupContext::Symbol *previousValue = _value;
-    _value = value;
-    return previousValue;
-}
-
-bool ResolveQmlExpression::visit(IdentifierExpression *ast)
-{
-    const QString name = ast->name->asString();
-    _value = _context.resolve(name);
-    return false;
-}
-
-bool ResolveQmlExpression::visit(FieldMemberExpression *ast)
-{
-    const QString memberName = ast->name->asString();
-
-    if (QmlLookupContext::Symbol *base = typeOf(ast->base)) {
-        UiObjectMemberList *members = 0;
-
-        if (UiObjectBinding *uiObjectBinding = cast<UiObjectBinding *>(base)) {
-            if (uiObjectBinding->initializer)
-                members = uiObjectBinding->initializer->members;
-        } else if (UiObjectDefinition *uiObjectDefinition = cast<UiObjectDefinition *>(base)) {
-            if (uiObjectDefinition->initializer)
-                members = uiObjectDefinition->initializer->members;
-        }
-
-        for (UiObjectMemberList *it = members; it; it = it->next) {
-            UiObjectMember *member = it->member;
-
-            if (UiPublicMember *publicMember = cast<UiPublicMember *>(member)) {
-                if (publicMember->name->asString() == memberName) {
-                    _value = publicMember;
-                    break; // we're done.
-                }
-            }
-        }
-    }
-
-    return false;
-}
-
diff --git a/src/plugins/duieditor/resolveqmlexpression.h b/src/plugins/duieditor/resolveqmlexpression.h
deleted file mode 100644
index 8cbea1ec29a1f2a2b57545b04479b16036039a5c..0000000000000000000000000000000000000000
--- a/src/plugins/duieditor/resolveqmlexpression.h
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef RESOLVEQMLEXPRESSION_H
-#define RESOLVEQMLEXPRESSION_H
-
-#include "qmljsastvisitor_p.h"
-#include "qmllookupcontext.h"
-
-namespace DuiEditor {
-namespace Internal {
-
-class ResolveQmlExpression: protected QmlJS::AST::Visitor
-{
-public:
-    ResolveQmlExpression(const QmlLookupContext &context);
-
-    QmlLookupContext::Symbol *operator()(QmlJS::AST::Node *node)
-    { return typeOf(node); }
-
-protected:
-    using QmlJS::AST::Visitor::visit;
-
-    QmlLookupContext::Symbol *typeOf(QmlJS::AST::Node *node);
-    QmlLookupContext::Symbol *switchValue(QmlLookupContext::Symbol *symbol);
-
-    virtual bool visit(QmlJS::AST::IdentifierExpression *ast);
-    virtual bool visit(QmlJS::AST::FieldMemberExpression *ast);
-
-private:
-    QmlLookupContext _context;
-    QmlLookupContext::Symbol *_value;
-};
-
-} // namespace Internal
-} // namespace DuiEditor
-
-#endif // RESOLVEQMLEXPRESSION_H
diff --git a/src/plugins/texteditor/basetexteditor.cpp b/src/plugins/texteditor/basetexteditor.cpp
index fb34d45174cb591e6b370c2d5ca5f38aa5509b89..b5e47fa6be3fce2d1899c32da971c3b3e3d07a7b 100644
--- a/src/plugins/texteditor/basetexteditor.cpp
+++ b/src/plugins/texteditor/basetexteditor.cpp
@@ -589,6 +589,9 @@ Core::IFile *BaseTextEditor::file()
 
 void BaseTextEditor::editorContentsChange(int position, int charsRemoved, int charsAdded)
 {
+    if (d->m_animator)
+        d->m_animator->finish();
+
     d->m_contentsChanged = true;
 
     // Keep the line numbers and the block information for the text marks updated
@@ -2689,7 +2692,8 @@ void BaseTextEditor::slotCursorPositionChanged()
 
     if (d->m_parenthesesMatchingEnabled) {
         // Delay update when no matching is displayed yet, to avoid flicker
-        if (extraSelections(ParenthesesMatchingSelection).isEmpty()) {
+        if (extraSelections(ParenthesesMatchingSelection).isEmpty()
+            && d->m_animator == 0) {
             d->m_parenthesesMatchingTimer->start(50);
         } else {
              // use 0-timer, not direct call, to give the syntax highlighter a chance
@@ -3747,11 +3751,13 @@ void BaseTextEditor::setFindScope(const QTextCursor &scope)
     }
 }
 
-void BaseTextEditor::_q_animateUpdate(int position, QRectF rect)
+void BaseTextEditor::_q_animateUpdate(int position, QPointF lastPos, QRectF rect)
 {
     QTextCursor cursor(textCursor());
     cursor.setPosition(position);
     viewport()->update(QRectF(cursorRect(cursor).topLeft() + rect.topLeft(), rect.size()).toAlignedRect());
+    if (!lastPos.isNull())
+        viewport()->update(QRectF(lastPos + rect.topLeft(), rect.size()).toAlignedRect());
 }
 
 
@@ -3778,6 +3784,7 @@ void BaseTextEditorAnimator::setData(QFont f, QPalette pal, const QString &text)
 
 void BaseTextEditorAnimator::draw(QPainter *p, const QPointF &pos)
 {
+    m_lastDrawPos = pos;
     p->setPen(m_palette.text().color());
     QFont f = m_font;
     f.setPointSizeF(f.pointSizeF() * (1.0 + m_value/2));
@@ -3809,11 +3816,12 @@ void BaseTextEditorAnimator::step(qreal v)
     QRectF before = rect();
     m_value = v;
     QRectF after = rect();
-    emit updateRequest(m_position, before.united(after));
+    emit updateRequest(m_position, m_lastDrawPos, before.united(after));
 }
 
 void BaseTextEditorAnimator::finish()
 {
+    m_timeline->stop();
     step(0);
     deleteLater();
 }
@@ -3912,8 +3920,8 @@ void BaseTextEditor::_q_matchParentheses()
         pal.setBrush(QPalette::Text, d->m_matchFormat.foreground());
         pal.setBrush(QPalette::Base, d->m_rangeFormat.background());
         d->m_animator->setData(font(), pal, characterAt(d->m_animator->position()));
-        connect(d->m_animator, SIGNAL(updateRequest(int,QRectF)),
-                this, SLOT(_q_animateUpdate(int,QRectF)));
+        connect(d->m_animator, SIGNAL(updateRequest(int,QPointF,QRectF)),
+                this, SLOT(_q_animateUpdate(int,QPointF,QRectF)));
     }
 
     setExtraSelections(ParenthesesMatchingSelection, extraSelections);
diff --git a/src/plugins/texteditor/basetexteditor.h b/src/plugins/texteditor/basetexteditor.h
index 2015a10fcb5fa2887464e5fcf23281a2ffaa82c8..ad2b022b0a31b12b3848131dff84458eb85af82b 100644
--- a/src/plugins/texteditor/basetexteditor.h
+++ b/src/plugins/texteditor/basetexteditor.h
@@ -242,22 +242,23 @@ class TEXTEDITOR_EXPORT BaseTextEditorAnimator : public QObject
 public:
     BaseTextEditorAnimator(QObject *parent);
 
-    void setPosition(int position) { m_position = position; }
-    int position() const { return m_position; }
+    inline void setPosition(int position) { m_position = position; }
+    inline int position() const { return m_position; }
 
     void setData(QFont f, QPalette pal, const QString &text);
 
     void draw(QPainter *p, const QPointF &pos);
     QRectF rect() const;
 
-    qreal value() const { return m_value; }
+    inline qreal value() const { return m_value; }
+    inline QPointF lastDrawPos() const { return m_lastDrawPos; }
 
     void finish();
 
     bool isRunning() const;
 
 signals:
-    void updateRequest(int position, QRectF rect);
+    void updateRequest(int position, QPointF lastPos, QRectF rect);
 
 
 private slots:
@@ -267,6 +268,7 @@ private:
     QTimeLine *m_timeline;
     qreal m_value;
     int m_position;
+    QPointF m_lastDrawPos;
     QFont m_font;
     QPalette m_palette;
     QString m_text;
@@ -599,7 +601,7 @@ private slots:
     void _q_matchParentheses();
     void _q_highlightBlocks();
     void slotSelectionChanged();
-    void _q_animateUpdate(int position, QRectF rect);
+    void _q_animateUpdate(int position, QPointF lastPos, QRectF rect);
 };
 
 
diff --git a/src/shared/cplusplus/CheckExpression.cpp b/src/shared/cplusplus/CheckExpression.cpp
index 6700b229b8d470ee9d1df9e9cca04ab36a656a4b..805975b62500560e60bee644d11cd5eca4ee8547 100644
--- a/src/shared/cplusplus/CheckExpression.cpp
+++ b/src/shared/cplusplus/CheckExpression.cpp
@@ -168,43 +168,37 @@ bool CheckExpression::visit(ArrayInitializerAST *ast)
 
 bool CheckExpression::visit(QualifiedNameAST *ast)
 {
-    Name *name = semantic()->check(ast, _scope);
-    _scope->addUse(ast->firstToken(), name);
+    (void) semantic()->check(ast, _scope);
     return false;
 }
 
 bool CheckExpression::visit(OperatorFunctionIdAST *ast)
 {
-    Name *name = semantic()->check(ast, _scope);
-    _scope->addUse(ast->firstToken(), name);
+    (void) semantic()->check(ast, _scope);
     return false;
 }
 
 bool CheckExpression::visit(ConversionFunctionIdAST *ast)
 {
-    Name *name = semantic()->check(ast, _scope);
-    _scope->addUse(ast->firstToken(), name);
+    (void) semantic()->check(ast, _scope);
     return false;
 }
 
 bool CheckExpression::visit(SimpleNameAST *ast)
 {
-    Name *name = semantic()->check(ast, _scope);
-    _scope->addUse(ast->firstToken(), name);
+    (void) semantic()->check(ast, _scope);
     return false;
 }
 
 bool CheckExpression::visit(DestructorNameAST *ast)
 {
-    Name *name = semantic()->check(ast, _scope);
-    _scope->addUse(ast->firstToken(), name);
+    (void) semantic()->check(ast, _scope);
     return false;
 }
 
 bool CheckExpression::visit(TemplateIdAST *ast)
 {
-    Name *name = semantic()->check(ast, _scope);
-    _scope->addUse(ast->firstToken(), name);
+    (void) semantic()->check(ast, _scope);
     return false;
 }
 
@@ -246,11 +240,11 @@ bool CheckExpression::visit(TypeidExpressionAST *ast)
 
 bool CheckExpression::visit(TypenameCallExpressionAST *ast)
 {
-    if (Name *name = semantic()->check(ast->name, _scope)) {
-        _scope->addUse(ast->name->firstToken(), name);
-    }
+    (void) semantic()->check(ast->name, _scope);
+
     for (ExpressionListAST *it = ast->expression_list; it; it = it->next) {
         FullySpecifiedType exprTy = semantic()->check(it->expression, _scope);
+        (void) exprTy;
     }
     return false;
 }
@@ -378,17 +372,14 @@ bool CheckExpression::visit(PostIncrDecrAST *)
 
 bool CheckExpression::visit(MemberAccessAST *ast)
 {
-    if (Name *name = semantic()->check(ast->member_name, _scope))
-        _scope->addUse(ast->member_name->firstToken(), name);
+    (void) semantic()->check(ast->member_name, _scope);
     return false;
 }
 
 bool CheckExpression::visit(ObjCMessageExpressionAST *ast)
 {
     semantic()->check(ast->receiver_expression, _scope);
-
-    if (Name *name = semantic()->check(ast->selector, _scope))
-        _scope->addUse(ast->selector->firstToken(), name);
+    (void) semantic()->check(ast->selector, _scope);
 
     accept(ast->argument_list);
     return false;
@@ -402,9 +393,7 @@ bool CheckExpression::visit(ObjCEncodeExpressionAST * /*ast*/)
 
 bool CheckExpression::visit(ObjCSelectorExpressionAST *ast)
 {
-    if (Name *name = semantic()->check(ast->selector, _scope))
-        _scope->addUse(ast->selector->firstToken(), name);
-
+    (void) semantic()->check(ast->selector, _scope);
     return false;
 }
 
diff --git a/src/shared/cplusplus/Control.cpp b/src/shared/cplusplus/Control.cpp
index fce76e32ad87c647b048d00a9e3a204de54d0ed1..fda1c3b32b7e0ac369e305c10e2030ff20b95c49 100644
--- a/src/shared/cplusplus/Control.cpp
+++ b/src/shared/cplusplus/Control.cpp
@@ -582,6 +582,9 @@ DiagnosticClient *Control::diagnosticClient() const
 void Control::setDiagnosticClient(DiagnosticClient *diagnosticClient)
 { d->diagnosticClient = diagnosticClient; }
 
+Identifier *Control::findIdentifier(const char *chars, unsigned size) const
+{ return d->identifiers.findLiteral(chars, size); }
+
 Identifier *Control::findOrInsertIdentifier(const char *chars, unsigned size)
 { return d->identifiers.findOrInsertLiteral(chars, size); }
 
diff --git a/src/shared/cplusplus/Control.h b/src/shared/cplusplus/Control.h
index 7698e0b226b380eae2acddc111eaeeaf6369c8a8..beb18aab4fe8c5b316b8658777390bb411fe0bd3 100644
--- a/src/shared/cplusplus/Control.h
+++ b/src/shared/cplusplus/Control.h
@@ -166,6 +166,8 @@ public:
     /// Creates a new Objective-C method symbol.
     ObjCMethod *newObjCMethod(unsigned sourceLocation, Name *name = 0);
 
+    Identifier *findIdentifier(const char *chars, unsigned size) const;
+
     Identifier *findOrInsertIdentifier(const char *chars, unsigned size);
     Identifier *findOrInsertIdentifier(const char *chars);
 
diff --git a/src/shared/cplusplus/LiteralTable.h b/src/shared/cplusplus/LiteralTable.h
index 67d074eca63b9b8debcc0c9956771576799274d8..64fd2e1dac57473ddbd3af6142147bf131ee363d 100644
--- a/src/shared/cplusplus/LiteralTable.h
+++ b/src/shared/cplusplus/LiteralTable.h
@@ -101,7 +101,21 @@ public:
     iterator end() const
     { return _literals + _literalCount + 1; }
 
-    _Literal *findOrInsertLiteral(const char *chars, unsigned size)
+    _Literal *findLiteral(const char *chars, unsigned size) const
+    {
+       if (_buckets) {
+           unsigned h = _Literal::hashCode(chars, size);
+           _Literal *literal = _buckets[h % _allocatedBuckets];
+           for (; literal; literal = static_cast<_Literal *>(literal->_next)) {
+               if (literal->size() == size && ! std::strncmp(literal->chars(), chars, size))
+                  return literal;
+           }
+       }
+
+       return 0;
+   }
+
+   _Literal *findOrInsertLiteral(const char *chars, unsigned size)
     {
        if (_buckets) {
            unsigned h = _Literal::hashCode(chars, size);
diff --git a/src/shared/cplusplus/Scope.cpp b/src/shared/cplusplus/Scope.cpp
index 5f5e6d5ca7b593ae8e3dfa99cf4c17a7667e6ca5..6c910c072c6fee8d7b1ae9642ff8ce544356b6d8 100644
--- a/src/shared/cplusplus/Scope.cpp
+++ b/src/shared/cplusplus/Scope.cpp
@@ -297,7 +297,4 @@ Scope::iterator Scope::firstSymbol() const
 Scope::iterator Scope::lastSymbol() const
 { return _symbols + _symbolCount + 1; }
 
-void Scope::addUse(unsigned, Name *)
-{ }
-
 CPLUSPLUS_END_NAMESPACE
diff --git a/src/shared/cplusplus/Scope.h b/src/shared/cplusplus/Scope.h
index 0daf7751c058a8bdeed8450ed8de419d02092d6c..5fb9eb3ac7caa768d7547bad7956712db2c3391b 100644
--- a/src/shared/cplusplus/Scope.h
+++ b/src/shared/cplusplus/Scope.h
@@ -54,34 +54,6 @@
 CPLUSPLUS_BEGIN_HEADER
 CPLUSPLUS_BEGIN_NAMESPACE
 
-class CPLUSPLUS_EXPORT Use
-{
-public:
-    inline Name *name() const
-    { return _name; }
-
-    inline unsigned sourceOffset() const
-    { return _sourceOffset; }
-
-    inline Symbol *lastVisibleSymbol() const
-    { return _lastVisibleSymbol; }
-
-private:
-    void init(unsigned sourceOffset, Name *name, Symbol *lastVisibleSymbol)
-    {
-        _sourceOffset = sourceOffset;
-        _name = name;
-        _lastVisibleSymbol = lastVisibleSymbol;
-    }
-
-    unsigned _sourceOffset;
-
-    Name *_name;
-    Symbol *_lastVisibleSymbol;
-
-    friend class Scope;
-};
-
 class CPLUSPLUS_EXPORT Scope
 {
     Scope(const Scope &other);
@@ -160,8 +132,6 @@ public:
     Symbol *lookat(Identifier *id) const;
     Symbol *lookat(int operatorId) const;
 
-    void addUse(unsigned sourceOffset, Name *name);
-
 private:
     /// Returns the hash value for the given Symbol.
     unsigned hashValue(Symbol *symbol) const;
diff --git a/src/shared/trk/trkdevice.cpp b/src/shared/trk/trkdevice.cpp
index c17a4532f19299868f4717246a792db601e64e4b..773e1ea3c48cf43e5612022688b408cd44f18ecb 100644
--- a/src/shared/trk/trkdevice.cpp
+++ b/src/shared/trk/trkdevice.cpp
@@ -39,6 +39,7 @@
 #include <QtCore/QMutex>
 #include <QtCore/QWaitCondition>
 #include <QtCore/QSharedPointer>
+#include <QtCore/QMetaType>
 
 #ifdef Q_OS_WIN
 #  include <windows.h>
@@ -132,18 +133,30 @@ TrkMessage::TrkMessage(byte c, byte t, TrkCallback cb) :
 {
 }
 
+} // namespace trk
+
+Q_DECLARE_METATYPE(trk::TrkMessage)
+
+namespace trk {
 
 ///////////////////////////////////////////////////////////////////////
 //
-// TrkWriteQueue
+// TrkWriteQueue: Mixin class that manages a write queue of Trk messages.
+// pendingMessage()/notifyWriteResult() should be called from a worked/timer
+// that writes the messages. The class does not take precautions for multithreading
+// with exception of the handling of the  TRK_WRITE_QUEUE_NOOP_CODE
+// synchronization message. The invocation of the callback is then
+// done by the thread owning the TrkWriteQueue, while pendingMessage() is called
+// from another thread. This happens via a Qt::BlockingQueuedConnection.
 //
 ///////////////////////////////////////////////////////////////////////
 
-/* Mixin class that manages a write queue of Trk messages. */
-class TrkWriteQueue
-{
+class TrkWriteQueue : public QObject
+{    
+    Q_OBJECT
+    Q_DISABLE_COPY(TrkWriteQueue)
 public:
-    TrkWriteQueue();
+    explicit TrkWriteQueue(bool multithreaded = true);
 
     // Enqueue messages.
     void queueTrkMessage(byte code, TrkCallback callback,
@@ -160,6 +173,12 @@ public:
     // after taking the pendingMessage off.
     void notifyWriteResult(bool ok);
 
+signals:
+    void internalNoopMessageDequeued(const trk::TrkMessage&);
+
+private slots:
+    void invokeNoopMessage(trk::TrkMessage);
+
 private:
     typedef QMap<byte, TrkMessage> TokenMessageMap;
 
@@ -171,10 +190,15 @@ private:
     bool m_trkWriteBusy;
 };
 
-TrkWriteQueue::TrkWriteQueue() :
+TrkWriteQueue::TrkWriteQueue(bool multithreaded) :
     m_trkWriteToken(0),
     m_trkWriteBusy(false)
 {
+    static const int trkMessageMetaId = qRegisterMetaType<trk::TrkMessage>();
+    Q_UNUSED(trkMessageMetaId)
+    connect(this, SIGNAL(internalNoopMessageDequeued(trk::TrkMessage)),
+            this, SLOT(invokeNoopMessage(trk::TrkMessage)),
+            multithreaded ? Qt::BlockingQueuedConnection : Qt::AutoConnection);
 }
 
 byte TrkWriteQueue::nextTrkWriteToken()
@@ -201,17 +225,11 @@ bool TrkWriteQueue::pendingMessage(TrkMessage *message)
     // Invoked from timer, try to flush out message queue
     if (m_trkWriteBusy || m_trkWriteQueue.isEmpty())
         return false;
-    // Handle the noop message, just invoke CB
+    // Handle the noop message, just invoke CB in slot (ower thread)
     if (m_trkWriteQueue.front().code == TRK_WRITE_QUEUE_NOOP_CODE) {
         TrkMessage noopMessage = m_trkWriteQueue.dequeue();
-        if (noopMessage.callback) {
-            TrkResult result;
-            result.code = noopMessage.code;
-            result.token = noopMessage.token;
-            result.data = noopMessage.data;
-            result.cookie = noopMessage.cookie;
-            noopMessage.callback(result);
-        }
+        if (noopMessage.callback)
+            emit internalNoopMessageDequeued(noopMessage);
     }
     // Check again for real messages
     if (m_trkWriteQueue.isEmpty())
@@ -221,6 +239,16 @@ bool TrkWriteQueue::pendingMessage(TrkMessage *message)
     return true;
 }
 
+void TrkWriteQueue::invokeNoopMessage(trk::TrkMessage noopMessage)
+{
+    TrkResult result;
+    result.code = noopMessage.code;
+    result.token = noopMessage.token;
+    result.data = noopMessage.data;
+    result.cookie = noopMessage.cookie;
+    noopMessage.callback(result);
+}
+
 void TrkWriteQueue::notifyWriteResult(bool ok)
 {
     // On success, dequeue message and await result
@@ -271,6 +299,7 @@ struct DeviceContext {
     QFile file;
 #endif
     bool serialFrame;
+    QMutex mutex;
 };
 
 DeviceContext::DeviceContext() :
@@ -358,6 +387,7 @@ void WriterThread::terminate()
 
 bool WriterThread::write(const QByteArray &data, QString *errorMessage)
 {
+    QMutexLocker(&m_context->mutex);
 #ifdef Q_OS_WIN
     DWORD charsWritten;
     if (!WriteFile(m_context->device, data.data(), data.size(), &charsWritten, NULL)) {
@@ -588,12 +618,14 @@ void TrkDevice::tryTrkRead()
     char buffer[BUFFERSIZE];
     DWORD charsRead;
     DWORD totalCharsRead = 0;
-
-    while (TryReadFile(d->deviceContext->device, buffer, BUFFERSIZE, &charsRead, NULL)) {
-        totalCharsRead += charsRead;
-        d->trkReadBuffer.append(buffer, charsRead);
-        if (isValidTrkResult(d->trkReadBuffer, d->deviceContext->serialFrame))
-            break;
+    {
+        QMutexLocker(&d->deviceContext->mutex);
+        while (TryReadFile(d->deviceContext->device, buffer, BUFFERSIZE, &charsRead, NULL)) {
+            totalCharsRead += charsRead;
+            d->trkReadBuffer.append(buffer, charsRead);
+            if (isValidTrkResult(d->trkReadBuffer, d->deviceContext->serialFrame))
+                break;
+        }
     }
     if (d->verbose > 1 && totalCharsRead)
         emitLogMessage("Read" + d->trkReadBuffer.toHex());
@@ -606,10 +638,14 @@ void TrkDevice::tryTrkRead()
         return;
     }
 #else
-    const int size = bytesAvailable(d->deviceContext->file.handle());
-    if (!size)
-        return;
-    const QByteArray data = d->deviceContext->file.read(size);
+    QByteArray data;
+    {
+        QMutexLocker(&d->deviceContext->mutex);
+        const int size = bytesAvailable(d->deviceContext->file.handle());
+        if (!size)
+            return;
+        data = d->deviceContext->file.read(size);
+    }
     if (d->verbose > 1)
         emitLogMessage("trk: <- " + stringFromArray(data));
     d->trkReadBuffer.append(data);