diff --git a/src/libs/cplusplus/CppDocument.cpp b/src/libs/cplusplus/CppDocument.cpp
index 94832cc1420f8606d49e51b07bfe0e5b888acf2f..cb9598614b6f869489c9ec9b647ea8990847dd68 100644
--- a/src/libs/cplusplus/CppDocument.cpp
+++ b/src/libs/cplusplus/CppDocument.cpp
@@ -740,11 +740,12 @@ Symbol *Snapshot::findMatchingDefinition(Symbol *declaration) const
                 continue; // nothing to do
 
             foreach (Function *fun, result) {
-                const QList<Symbol *> declarations = context.lookup(fun->name(), fun->scope());
+                const QList<LookupItem> declarations = context.lookup(fun->name(), fun->scope());
                 if (declarations.isEmpty())
                     continue;
 
-                else if (enclosingType == context.lookupType(declarations.first()))
+                const LookupItem best = declarations.first();
+                if (enclosingType == context.lookupType(best.declaration()))
                     viableFunctions.append(fun);
             }
 
diff --git a/src/libs/cplusplus/CppRewriter.cpp b/src/libs/cplusplus/CppRewriter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2dcec18a419ce34ad9fa063b06b5f2897722e9e7
--- /dev/null
+++ b/src/libs/cplusplus/CppRewriter.cpp
@@ -0,0 +1,364 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 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 "CppRewriter.h"
+#include <TypeVisitor.h>
+#include <NameVisitor.h>
+#include <CoreTypes.h>
+#include <Symbols.h>
+#include <Literals.h>
+#include <Names.h>
+#include <Scope.h>
+
+#include <QtCore/QVarLengthArray>
+#include <QtCore/QDebug>
+
+using namespace CPlusPlus;
+
+class CPlusPlus::Rewrite
+{
+public:
+    Rewrite(Control *control, const SubstitutionEnvironment &env)
+        : control(control), env(env), rewriteType(this), rewriteName(this) {}
+
+    class RewriteType: public TypeVisitor
+    {
+        Rewrite *rewrite;
+        QList<FullySpecifiedType> temps;
+
+        Control *control() const
+        { return rewrite->control; }
+
+        void accept(const FullySpecifiedType &ty)
+        {
+            TypeVisitor::accept(ty.type());
+            unsigned flags = ty.flags();
+            flags |= temps.back().flags();
+            temps.back().setFlags(flags);
+        }
+
+    public:
+        RewriteType(Rewrite *r): rewrite(r) {}
+
+        FullySpecifiedType operator()(const FullySpecifiedType &ty)
+        {
+            accept(ty);
+            return temps.takeLast();
+        }
+
+        virtual void visit(UndefinedType *)
+        {
+            temps.append(FullySpecifiedType());
+        }
+
+        virtual void visit(VoidType *)
+        {
+            temps.append(control()->voidType());
+        }
+
+        virtual void visit(IntegerType *type)
+        {
+            temps.append(control()->integerType(type->kind()));
+        }
+
+        virtual void visit(FloatType *type)
+        {
+            temps.append(control()->floatType(type->kind()));
+        }
+
+        virtual void visit(PointerToMemberType *type)
+        {
+            const Name *memberName = rewrite->rewriteName(type->memberName());
+            const FullySpecifiedType elementType = rewrite->rewriteType(type->elementType());
+            temps.append(control()->pointerToMemberType(memberName, elementType));
+        }
+
+        virtual void visit(PointerType *type)
+        {
+            const FullySpecifiedType elementType = rewrite->rewriteType(type->elementType());
+            temps.append(control()->pointerType(elementType));
+        }
+
+        virtual void visit(ReferenceType *type)
+        {
+            const FullySpecifiedType elementType = rewrite->rewriteType(type->elementType());
+            temps.append(control()->referenceType(elementType));
+        }
+
+        virtual void visit(ArrayType *type)
+        {
+            const FullySpecifiedType elementType = rewrite->rewriteType(type->elementType());
+            temps.append(control()->arrayType(elementType, type->size()));
+        }
+
+        virtual void visit(NamedType *type)
+        {
+            FullySpecifiedType ty = rewrite->env.apply(type->name(), rewrite);
+            if (! ty->isUndefinedType())
+                temps.append(rewrite->rewriteType(ty));
+            else {
+                const Name *name = rewrite->rewriteName(type->name());
+                temps.append(control()->namedType(name));
+            }
+        }
+
+        virtual void visit(Function *type)
+        {
+            Function *funTy = control()->newFunction(0, 0);
+            funTy->copy(type);
+
+            funTy->setName(rewrite->rewriteName(type->name()));
+
+            funTy->setReturnType(rewrite->rewriteType(type->returnType()));
+
+            for (unsigned i = 0; i < type->argumentCount(); ++i) {
+                Symbol *arg = type->argumentAt(i);
+
+                Argument *newArg = control()->newArgument(0, 0);
+                newArg->copy(arg);
+                newArg->setName(rewrite->rewriteName(arg->name()));
+                newArg->setType(rewrite->rewriteType(arg->type()));
+
+                funTy->arguments()->enterSymbol(newArg);
+            }
+
+            temps.append(funTy);
+        }
+
+        virtual void visit(Namespace *type)
+        {
+            qWarning() << Q_FUNC_INFO;
+            temps.append(type);
+        }
+
+        virtual void visit(Class *type)
+        {
+            qWarning() << Q_FUNC_INFO;
+            temps.append(type);
+        }
+
+        virtual void visit(Enum *type)
+        {
+            qWarning() << Q_FUNC_INFO;
+            temps.append(type);
+        }
+
+        virtual void visit(ForwardClassDeclaration *type)
+        {
+            qWarning() << Q_FUNC_INFO;
+            temps.append(type);
+        }
+
+        virtual void visit(ObjCClass *type)
+        {
+            qWarning() << Q_FUNC_INFO;
+            temps.append(type);
+        }
+
+        virtual void visit(ObjCProtocol *type)
+        {
+            qWarning() << Q_FUNC_INFO;
+            temps.append(type);
+        }
+
+        virtual void visit(ObjCMethod *type)
+        {
+            qWarning() << Q_FUNC_INFO;
+            temps.append(type);
+        }
+
+        virtual void visit(ObjCForwardClassDeclaration *type)
+        {
+            qWarning() << Q_FUNC_INFO;
+            temps.append(type);
+        }
+
+        virtual void visit(ObjCForwardProtocolDeclaration *type)
+        {
+            qWarning() << Q_FUNC_INFO;
+            temps.append(type);
+        }
+
+    };
+
+    class RewriteName: public NameVisitor
+    {
+        Rewrite *rewrite;
+        QList<const Name *> temps;
+
+        Control *control() const
+        { return rewrite->control; }
+
+        const Identifier *identifier(const Identifier *other) const
+        {
+            if (! other)
+                return 0;
+
+            return control()->findOrInsertIdentifier(other->chars(), other->size());
+        }
+
+    public:
+        RewriteName(Rewrite *r): rewrite(r) {}
+
+        const Name *operator()(const Name *name)
+        {
+            if (! name)
+                return 0;
+
+            accept(name);
+            return temps.takeLast();
+        }
+
+        virtual void visit(const QualifiedNameId *name)
+        {
+            const Name *base = rewrite->rewriteName(name->base());
+            const Name *n = rewrite->rewriteName(name->name());
+            temps.append(control()->qualifiedNameId(base, n));
+        }
+
+        virtual void visit(const NameId *name)
+        {
+            temps.append(control()->nameId(identifier(name->identifier())));
+        }
+
+        virtual void visit(const TemplateNameId *name)
+        {
+            QVarLengthArray<FullySpecifiedType, 8> args(name->templateArgumentCount());
+            for (unsigned i = 0; i < name->templateArgumentCount(); ++i)
+                args[i] = rewrite->rewriteType(name->templateArgumentAt(i));
+            temps.append(control()->templateNameId(identifier(name->identifier()), args.data(), args.size()));
+        }
+
+        virtual void visit(const DestructorNameId *name)
+        {
+            temps.append(control()->destructorNameId(identifier(name->identifier())));
+        }
+
+        virtual void visit(const OperatorNameId *name)
+        {
+            temps.append(control()->operatorNameId(name->kind()));
+        }
+
+        virtual void visit(const ConversionNameId *name)
+        {
+            FullySpecifiedType ty = rewrite->rewriteType(name->type());
+            temps.append(control()->conversionNameId(ty));
+        }
+
+        virtual void visit(const SelectorNameId *name)
+        {
+            QVarLengthArray<const Name *, 8> names(name->nameCount());
+            for (unsigned i = 0; i < name->nameCount(); ++i)
+                names[i] = rewrite->rewriteName(name->nameAt(i));
+            temps.append(control()->selectorNameId(names.constData(), names.size(), name->hasArguments()));
+        }
+    };
+
+public: // attributes
+    Control *control;
+    SubstitutionEnvironment env;
+    RewriteType rewriteType;
+    RewriteName rewriteName;
+};
+
+ContextSubstitution::ContextSubstitution(const LookupContext &context, Scope *scope)
+    : _context(context), _scope(scope)
+{
+}
+
+ContextSubstitution::~ContextSubstitution()
+{
+}
+
+FullySpecifiedType ContextSubstitution::apply(const Name *name, Rewrite *rewrite) const
+{
+    const QList<LookupItem> candidates = _context.lookup(name, _scope);
+
+    foreach (const LookupItem &r, candidates) {
+        Symbol *s = r.declaration();
+        if (s->isDeclaration() && s->isTypedef()) {
+            qDebug() << "resolved typedef:" << s->fileName() << s->line() << s->column();
+
+            qDebug() << "scope is:" << r.scope()->owner()->fileName()
+                     << r.scope()->owner()->line()
+                     << r.scope()->owner()->column();
+
+            ContextSubstitution subst(_context, s->scope());
+            rewrite->env.enter(&subst);
+            FullySpecifiedType ty = rewrite->rewriteType(s->type());
+            rewrite->env.leave();
+
+            return ty;
+        }
+    }
+    return FullySpecifiedType();
+}
+
+
+SubstitutionMap::SubstitutionMap()
+{
+
+}
+
+SubstitutionMap::~SubstitutionMap()
+{
+
+}
+
+void SubstitutionMap::bind(const Name *name, const FullySpecifiedType &ty)
+{
+    _map.append(qMakePair(name, ty));
+}
+
+FullySpecifiedType SubstitutionMap::apply(const Name *name, Rewrite *) const
+{
+    for (int n = _map.size() - 1; n != -1; --n) {
+        const QPair<const Name *, FullySpecifiedType> &p = _map.at(n);
+
+        if (name->isEqualTo(p.first))
+            return p.second;
+    }
+
+    return FullySpecifiedType();
+}
+
+FullySpecifiedType CPlusPlus::rewriteType(const FullySpecifiedType &type,
+                                          const SubstitutionEnvironment &env,
+                                          Control *control)
+{
+    Rewrite rewrite(control, env);
+    return rewrite.rewriteType(type);
+}
+
+const Name *CPlusPlus::rewriteName(const Name *name,
+                                   const SubstitutionEnvironment &env,
+                                   Control *control)
+{
+    Rewrite rewrite(control, env);
+    return rewrite.rewriteName(name);
+}
diff --git a/src/libs/cplusplus/CppRewriter.h b/src/libs/cplusplus/CppRewriter.h
new file mode 100644
index 0000000000000000000000000000000000000000..4e6d14b3f5a03d7811796837b2fdfd9ab0ca696c
--- /dev/null
+++ b/src/libs/cplusplus/CppRewriter.h
@@ -0,0 +1,119 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 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 CPLUSPLUS_REWRITER_H
+#define CPLUSPLUS_REWRITER_H
+
+#include "CppDocument.h"
+#include "LookupContext.h"
+
+namespace CPlusPlus {
+
+class Rewrite;
+
+class CPLUSPLUS_EXPORT Substitution
+{
+    Q_DISABLE_COPY(Substitution)
+
+public:
+    Substitution() {}
+    virtual ~Substitution() {}
+
+    virtual FullySpecifiedType apply(const Name *name, Rewrite *rewrite) const = 0;
+};
+
+class CPLUSPLUS_EXPORT SubstitutionEnvironment
+{
+    QList<Substitution *> substs;
+
+public:
+    FullySpecifiedType apply(const Name *name, Rewrite *rewrite) const
+    {
+        if (name) {
+            for (int index = substs.size() - 1; index != -1; --index) {
+                const Substitution *subst = substs.at(index);
+
+                FullySpecifiedType ty = subst->apply(name, rewrite);
+                if (! ty->isUndefinedType())
+                    return ty;
+            }
+        }
+
+        return FullySpecifiedType();
+    }
+
+    void enter(Substitution *subst)
+    {
+        substs.append(subst);
+    }
+
+    void leave()
+    {
+        substs.removeLast();
+    }
+};
+
+class CPLUSPLUS_EXPORT ContextSubstitution: public Substitution
+{
+public:
+    ContextSubstitution(const LookupContext &context, Scope *scope);
+    virtual ~ContextSubstitution();
+
+    virtual FullySpecifiedType apply(const Name *name, Rewrite *rewrite) const;
+
+private:
+    LookupContext _context;
+    Scope *_scope;
+};
+
+
+class CPLUSPLUS_EXPORT SubstitutionMap: public Substitution
+{
+public:
+    SubstitutionMap();
+    virtual ~SubstitutionMap();
+
+    void bind(const Name *name, const FullySpecifiedType &ty);
+    virtual FullySpecifiedType apply(const Name *name, Rewrite *rewrite) const;
+
+private:
+    QList<QPair<const Name *, FullySpecifiedType> > _map;
+};
+
+CPLUSPLUS_EXPORT FullySpecifiedType rewriteType(const FullySpecifiedType &type,
+                                                const SubstitutionEnvironment &env,
+                                                Control *control);
+
+CPLUSPLUS_EXPORT const Name *rewriteName(const Name *name,
+                                         const SubstitutionEnvironment &env,
+                                         Control *control);
+
+} // end of namespace CPlusPlus
+
+#endif
diff --git a/src/libs/cplusplus/DeprecatedGenTemplateInstance.h b/src/libs/cplusplus/DeprecatedGenTemplateInstance.h
index f40c951ba50e73e32c83bed06f70877e47d6b8ae..755fc341b59029f245df73eb1c8017358fba1e55 100644
--- a/src/libs/cplusplus/DeprecatedGenTemplateInstance.h
+++ b/src/libs/cplusplus/DeprecatedGenTemplateInstance.h
@@ -46,7 +46,7 @@ public:
     typedef QList< QPair<const Identifier *, FullySpecifiedType> > Substitution;
 
 public:
-    static FullySpecifiedType instantiate(const Name *className, Symbol *candidate, QSharedPointer<Control> control);
+    Q_DECL_DEPRECATED static FullySpecifiedType instantiate(const Name *className, Symbol *candidate, QSharedPointer<Control> control);
 
 private:
     DeprecatedGenTemplateInstance(QSharedPointer<Control> control, const Substitution &substitution);
diff --git a/src/libs/cplusplus/FindUsages.cpp b/src/libs/cplusplus/FindUsages.cpp
index f8119fe456f68aaedde8881d81e3674a8c9c2f5c..e703f5fddb2b4badba7a229449f93ae0b827d7dc 100644
--- a/src/libs/cplusplus/FindUsages.cpp
+++ b/src/libs/cplusplus/FindUsages.cpp
@@ -124,7 +124,7 @@ Scope *FindUsages::scopeAt(unsigned tokenIndex) const
     return _doc->scopeAt(line, column);
 }
 
-void FindUsages::reportResult(unsigned tokenIndex, const QList<Symbol *> &candidates)
+void FindUsages::reportResult(unsigned tokenIndex, const QList<LookupItem> &candidates)
 {
     if (_processed.contains(tokenIndex))
         return;
@@ -160,11 +160,12 @@ void FindUsages::reportResult(unsigned tokenIndex)
     _references.append(tokenIndex);
 }
 
-bool FindUsages::checkCandidates(const QList<Symbol *> &candidates) const
+bool FindUsages::checkCandidates(const QList<LookupItem> &candidates) const
 {
     if (ClassOrNamespace *c = _context.lookupType(_declSymbol)) {
         for (int i = candidates.size() - 1; i != -1; --i) {
-            Symbol *s = candidates.at(i);
+            const LookupItem &r = candidates.at(i);
+            Symbol *s = r.declaration();
             if (_context.lookupType(s) == c)
                 return true;
         }
@@ -186,7 +187,7 @@ bool FindUsages::visit(MemInitializerAST *ast)
 
         SimpleNameAST *simple = ast->name->asSimpleName();
         if (identifier(simple->identifier_token) == _id) {
-            const QList<Symbol *> candidates = _context.lookup(simple->name, scopeAt(simple->identifier_token));
+            const QList<LookupItem> candidates = _context.lookup(simple->name, scopeAt(simple->identifier_token));
             reportResult(simple->identifier_token, candidates);
         }
     }
@@ -223,14 +224,7 @@ void FindUsages::checkExpression(unsigned startToken, unsigned endToken)
     const QList<LookupItem> results = typeofExpression(expression, scope,
                                                        TypeOfExpression::Preprocess);
 
-    QList<Symbol *> candidates;
-
-    foreach (const LookupItem &r, results) {
-        Symbol *lastVisibleSymbol = r.declaration();
-        candidates.append(lastVisibleSymbol);
-    }
-
-    reportResult(endToken, candidates);
+    reportResult(endToken, results);
 }
 
 bool FindUsages::visit(QualifiedNameAST *ast)
@@ -297,7 +291,7 @@ bool FindUsages::visit(EnumeratorAST *ast)
 {
     const Identifier *id = identifier(ast->identifier_token);
     if (id == _id) {
-        const QList<Symbol *> candidates = _context.lookup(control()->nameId(id), scopeAt(ast->identifier_token));
+        const QList<LookupItem> candidates = _context.lookup(control()->nameId(id), scopeAt(ast->identifier_token));
         reportResult(ast->identifier_token, candidates);
     }
 
@@ -310,7 +304,7 @@ bool FindUsages::visit(SimpleNameAST *ast)
 {
     const Identifier *id = identifier(ast->identifier_token);
     if (id == _id) {
-        const QList<Symbol *> candidates = _context.lookup(ast->name, scopeAt(ast->identifier_token));
+        const QList<LookupItem> candidates = _context.lookup(ast->name, scopeAt(ast->identifier_token));
         reportResult(ast->identifier_token, candidates);
     }
 
@@ -321,7 +315,7 @@ bool FindUsages::visit(DestructorNameAST *ast)
 {
     const Identifier *id = identifier(ast->identifier_token);
     if (id == _id) {
-        const QList<Symbol *> candidates = _context.lookup(ast->name, scopeAt(ast->identifier_token));
+        const QList<LookupItem> candidates = _context.lookup(ast->name, scopeAt(ast->identifier_token));
         reportResult(ast->identifier_token, candidates);
     }
 
@@ -331,7 +325,7 @@ bool FindUsages::visit(DestructorNameAST *ast)
 bool FindUsages::visit(TemplateIdAST *ast)
 {
     if (_id == identifier(ast->identifier_token)) {
-        const QList<Symbol *> candidates = _context.lookup(ast->name, scopeAt(ast->identifier_token));
+        const QList<LookupItem> candidates = _context.lookup(ast->name, scopeAt(ast->identifier_token));
         reportResult(ast->identifier_token, candidates);
     }
 
@@ -406,7 +400,7 @@ bool FindUsages::visit(ObjCSelectorAST *ast)
     if (ast->name) {
         const Identifier *id = ast->name->identifier();
         if (id == _id) {
-            const QList<Symbol *> candidates = _context.lookup(ast->name, scopeAt(ast->firstToken()));
+            const QList<LookupItem> candidates = _context.lookup(ast->name, scopeAt(ast->firstToken()));
             reportResult(ast->firstToken(), candidates);
         }
     }
@@ -440,7 +434,7 @@ bool FindUsages::visit(TypenameTypeParameterAST *ast)
         const Identifier *id = name->name->identifier();
         if (id == _id) {
             unsigned start = startOfTemplateDeclaration(_templateDeclarationStack.back());
-            const QList<Symbol *> candidates = _context.lookup(name->name, scopeAt(start));
+            const QList<LookupItem> candidates = _context.lookup(name->name, scopeAt(start));
             reportResult(ast->name->firstToken(), candidates);
         }
     }
@@ -454,7 +448,7 @@ bool FindUsages::visit(TemplateTypeParameterAST *ast)
         const Identifier *id = name->name->identifier();
         if (id == _id) {
             unsigned start = startOfTemplateDeclaration(_templateDeclarationStack.back());
-            const QList<Symbol *> candidates = _context.lookup(name->name, scopeAt(start));
+            const QList<LookupItem> candidates = _context.lookup(name->name, scopeAt(start));
             reportResult(ast->name->firstToken(), candidates);
         }
     }
diff --git a/src/libs/cplusplus/FindUsages.h b/src/libs/cplusplus/FindUsages.h
index ff7a3b063bed07f54bf83fbdd810a48c12245aac..f274da04d6676000c74dbc008c7b22dc54eeeaf6 100644
--- a/src/libs/cplusplus/FindUsages.h
+++ b/src/libs/cplusplus/FindUsages.h
@@ -74,10 +74,10 @@ protected:
     QString matchingLine(const Token &tk) const;
     Scope *scopeAt(unsigned tokenIndex) const;
 
-    void reportResult(unsigned tokenIndex, const QList<Symbol *> &candidates);
+    void reportResult(unsigned tokenIndex, const QList<LookupItem> &candidates);
     void reportResult(unsigned tokenIndex);
 
-    bool checkCandidates(const QList<Symbol *> &candidates) const;
+    bool checkCandidates(const QList<LookupItem> &candidates) const;
     void checkExpression(unsigned startToken, unsigned endToken);
 
     void ensureNameIsValid(NameAST *ast);
diff --git a/src/libs/cplusplus/Icons.cpp b/src/libs/cplusplus/Icons.cpp
index 2efa8b3337547e7a8160edaab5a8c81a4fdc992c..a3bb5a38ef3514579bbe920ca228307fcfd94ff1 100644
--- a/src/libs/cplusplus/Icons.cpp
+++ b/src/libs/cplusplus/Icons.cpp
@@ -58,6 +58,21 @@ Icons::Icons()
 }
 
 QIcon Icons::iconForSymbol(const Symbol *symbol) const
+{
+    return iconForType(iconTypeForSymbol(symbol));
+}
+
+QIcon Icons::keywordIcon() const
+{
+    return _keywordIcon;
+}
+
+QIcon Icons::macroIcon() const
+{
+    return _macroIcon;
+}
+
+Icons::IconType Icons::iconTypeForSymbol(const Symbol *symbol)
 {
     FullySpecifiedType symbolType = symbol->type();
     if (symbol->isFunction() || (symbol->isDeclaration() && symbolType &&
@@ -69,58 +84,89 @@ QIcon Icons::iconForSymbol(const Symbol *symbol) const
 
         if (function->isSlot()) {
             if (function->isPublic()) {
-                return _slotPublicIcon;
+                return SlotPublicIconType;
             } else if (function->isProtected()) {
-                return _slotProtectedIcon;
+                return SlotProtectedIconType;
             } else if (function->isPrivate()) {
-                return _slotPrivateIcon;
+                return SlotPrivateIconType;
             }
         } else if (function->isSignal()) {
-            return _signalIcon;
+            return SignalIconType;
         } else if (symbol->isPublic()) {
-            return _funcPublicIcon;
+            return FuncPublicIconType;
         } else if (symbol->isProtected()) {
-            return _funcProtectedIcon;
+            return FuncProtectedIconType;
         } else if (symbol->isPrivate()) {
-            return _funcPrivateIcon;
+            return FuncPrivateIconType;
         }
     } else if (symbol->scope() && symbol->scope()->isEnumScope()) {
-        return _enumeratorIcon;
+        return EnumeratorIconType;
     } else if (symbol->isDeclaration() || symbol->isArgument()) {
         if (symbol->isPublic()) {
-            return _varPublicIcon;
+            return VarPublicIconType;
         } else if (symbol->isProtected()) {
-            return _varProtectedIcon;
+            return VarProtectedIconType;
         } else if (symbol->isPrivate()) {
-            return _varPrivateIcon;
+            return VarPrivateIconType;
         }
     } else if (symbol->isEnum()) {
-        return _enumIcon;
+        return EnumIconType;
     } else if (symbol->isClass() || symbol->isForwardClassDeclaration()) {
-        return _classIcon;
+        return ClassIconType;
     } else if (symbol->isObjCClass() || symbol->isObjCForwardClassDeclaration()) {
-        return _classIcon;
+        return ClassIconType;
     } else if (symbol->isObjCProtocol() || symbol->isObjCForwardProtocolDeclaration()) {
-        return _classIcon;
+        return ClassIconType;
     } else if (symbol->isObjCMethod()) {
-        return _funcPublicIcon;
+        return FuncPublicIconType;
     } else if (symbol->isNamespace()) {
-        return _namespaceIcon;
+        return NamespaceIconType;
     } else if (symbol->isUsingNamespaceDirective() ||
                symbol->isUsingDeclaration()) {
         // TODO: Might be nice to have a different icons for these things
-        return _namespaceIcon;
+        return NamespaceIconType;
     }
 
-    return QIcon();
-}
-
-QIcon Icons::keywordIcon() const
-{
-    return _keywordIcon;
+    return UnknownIconType;
 }
 
-QIcon Icons::macroIcon() const
+QIcon Icons::iconForType(IconType type) const
 {
-    return _macroIcon;
+    switch(type) {
+    case ClassIconType:
+        return _classIcon;
+    case EnumIconType:
+        return _enumIcon;
+    case EnumeratorIconType:
+        return _enumeratorIcon;
+    case FuncPublicIconType:
+        return _funcPublicIcon;
+    case FuncProtectedIconType:
+        return _funcProtectedIcon;
+    case FuncPrivateIconType:
+        return _funcPrivateIcon;
+    case NamespaceIconType:
+        return _namespaceIcon;
+    case VarPublicIconType:
+        return _varPublicIcon;
+    case VarProtectedIconType:
+        return _varProtectedIcon;
+    case VarPrivateIconType:
+        return _varPrivateIcon;
+    case SignalIconType:
+        return _signalIcon;
+    case SlotPublicIconType:
+        return _slotPublicIcon;
+    case SlotProtectedIconType:
+        return _slotProtectedIcon;
+    case SlotPrivateIconType:
+        return _slotPrivateIcon;
+    case KeywordIconType:
+        return _keywordIcon;
+    case MacroIconType:
+        return _macroIcon;
+    default:
+        break;
+    }
+    return QIcon();
 }
diff --git a/src/libs/cplusplus/Icons.h b/src/libs/cplusplus/Icons.h
index 4fd0d694239cce43357b00d730eccff3dfc78519..79c2ff965605a202a22551ee625779403c60d7a0 100644
--- a/src/libs/cplusplus/Icons.h
+++ b/src/libs/cplusplus/Icons.h
@@ -48,6 +48,29 @@ public:
     QIcon keywordIcon() const;
     QIcon macroIcon() const;
 
+    enum IconType {
+        ClassIconType = 0,
+        EnumIconType,
+        EnumeratorIconType,
+        FuncPublicIconType,
+        FuncProtectedIconType,
+        FuncPrivateIconType,
+        NamespaceIconType,
+        VarPublicIconType,
+        VarProtectedIconType,
+        VarPrivateIconType,
+        SignalIconType,
+        SlotPublicIconType,
+        SlotProtectedIconType,
+        SlotPrivateIconType,
+        KeywordIconType,
+        MacroIconType,
+        UnknownIconType
+    };
+
+    static IconType iconTypeForSymbol(const Symbol *symbol);
+    QIcon iconForType(IconType type) const;
+
 private:
     QIcon _classIcon;
     QIcon _enumIcon;
diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp
index ce832e2df60c7b5f911c70420489488fdfd1a0b5..5c935eb6a11babaaa9df83444c01264a570187ca 100644
--- a/src/libs/cplusplus/LookupContext.cpp
+++ b/src/libs/cplusplus/LookupContext.cpp
@@ -39,13 +39,17 @@
 #include <Scope.h>
 #include <Control.h>
 
-#include <QtDebug>
+#include <QtCore/QStack>
+#include <QtCore/QHash>
+#include <QtCore/QVarLengthArray>
+#include <QtCore/QtDebug>
+
+using namespace CPlusPlus;
 
 namespace {
-    const bool debug = ! qgetenv("CPLUSPLUS_LOOKUPCONTEXT_DEBUG").isEmpty();
-}
+const bool debug = ! qgetenv("CPLUSPLUS_LOOKUPCONTEXT_DEBUG").isEmpty();
+} // end of anonymous namespace
 
-using namespace CPlusPlus;
 
 static void addNames(const Name *name, QList<const Name *> *names, bool addAllNames = false)
 {
@@ -241,16 +245,16 @@ ClassOrNamespace *LookupContext::lookupType(Symbol *symbol) const
     return bindings()->lookupType(symbol);
 }
 
-QList<Symbol *> LookupContext::lookup(const Name *name, Scope *scope) const
+QList<LookupItem> LookupContext::lookup(const Name *name, Scope *scope) const
 {
-    QList<Symbol *> candidates;
+    QList<LookupItem> candidates;
 
     if (! name)
         return candidates;
 
     for (; scope; scope = scope->enclosingScope()) {
         if ((name->isNameId() || name->isTemplateNameId()) && scope->isBlockScope()) {
-            bindings()->lookupInScope(name, scope, &candidates, /*templateId = */ 0);
+            bindings()->lookupInScope(name, scope, &candidates, /*templateId = */ 0, /*binding=*/ 0);
 
             if (! candidates.isEmpty())
                 break; // it's a local.
@@ -274,10 +278,10 @@ QList<Symbol *> LookupContext::lookup(const Name *name, Scope *scope) const
 
         } else if (scope->isFunctionScope()) {
             Function *fun = scope->owner()->asFunction();
-            bindings()->lookupInScope(name, fun->arguments(), &candidates, /*templateId = */ 0);
+            bindings()->lookupInScope(name, fun->arguments(), &candidates, /*templateId = */ 0, /*binding=*/ 0);
 
             for (TemplateParameters *it = fun->templateParameters(); it && candidates.isEmpty(); it = it->previous())
-                bindings()->lookupInScope(name, it->scope(), &candidates, /* templateId = */ 0);
+                bindings()->lookupInScope(name, it->scope(), &candidates, /* templateId = */ 0, /*binding=*/ 0);
 
             if (! candidates.isEmpty())
                 break; // it's an argument or a template parameter.
@@ -295,7 +299,7 @@ QList<Symbol *> LookupContext::lookup(const Name *name, Scope *scope) const
 
         } else if (scope->isObjCMethodScope()) {
             ObjCMethod *method = scope->owner()->asObjCMethod();
-            bindings()->lookupInScope(name, method->arguments(), &candidates, /*templateId = */ 0);
+            bindings()->lookupInScope(name, method->arguments(), &candidates, /*templateId = */ 0, /*binding=*/ 0);
 
             if (! candidates.isEmpty())
                 break; // it's a formal argument.
@@ -304,7 +308,7 @@ QList<Symbol *> LookupContext::lookup(const Name *name, Scope *scope) const
             Class *klass = scope->owner()->asClass();
 
             for (TemplateParameters *it = klass->templateParameters(); it && candidates.isEmpty(); it = it->previous())
-                bindings()->lookupInScope(name, it->scope(), &candidates, /* templateId = */ 0);
+                bindings()->lookupInScope(name, it->scope(), &candidates, /* templateId = */ 0, /*binding=*/ 0);
 
             if (! candidates.isEmpty())
                 break; // it's an argument or a template parameter.
@@ -398,19 +402,19 @@ ClassOrNamespace *ClassOrNamespace::globalNamespace() const
     return e;
 }
 
-QList<Symbol *> ClassOrNamespace::find(const Name *name)
+QList<LookupItem> ClassOrNamespace::find(const Name *name)
 {
     return lookup_helper(name, false);
 }
 
-QList<Symbol *> ClassOrNamespace::lookup(const Name *name)
+QList<LookupItem> ClassOrNamespace::lookup(const Name *name)
 {
     return lookup_helper(name, true);
 }
 
-QList<Symbol *> ClassOrNamespace::lookup_helper(const Name *name, bool searchInEnclosingScope)
+QList<LookupItem> ClassOrNamespace::lookup_helper(const Name *name, bool searchInEnclosingScope)
 {
-    QList<Symbol *> result;
+    QList<LookupItem> result;
 
     if (name) {
         if (const QualifiedNameId *q = name->asQualifiedNameId()) {
@@ -435,9 +439,9 @@ QList<Symbol *> ClassOrNamespace::lookup_helper(const Name *name, bool searchInE
 }
 
 void ClassOrNamespace::lookup_helper(const Name *name, ClassOrNamespace *binding,
-                                     QList<Symbol *> *result,
-                                     QSet<ClassOrNamespace *> *processed,
-                                     const TemplateNameId *templateId)
+                                          QList<LookupItem> *result,
+                                          QSet<ClassOrNamespace *> *processed,
+                                          const TemplateNameId *templateId)
 {
     if (binding && ! processed->contains(binding)) {
         processed->insert(binding);
@@ -448,16 +452,20 @@ void ClassOrNamespace::lookup_helper(const Name *name, ClassOrNamespace *binding
             if (ScopedSymbol *scoped = s->asScopedSymbol()) {
                 if (Class *klass = scoped->asClass()) {
                     if (const Identifier *id = klass->identifier()) {
-                        if (nameId && nameId->isEqualTo(id))
-                            result->append(klass);
+                        if (nameId && nameId->isEqualTo(id)) {
+                            LookupItem item;
+                            item.setDeclaration(klass);
+                            item.setBinding(binding);
+                            result->append(item);
+                        }
                     }
                 }
-                _factory->lookupInScope(name, scoped->members(), result, templateId);
+                _factory->lookupInScope(name, scoped->members(), result, templateId, binding);
             }
         }
 
         foreach (Enum *e, binding->enums())
-            _factory->lookupInScope(name, e->members(), result, templateId);
+            _factory->lookupInScope(name, e->members(), result, templateId, binding);
 
         foreach (ClassOrNamespace *u, binding->usings())
             lookup_helper(name, u, result, processed, binding->_templateId);
@@ -465,8 +473,9 @@ void ClassOrNamespace::lookup_helper(const Name *name, ClassOrNamespace *binding
 }
 
 void CreateBindings::lookupInScope(const Name *name, Scope *scope,
-                                   QList<Symbol *> *result,
-                                   const TemplateNameId *templateId)
+                                   QList<LookupItem> *result,
+                                   const TemplateNameId *templateId,
+                                   ClassOrNamespace *binding)
 {
     Q_UNUSED(templateId);
 
@@ -480,7 +489,10 @@ void CreateBindings::lookupInScope(const Name *name, Scope *scope,
             else if (! s->name()->isEqualTo(op))
                 continue;
 
-            result->append(s);
+            LookupItem item;
+            item.setDeclaration(s);
+            item.setBinding(binding);
+            result->append(item);
         }
 
     } else if (const Identifier *id = name->identifier()) {
@@ -490,34 +502,17 @@ void CreateBindings::lookupInScope(const Name *name, Scope *scope,
             else if (s->name()->isQualifiedNameId())
                 continue; // skip qualified ids.
 
-            if (templateId && (s->isDeclaration() || s->isFunction())) {
+            LookupItem item;
+            item.setDeclaration(s);
+            item.setBinding(binding);
 
+            if (templateId && (s->isDeclaration() || s->isFunction())) {
                 FullySpecifiedType ty = DeprecatedGenTemplateInstance::instantiate(templateId, s, _control);
-
-                if (debug) {
-                    Overview oo;
-                    oo.setShowFunctionSignatures(true);
-                    oo.setShowReturnTypes(true);
-                    qDebug() << "instantiate:" << oo(s->type(), s->name()) << "using:" << oo(templateId) << oo(ty);
-                }
-
-                if (Declaration *decl = s->asDeclaration()) {
-                    Declaration *d = _control->newDeclaration(0, 0);
-                    d->copy(decl);
-                    d->setType(ty);
-                    result->append(d);
-                    continue;
-                } else if (Function *fun = s->asFunction()) {
-                    Function *d = ty->asFunctionType();
-                    d->copy(fun);
-                    result->append(d);
-                    continue;
-                }
+                item.setType(ty); // override the type.
             }
 
-            result->append(s);
+            result->append(item);
         }
-
     }
 }
 
@@ -987,3 +982,4 @@ bool CreateBindings::visit(ObjCMethod *)
 {
     return false;
 }
+
diff --git a/src/libs/cplusplus/LookupContext.h b/src/libs/cplusplus/LookupContext.h
index 3854b4cb7b7b5924d6f1556de3ffcc80972f6a96..db6163f8d06af7aed5553011fa444f5e739e45bb 100644
--- a/src/libs/cplusplus/LookupContext.h
+++ b/src/libs/cplusplus/LookupContext.h
@@ -36,6 +36,7 @@
 #include <Type.h>
 #include <SymbolVisitor.h>
 #include <Control.h>
+#include <Name.h>
 #include <QtCore/QSet>
 #include <map>
 #include <functional>
@@ -57,8 +58,8 @@ public:
 
     ClassOrNamespace *globalNamespace() const;
 
-    QList<Symbol *> lookup(const Name *name);
-    QList<Symbol *> find(const Name *name);
+    QList<LookupItem> lookup(const Name *name);
+    QList<LookupItem> find(const Name *name);
 
     ClassOrNamespace *lookupType(const Name *name);
     ClassOrNamespace *findType(const Name *name);
@@ -76,12 +77,12 @@ private:
     void addUsing(ClassOrNamespace *u);
     void addNestedType(const Name *alias, ClassOrNamespace *e);
 
-    QList<Symbol *> lookup_helper(const Name *name, bool searchInEnclosingScope);
+    QList<LookupItem> lookup_helper(const Name *name, bool searchInEnclosingScope);
 
     void lookup_helper(const Name *name, ClassOrNamespace *binding,
-                       QList<Symbol *> *result,
-                       QSet<ClassOrNamespace *> *processed,
-                       const TemplateNameId *templateId);
+                            QList<LookupItem> *result,
+                            QSet<ClassOrNamespace *> *processed,
+                            const TemplateNameId *templateId);
 
     ClassOrNamespace *lookupType_helper(const Name *name, QSet<ClassOrNamespace *> *processed,
                                         bool searchInEnclosingScope);
@@ -134,8 +135,8 @@ public:
     /// Searches in \a scope for symbols with the given \a name.
     /// Store the result in \a results.
     /// \internal
-    void lookupInScope(const Name *name, Scope *scope, QList<Symbol *> *result,
-                       const TemplateNameId *templateId);
+    void lookupInScope(const Name *name, Scope *scope, QList<LookupItem> *result,
+                            const TemplateNameId *templateId, ClassOrNamespace *binding);
 
     /// Create bindings for the symbols reachable from \a rootSymbol.
     /// \internal
@@ -214,7 +215,7 @@ public:
 
     ClassOrNamespace *globalNamespace() const;
 
-    QList<Symbol *> lookup(const Name *name, Scope *scope) const;
+    QList<LookupItem> lookup(const Name *name, Scope *scope) const;
     ClassOrNamespace *lookupType(const Name *name, Scope *scope) const;
     ClassOrNamespace *lookupType(Symbol *symbol) const;
     ClassOrNamespace *lookupParent(Symbol *symbol) const;
diff --git a/src/libs/cplusplus/LookupItem.cpp b/src/libs/cplusplus/LookupItem.cpp
index 2502c02790b6f5617136d0314b2be6676d08fb21..1bc49303a3114705e6ae52fa8f186a16caa39e73 100644
--- a/src/libs/cplusplus/LookupItem.cpp
+++ b/src/libs/cplusplus/LookupItem.cpp
@@ -44,11 +44,16 @@ uint CPlusPlus::qHash(const CPlusPlus::LookupItem &key)
 }
 
 LookupItem::LookupItem()
-    : _scope(0), _declaration(0)
+    : _scope(0), _declaration(0), _binding(0)
 { }
 
 FullySpecifiedType LookupItem::type() const
-{ return _type; }
+{
+    if (! _type && _declaration)
+        return _declaration->type();
+
+    return _type;
+}
 
 void LookupItem::setType(const FullySpecifiedType &type)
 { _type = type; }
@@ -70,9 +75,16 @@ Scope *LookupItem::scope() const
 void LookupItem::setScope(Scope *scope)
 { _scope = scope; }
 
+ClassOrNamespace *LookupItem::binding() const
+{ return _binding; }
+
+void LookupItem::setBinding(ClassOrNamespace *binding)
+{ _binding = binding; }
+
 bool LookupItem::operator == (const LookupItem &other) const
 {
-    if (_type == other._type && _declaration == other._declaration && _scope == other._scope)
+    if (_type == other._type && _declaration == other._declaration && _scope == other._scope
+            && _binding == other._binding)
         return true;
 
     return false;
diff --git a/src/libs/cplusplus/LookupItem.h b/src/libs/cplusplus/LookupItem.h
index 14ba99c5734ff1cdeaac98e79f3f15edc4a5bed4..489fe31a09709bc10248afb2e497a1a75a0b1d43 100644
--- a/src/libs/cplusplus/LookupItem.h
+++ b/src/libs/cplusplus/LookupItem.h
@@ -35,6 +35,8 @@
 
 namespace CPlusPlus {
 
+class ClassOrNamespace;
+
 class CPLUSPLUS_EXPORT LookupItem
 {
 public:
@@ -59,6 +61,9 @@ public:
     /// Sets this item's scope.
     void setScope(Scope *scope);
 
+    ClassOrNamespace *binding() const;
+    void setBinding(ClassOrNamespace *binding);
+
     bool operator == (const LookupItem &other) const;
     bool operator != (const LookupItem &other) const;
 
@@ -66,6 +71,7 @@ private:
     FullySpecifiedType _type;
     Scope *_scope;
     Symbol *_declaration;
+    ClassOrNamespace *_binding;
 };
 
 uint qHash(const CPlusPlus::LookupItem &result);
diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp
index b02b7ecf5d1dda510e5a499f587b56decbd329ce..3f2ae7ac82e12157d8e62e53544e2f481f1207ae 100644
--- a/src/libs/cplusplus/ResolveExpression.cpp
+++ b/src/libs/cplusplus/ResolveExpression.cpp
@@ -31,6 +31,7 @@
 #include "LookupContext.h"
 #include "Overview.h"
 #include "DeprecatedGenTemplateInstance.h"
+#include "CppRewriter.h"
 
 #include <Control.h>
 #include <AST.h>
@@ -121,6 +122,11 @@ void ResolveExpression::addResults(const QList<Symbol *> &symbols)
     }
 }
 
+void ResolveExpression::addResults(const QList<LookupItem> &items)
+{
+    _results += items;
+}
+
 void ResolveExpression::addResult(const FullySpecifiedType &ty, Scope *scope)
 {
     LookupItem item;
@@ -395,7 +401,7 @@ bool ResolveExpression::visit(CompoundLiteralAST *ast)
 bool ResolveExpression::visit(QualifiedNameAST *ast)
 {
     if (const Name *name = ast->name) {
-        const QList<Symbol *> candidates = _context.lookup(name, _scope);
+        const QList<LookupItem> candidates = _context.lookup(name, _scope);
         addResults(candidates);
     }
 
@@ -404,14 +410,14 @@ bool ResolveExpression::visit(QualifiedNameAST *ast)
 
 bool ResolveExpression::visit(SimpleNameAST *ast)
 {
-    const QList<Symbol *> candidates = _context.lookup(ast->name, _scope);
+    const QList<LookupItem> candidates = _context.lookup(ast->name, _scope);
     addResults(candidates);
     return false;
 }
 
 bool ResolveExpression::visit(TemplateIdAST *ast)
 {
-    const QList<Symbol *> candidates = _context.lookup(ast->name, _scope);
+    const QList<LookupItem> candidates = _context.lookup(ast->name, _scope);
     addResults(candidates);
     return false;
 }
@@ -477,7 +483,8 @@ bool ResolveExpression::visit(CallAST *ast)
 
         if (NamedType *namedTy = ty->asNamedType()) {
             if (ClassOrNamespace *b = _context.lookupType(namedTy->name(), scope)) {
-                foreach (Symbol *overload, b->find(functionCallOp)) {
+                foreach (const LookupItem &r, b->find(functionCallOp)) {
+                    Symbol *overload = r.declaration();
                     if (Function *funTy = overload->type()->asFunctionType()) {
                         if (maybeValidPrototype(funTy, actualArgumentCount)) {
                             if (Function *proto = instantiate(namedTy->name(), funTy)->asFunctionType())
@@ -520,7 +527,8 @@ bool ResolveExpression::visit(ArrayAccessAST *ast)
 
         } else if (NamedType *namedTy = ty->asNamedType()) {
             if (ClassOrNamespace *b = _context.lookupType(namedTy->name(), scope)) {
-                foreach (Symbol *overload, b->find(arrayAccessOp)) {
+                foreach (const LookupItem &r, b->find(arrayAccessOp)) {
+                    Symbol *overload = r.declaration();
                     if (Function *funTy = overload->type()->asFunctionType()) {
                         if (Function *proto = instantiate(namedTy->name(), funTy)->asFunctionType())
                             // ### TODO: check the actual arguments
@@ -534,6 +542,56 @@ bool ResolveExpression::visit(ArrayAccessAST *ast)
     return false;
 }
 
+QList<LookupItem> ResolveExpression::getMembers(ClassOrNamespace *binding, const Name *memberName) const
+{
+    QList<LookupItem> members;
+
+    const QList<LookupItem> originalMembers = binding->find(memberName);
+
+    foreach (const LookupItem &m, originalMembers) {
+        if (! m.binding() || ! m.binding()->templateId()) {
+            members.append(m);
+            continue;
+        }
+
+        Symbol *decl = m.declaration();
+
+        if (Class *klass = decl->enclosingSymbol()->asClass()) {
+            if (klass->templateParameters() != 0) {
+                SubstitutionMap map;
+
+                const TemplateNameId *templateId = m.binding()->templateId();
+                unsigned count = qMin(klass->templateParameterCount(), templateId->templateArgumentCount());
+
+                for (unsigned i = 0; i < count; ++i) {
+                    map.bind(klass->templateParameterAt(i)->name(), templateId->templateArgumentAt(i));
+                }
+
+                SubstitutionEnvironment env;
+                ContextSubstitution ctxSubst(_context, m.scope());
+
+                env.enter(&ctxSubst);
+                env.enter(&map);
+                FullySpecifiedType instantiatedTy = rewriteType(decl->type(), env, _context.control().data());
+
+                Overview oo;
+                oo.setShowReturnTypes(true);
+                oo.setShowFunctionSignatures(true);
+
+                qDebug() << "original:" << oo(decl->type(), decl->name()) << "inst:" << oo(instantiatedTy, decl->name());
+
+                LookupItem newItem;
+                newItem = m;
+                newItem.setType(instantiatedTy);
+                members.append(newItem);
+            }
+        }
+    }
+
+
+    return members;
+}
+
 bool ResolveExpression::visit(MemberAccessAST *ast)
 {
     // The candidate types for the base expression are stored in
@@ -586,9 +644,13 @@ ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &bas
 
             } else if (ClassOrNamespace *binding = findClass(ty, scope)) {
                 // lookup for overloads of operator->
+
                 const OperatorNameId *arrowOp = control()->operatorNameId(OperatorNameId::ArrowOp);
+                foreach (const LookupItem &r, binding->find(arrowOp)) {
+                    Symbol *overload = r.declaration();
+                    if (! overload)
+                        continue;
 
-                foreach (Symbol *overload, binding->find(arrowOp)) {
                     if (overload->type()->isFunctionType()) {
                         FullySpecifiedType overloadTy = instantiate(binding->templateId(), overload);
                         Function *instantiatedFunction = overloadTy->asFunctionType();
@@ -604,14 +666,10 @@ ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &bas
                                 if (ClassOrNamespace *retBinding = findClass(ptrTy->elementType(), scope))
                                     return retBinding;
                             }
-
-                            if (debug) {
-                                Overview oo;
-                                qDebug() << "no class for:" << oo(ptrTy->elementType());
-                            }
                         }
                     }
                 }
+
             }
         } else if (accessOp == T_DOT) {
             if (replacedDotOperator) {
@@ -663,9 +721,11 @@ bool ResolveExpression::visit(ObjCMessageExpressionAST *ast)
         }
 
         if (binding) {
-            foreach (Symbol *s, binding->lookup(ast->selector->name))
+            foreach (const LookupItem &r, binding->lookup(ast->selector->name)) {
+                Symbol *s = r.declaration();
                 if (ObjCMethod *m = s->asObjCMethod())
                     addResult(m->returnType(), result.scope());
+            }
         }
     }
 
diff --git a/src/libs/cplusplus/ResolveExpression.h b/src/libs/cplusplus/ResolveExpression.h
index 8496631af4c2247cd95be0760560a4134f145ff8..19692a37def993f21b8d905a7d22b71305af901a 100644
--- a/src/libs/cplusplus/ResolveExpression.h
+++ b/src/libs/cplusplus/ResolveExpression.h
@@ -59,10 +59,13 @@ protected:
     QList<LookupItem> switchResults(const QList<LookupItem> &symbols);
     FullySpecifiedType instantiate(const Name *className, Symbol *candidate) const;
 
+    Q_DECL_DEPRECATED QList<LookupItem> getMembers(ClassOrNamespace *binding, const Name *memberName) const;
+
     void thisObject();
 
     void addResult(const FullySpecifiedType &ty, Scope *scope);
     void addResults(const QList<Symbol *> &symbols);
+    void addResults(const QList<LookupItem> &items);
 
     bool maybeValidPrototype(Function *funTy, unsigned actualArgumentCount) const;
 
diff --git a/src/libs/cplusplus/cplusplus-lib.pri b/src/libs/cplusplus/cplusplus-lib.pri
index 24bb51cf5e2c9216b00754d32d2b5cf2d9a506a5..2a718d5712b359407a1a85ed9856d4b28bef2836 100644
--- a/src/libs/cplusplus/cplusplus-lib.pri
+++ b/src/libs/cplusplus/cplusplus-lib.pri
@@ -27,6 +27,7 @@ SOURCES += \
 HEADERS += \
     $$PWD/SimpleLexer.h \
     $$PWD/CppDocument.h \
+    $$PWD/CppRewriter.h \
     $$PWD/Overview.h \
     $$PWD/NamePrettyPrinter.h \
     $$PWD/TypeOfExpression.h \
@@ -52,6 +53,7 @@ HEADERS += \
 SOURCES += \
     $$PWD/SimpleLexer.cpp \
     $$PWD/CppDocument.cpp \
+    $$PWD/CppRewriter.cpp \
     $$PWD/Overview.cpp \
     $$PWD/NamePrettyPrinter.cpp \
     $$PWD/TypeOfExpression.cpp \
diff --git a/src/libs/qmljs/qmljsbind.cpp b/src/libs/qmljs/qmljsbind.cpp
index 0328a7c9a22d6de56f006e071d6500631c3168c9..a8b7a2a1f3afb11a67cd7e28146a46bd2bba51a5 100644
--- a/src/libs/qmljs/qmljsbind.cpp
+++ b/src/libs/qmljs/qmljsbind.cpp
@@ -181,6 +181,7 @@ bool Bind::visit(AST::Program *)
 bool Bind::visit(UiImport *ast)
 {
     ImportInfo info;
+    info.ast = ast;
 
     if (ast->versionToken.isValid()) {
         const QString versionString = _doc->source().mid(ast->versionToken.offset, ast->versionToken.length);
diff --git a/src/libs/qmljs/qmljsbind.h b/src/libs/qmljs/qmljsbind.h
index e71f171774d95da099838a4768b62d396cd07ce4..a836eac18a5d95865c93214a946b01c506c10493 100644
--- a/src/libs/qmljs/qmljsbind.h
+++ b/src/libs/qmljs/qmljsbind.h
@@ -54,6 +54,7 @@ public:
     struct ImportInfo {
         QString name;
         ComponentVersion version;
+        AST::UiImport *ast;
     };
 
     QList<ImportInfo> fileImports() const;
diff --git a/src/libs/qmljs/qmljsinterpreter.cpp b/src/libs/qmljs/qmljsinterpreter.cpp
index d8b4d2c62333c041eae06af8d03e4877d4f1147e..6a084d04689f173646f56acd5dc3de0e39522d41 100644
--- a/src/libs/qmljs/qmljsinterpreter.cpp
+++ b/src/libs/qmljs/qmljsinterpreter.cpp
@@ -2959,7 +2959,7 @@ const Value *ASTVariableReference::value(Context *context) const
     return check(_ast->expression);
 }
 
-ASTFunctionValue::ASTFunctionValue(FunctionDeclaration *ast, const Document *doc, Engine *engine)
+ASTFunctionValue::ASTFunctionValue(FunctionDeclaration *ast, const QmlJS::Document *doc, Engine *engine)
     : FunctionValue(engine), _doc(doc), _ast(ast)
 {
     setPrototype(engine->functionPrototype());
diff --git a/src/libs/utils/navigationtreeview.cpp b/src/libs/utils/navigationtreeview.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0974bccaaa0ad95ddb73b9d90bb458e5e66e6d92
--- /dev/null
+++ b/src/libs/utils/navigationtreeview.cpp
@@ -0,0 +1,79 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 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 "navigationtreeview.h"
+
+#include <QtGui/QFocusEvent>
+
+#ifdef Q_WS_MAC
+#include <QtGui/QKeyEvent>
+#endif
+
+namespace Utils {
+
+NavigationTreeView::NavigationTreeView(QWidget *parent)
+    : QTreeView(parent)
+{
+    setFrameStyle(QFrame::NoFrame);
+    setIndentation(indentation() * 9/10);
+    setUniformRowHeights(true);
+    setTextElideMode(Qt::ElideNone);
+    setAttribute(Qt::WA_MacShowFocusRect, false);
+}
+
+// This is a workaround to stop Qt from redrawing the project tree every
+// time the user opens or closes a menu when it has focus. Would be nicer to
+// fix it in Qt.
+void NavigationTreeView::focusInEvent(QFocusEvent *event)
+{
+    if (event->reason() != Qt::PopupFocusReason)
+        QTreeView::focusInEvent(event);
+}
+
+void NavigationTreeView::focusOutEvent(QFocusEvent *event)
+{
+    if (event->reason() != Qt::PopupFocusReason)
+        QTreeView::focusOutEvent(event);
+}
+
+#ifdef Q_WS_MAC
+void NavigationTreeView::keyPressEvent(QKeyEvent *event)
+{
+    if ((event->key() == Qt::Key_Return
+            || event->key() == Qt::Key_Enter)
+            && event->modifiers() == 0
+            && currentIndex().isValid()) {
+        emit activated(currentIndex());
+        return;
+    }
+    QTreeView::keyPressEvent(event);
+}
+#endif
+
+} // namespace Utils
diff --git a/src/libs/utils/navigationtreeview.h b/src/libs/utils/navigationtreeview.h
new file mode 100644
index 0000000000000000000000000000000000000000..697fed10124e94ae4f1fd340f2d52d986963f629
--- /dev/null
+++ b/src/libs/utils/navigationtreeview.h
@@ -0,0 +1,63 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 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 NAVIGATIONTREEVIEW_H
+#define NAVIGATIONTREEVIEW_H
+
+#include "utils_global.h"
+
+#include <QtGui/QTreeView>
+
+namespace Utils {
+
+/*!
+   \class NavigationTreeView
+   \sa Core::NavigationView, Core::INavigationWidgetFactory
+
+   General TreeView for any Side Bar widget. Common initialization etc, e.g. Mac specific behaviour.
+ */
+
+class QTCREATOR_UTILS_EXPORT NavigationTreeView : public QTreeView
+{
+    Q_OBJECT
+public:
+    NavigationTreeView(QWidget *parent = 0);
+
+protected:
+    void focusInEvent(QFocusEvent *event);
+    void focusOutEvent(QFocusEvent *event);
+
+#ifdef Q_WS_MAC
+    void keyPressEvent(QKeyEvent *event);
+#endif
+};
+
+} // Utils
+
+#endif // NAVIGATIONTREEVIEW_H
diff --git a/src/libs/utils/utils.pro b/src/libs/utils/utils.pro
index a189b6725083f21ff0b9234db75b8cfd268a8c64..582286884c3f057f40b5f8889bc4c42722352c00 100644
--- a/src/libs/utils/utils.pro
+++ b/src/libs/utils/utils.pro
@@ -41,7 +41,8 @@ SOURCES += reloadpromptutils.cpp \
     changeset.cpp \
     filterlineedit.cpp \
     faketooltip.cpp \
-    htmldocextractor.cpp
+    htmldocextractor.cpp \
+    navigationtreeview.cpp
 win32 {
     SOURCES += abstractprocess_win.cpp \
         consoleprocess_win.cpp \
@@ -95,7 +96,8 @@ HEADERS += utils_global.h \
     changeset.h \
     filterlineedit.h \
     faketooltip.h \
-    htmldocextractor.h
+    htmldocextractor.h \
+    navigationtreeview.h
 FORMS += filewizardpage.ui \
     projectintropage.ui \
     newclasswidget.ui \
diff --git a/src/plugins/classview/ClassView.pluginspec b/src/plugins/classview/ClassView.pluginspec
new file mode 100644
index 0000000000000000000000000000000000000000..af18b6b88b0bb7d7dc9e06a2c32f7373d3378617
--- /dev/null
+++ b/src/plugins/classview/ClassView.pluginspec
@@ -0,0 +1,22 @@
+<plugin name="ClassView" version="2.1.80" compatVersion="2.1.80">
+    <vendor>Nokia Corporation</vendor>
+    <copyright>(C) 2010 Denis Mingulov</copyright>
+    <license>
+Commercial Usage
+
+Licensees holding valid Qt Commercial licenses may use this plugin 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 plugin may be used under the terms of the GNU Lesser General Public License version 2.1 as published by the Free Software Foundation.  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.
+    </license>
+    <category>Qt Creator</category>
+    <description>Class View component.</description>
+    <url>http://qt.nokia.com</url>
+    <dependencyList>
+        <dependency name="Core" version="2.1.80"/>
+        <dependency name="CppTools" version="2.1.80"/>
+        <dependency name="ProjectExplorer" version="2.1.80"/>
+        <dependency name="TextEditor" version="2.1.80"/>
+    </dependencyList>
+</plugin>
diff --git a/src/plugins/classview/classview.pro b/src/plugins/classview/classview.pro
new file mode 100644
index 0000000000000000000000000000000000000000..d6de0d148abaae2d6bc4b0c454b1804fb89b1b45
--- /dev/null
+++ b/src/plugins/classview/classview.pro
@@ -0,0 +1,38 @@
+TEMPLATE = lib
+TARGET = ClassView
+
+include(classview_dependencies.pri)
+
+HEADERS += \
+    classviewplugin.h \
+    classviewnavigationwidgetfactory.h \
+    classviewconstants.h \
+    classviewnavigationwidget.h \
+    classviewparser.h \
+    classviewmanager.h \
+    classviewsymbollocation.h \
+    classviewsymbolinformation.h \
+    classviewparsertreeitem.h \
+    classviewutils.h \
+    classviewtreeitemmodel.h
+
+SOURCES += \
+    classviewplugin.cpp \
+    classviewnavigationwidgetfactory.cpp \
+    classviewnavigationwidget.cpp \
+    classviewparser.cpp \
+    classviewmanager.cpp \
+    classviewsymbollocation.cpp \
+    classviewsymbolinformation.cpp \
+    classviewparsertreeitem.cpp \
+    classviewutils.cpp \
+    classviewtreeitemmodel.cpp
+
+OTHER_FILES += \
+    ClassView.pluginspec
+
+FORMS += \
+    classviewnavigationwidget.ui
+
+RESOURCES += \
+    classview.qrc
diff --git a/src/plugins/classview/classview.qrc b/src/plugins/classview/classview.qrc
new file mode 100644
index 0000000000000000000000000000000000000000..189357bc0be59365df0b90c7b9fe7ac83b8fc3b2
--- /dev/null
+++ b/src/plugins/classview/classview.qrc
@@ -0,0 +1,5 @@
+<RCC>
+    <qresource prefix="/classview">
+        <file>images/hierarchicalmode.png</file>
+    </qresource>
+</RCC>
diff --git a/src/plugins/classview/classview_dependencies.pri b/src/plugins/classview/classview_dependencies.pri
new file mode 100644
index 0000000000000000000000000000000000000000..fd0ecfea3fcbfa9bb09a00acb45c6b4b29a9e708
--- /dev/null
+++ b/src/plugins/classview/classview_dependencies.pri
@@ -0,0 +1,7 @@
+include(../../qtcreatorplugin.pri)
+include(../../libs/utils/utils.pri)
+include(../../plugins/coreplugin/coreplugin.pri)
+include(../../plugins/cpptools/cpptools.pri)
+include(../../plugins/projectexplorer/projectexplorer.pri)
+include(../../libs/cplusplus/cplusplus.pri)
+include(../../plugins/texteditor/texteditor.pri)
diff --git a/src/plugins/classview/classviewconstants.h b/src/plugins/classview/classviewconstants.h
new file mode 100644
index 0000000000000000000000000000000000000000..17b03bd560a6b97e3c8e8974a0c506fe19c6b102
--- /dev/null
+++ b/src/plugins/classview/classviewconstants.h
@@ -0,0 +1,62 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Denis Mingulov.
+**
+** 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 CLASSVIEWCONSTANTS_H
+#define CLASSVIEWCONSTANTS_H
+
+namespace ClassView {
+namespace Constants {
+
+//! Navi Widget Factory id
+const char * const CLASSVIEWNAVIGATION_ID = "Class View";
+
+//! Settings' group
+const char * const CLASSVIEW_SETTINGS_GROUP = "ClassView";
+
+//! Settings' prefix for the tree widget
+const char * const CLASSVIEW_SETTINGS_TREEWIDGET_PREFIX = "TreeWidget.";
+
+//! Flat mode settings
+const char * const CLASSVIEW_SETTINGS_FLATMODE = "FlatMode";
+
+//! Delay in msecs before an update
+const int CLASSVIEW_EDITINGTREEUPDATE_DELAY = 400;
+
+//! QStandardItem roles
+enum ItemRole {
+    SymbolLocationsRole = Qt::UserRole + 1, //!< Symbol locations
+    IconTypeRole,                           //!< Icon type (integer)
+    SymbolNameRole,                         //!< Symbol name
+    SymbolTypeRole                          //!< Symbol type
+};
+
+} // namespace Constants
+} // namespace ClassView
+
+#endif // CLASSVIEWCONSTANTS_H
diff --git a/src/plugins/classview/classviewmanager.cpp b/src/plugins/classview/classviewmanager.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b602333684795ce4edf14903b203c7ad9dd0dfce
--- /dev/null
+++ b/src/plugins/classview/classviewmanager.cpp
@@ -0,0 +1,380 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Denis Mingulov.
+**
+** 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 "classviewsymbollocation.h"
+#include "classviewmanager.h"
+#include "classviewnavigationwidgetfactory.h"
+#include "classviewparser.h"
+#include "classviewutils.h"
+
+#include <utils/qtcassert.h>
+#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/session.h>
+#include <texteditor/basetexteditor.h>
+#include <cpptools/cppmodelmanagerinterface.h>
+#include <cpptools/cpptoolsconstants.h>
+#include <coreplugin/icore.h>
+#include <coreplugin/progressmanager/progressmanager.h>
+#include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/editormanager/ieditor.h>
+#include <texteditor/itexteditor.h>
+
+#include <QtCore/QThread>
+#include <QtCore/QMutex>
+#include <QtCore/QMutexLocker>
+
+namespace ClassView {
+namespace Internal {
+
+///////////////////////////////// ManagerPrivate //////////////////////////////////
+
+/*!
+   \struct ManagerPrivate
+   \brief Private class data for \a Manager
+   \sa Manager
+ */
+struct ManagerPrivate
+{
+    ManagerPrivate() : state(false) {}
+
+    //! instance
+    static Manager *instance;
+
+    //! Pointer to widget factory
+    QPointer<NavigationWidgetFactory> widgetFactory;
+
+    //! State mutex
+    QMutex mutexState;
+
+    //! Internal manager state. \sa Manager::state
+    bool state;
+
+    //! code state/changes parser
+    Parser parser;
+
+    //! separate thread for the parser
+    QThread parserThread;
+
+    //! cpp code model manager
+    QPointer<CppTools::CppModelManagerInterface> codeModelManager;
+
+    //! there is some massive operation ongoing so temporary we should wait
+    bool disableCodeParser;
+};
+
+// static variable initialization
+Manager *ManagerPrivate::instance = 0;
+
+///////////////////////////////// Manager //////////////////////////////////
+
+Manager::Manager(QObject *parent)
+    : QObject(parent),
+    d_ptr(new ManagerPrivate())
+{
+    d_ptr->widgetFactory = NavigationWidgetFactory::instance();
+
+    // register - to be able send between signal/slots
+    qRegisterMetaType<QSharedPointer<QStandardItem> >("QSharedPointer<QStandardItem>");
+
+    initialize();
+
+    // start a separate thread for the parser
+    d_ptr->parser.moveToThread(&d_ptr->parserThread);
+    d_ptr->parserThread.start();
+
+    // initial setup
+    onProjectListChanged();
+}
+
+Manager::~Manager()
+{
+    d_ptr->parserThread.quit();
+    d_ptr->parserThread.wait();
+}
+
+Manager *Manager::instance(QObject *parent)
+{
+    if (!ManagerPrivate::instance)
+        ManagerPrivate::instance = new Manager(parent);
+    return ManagerPrivate::instance;
+}
+
+bool Manager::canFetchMore(QStandardItem *item) const
+{
+    return d_ptr->parser.canFetchMore(item);
+}
+
+void Manager::fetchMore(QStandardItem *item, bool skipRoot)
+{
+    d_ptr->parser.fetchMore(item, skipRoot);
+}
+
+void Manager::initialize()
+{
+    // use Qt::QueuedConnection everywhere
+
+    // widget factory signals
+    connect(d_ptr->widgetFactory, SIGNAL(widgetIsCreated()),
+            SLOT(onWidgetIsCreated()), Qt::QueuedConnection);
+
+    // internal manager state is changed
+    connect(this, SIGNAL(stateChanged(bool)), SLOT(onStateChanged(bool)), Qt::QueuedConnection);
+
+    // connections to enable/disbale navi widget factory
+    ProjectExplorer::SessionManager *sessionManager =
+        ProjectExplorer::ProjectExplorerPlugin::instance()->session();
+    connect(sessionManager, SIGNAL(projectAdded(ProjectExplorer::Project*)),
+            SLOT(onProjectListChanged()), Qt::QueuedConnection);
+    connect(sessionManager, SIGNAL(projectRemoved(ProjectExplorer::Project*)),
+            SLOT(onProjectListChanged()), Qt::QueuedConnection);
+
+    Core::ICore *core = Core::ICore::instance();
+
+    // connect to the progress manager for signals about Parsing tasks
+    connect(core->progressManager(), SIGNAL(taskStarted(QString)),
+            SLOT(onTaskStarted(QString)), Qt::QueuedConnection);
+    connect(core->progressManager(), SIGNAL(allTasksFinished(QString)),
+            SLOT(onAllTasksFinished(QString)), Qt::QueuedConnection);
+
+    // connect to the cpp model manager for signals about document updates
+    d_ptr->codeModelManager = CppTools::CppModelManagerInterface::instance();
+
+    // when code manager signals that document is updated - handle it by ourselves
+    connect(d_ptr->codeModelManager, SIGNAL(documentUpdated(CPlusPlus::Document::Ptr)),
+            SLOT(onDocumentUpdated(CPlusPlus::Document::Ptr)), Qt::QueuedConnection);
+
+    // when we signals that really document is updated - sent it to the parser
+    connect(this, SIGNAL(requestDocumentUpdated(CPlusPlus::Document::Ptr)),
+            &d_ptr->parser, SLOT(parseDocument(CPlusPlus::Document::Ptr)), Qt::QueuedConnection);
+
+    //
+    connect(d_ptr->codeModelManager, SIGNAL(aboutToRemoveFiles(QStringList)),
+            &d_ptr->parser, SLOT(removeFiles(QStringList)), Qt::QueuedConnection);
+
+    // translate data update from the parser to listeners
+    connect(&d_ptr->parser, SIGNAL(treeDataUpdate(QSharedPointer<QStandardItem>)),
+            this, SLOT(onTreeDataUpdate(QSharedPointer<QStandardItem>)), Qt::QueuedConnection);
+
+    // requet current state - immediately after a notification
+    connect(this, SIGNAL(requestTreeDataUpdate()),
+            &d_ptr->parser, SLOT(requestCurrentState()), Qt::QueuedConnection);
+
+    // full reset request to parser
+    connect(this, SIGNAL(requestResetCurrentState()),
+            &d_ptr->parser, SLOT(resetDataToCurrentState()), Qt::QueuedConnection);
+
+    // clear cache request
+    connect(this, SIGNAL(requestClearCache()),
+            &d_ptr->parser, SLOT(clearCache()), Qt::QueuedConnection);
+
+    // clear full cache request
+    connect(this, SIGNAL(requestClearCacheAll()),
+            &d_ptr->parser, SLOT(clearCacheAll()), Qt::QueuedConnection);
+
+    // flat mode request
+    connect(this, SIGNAL(requestSetFlatMode(bool)),
+            &d_ptr->parser, SLOT(setFlatMode(bool)), Qt::QueuedConnection);
+}
+
+bool Manager::state() const
+{
+    return d_ptr->state;
+}
+
+void Manager::setState(bool state)
+{
+    QMutexLocker locker(&d_ptr->mutexState);
+
+    // boolean comparsion - should be done correctly by any compiler
+    if (state == d_ptr->state)
+        return;
+
+    d_ptr->state = state;
+
+    emit stateChanged(d_ptr->state);
+}
+
+void Manager::onWidgetIsCreated()
+{
+    // do nothing - continue to sleep
+}
+
+void Manager::onWidgetVisibilityIsChanged(bool visibility)
+{
+    // activate data handling - when 1st time 'Class View' will be open
+    if (visibility)
+        setState(true);
+}
+
+void Manager::onStateChanged(bool state)
+{
+    if (state) {
+        // enabled - request a current snapshots etc?..
+        emit requestResetCurrentState();
+    } else {
+        // disabled - clean parsers internal cache
+        emit requestClearCacheAll();
+    }
+}
+
+void Manager::onProjectListChanged()
+{
+    // do nothing if Manager is disabled
+    if (!state())
+        return;
+
+    // update to the latest state
+    requestTreeDataUpdate();
+}
+
+void Manager::onTaskStarted(const QString &type)
+{
+    if (type != CppTools::Constants::TASK_INDEX)
+        return;
+
+    // disable tree updates to speed up
+    d_ptr->disableCodeParser = true;
+}
+
+void Manager::onAllTasksFinished(const QString &type)
+{
+    if (type != CppTools::Constants::TASK_INDEX)
+        return;
+
+    // parsing is finished, enable tree updates
+    d_ptr->disableCodeParser = false;
+
+    // do nothing if Manager is disabled
+    if (!state())
+        return;
+
+    // any document might be changed, emit signal to clear cache
+    emit requestClearCache();
+
+    // request to update a tree to the current state
+    emit requestResetCurrentState();
+}
+
+void Manager::onDocumentUpdated(CPlusPlus::Document::Ptr doc)
+{
+    // do nothing if Manager is disabled
+    if (!state())
+        return;
+
+    // do nothing if updates are disabled
+    if (d_ptr->disableCodeParser)
+        return;
+
+    emit requestDocumentUpdated(doc);
+}
+
+void Manager::gotoLocation(const QString &fileName, int line, int column)
+{
+    bool newEditor = false;
+    TextEditor::BaseTextEditor::openEditorAt(fileName, line, column, QString(), &newEditor);
+}
+
+void Manager::gotoLocations(const QList<QVariant> &list)
+{
+    QSet<SymbolLocation> locations = Utils::roleToLocations(list);
+
+    if (locations.count() == 0)
+        return;
+
+    QString fileName;
+    int line = 0;
+    int column = 0;
+    bool currentPositionAvailable = false;
+
+    // what is open now?
+    Core::IEditor *editor = Core::EditorManager::instance()->currentEditor();
+    if (editor) {
+        // get current file name
+        Core::IFile *file = editor->file();
+        if (file)
+            fileName = file->fileName();
+
+        // if text file - what is current position?
+        TextEditor::ITextEditor *textEditor = qobject_cast<TextEditor::ITextEditor *>(editor);
+        if (textEditor) {
+            // there is open currently text editor
+            int position = textEditor->position();
+            textEditor->convertPosition(position, &line, &column);
+            currentPositionAvailable = true;
+        }
+    }
+
+    // if there is something open - try to check, is it currently activated symbol?
+    if (currentPositionAvailable) {
+        SymbolLocation current(fileName, line, column);
+        QSet<SymbolLocation>::const_iterator it = locations.find(current);
+        QSet<SymbolLocation>::const_iterator end = locations.constEnd();
+        // is it known location?
+        if (it != end) {
+            // found - do one additional step
+            ++it;
+            if (it == end)
+                it = locations.begin();
+            const SymbolLocation &found = *it;
+            gotoLocation(found.fileName(), found.line(), found.column());
+            return;
+        }
+    }
+
+    // no success - open first item in the list
+    const SymbolLocation loc = *locations.constBegin();
+
+    gotoLocation(loc.fileName(), loc.line(), loc.column());
+}
+
+void Manager::onRequestTreeDataUpdate()
+{
+    // do nothing if Manager is disabled
+    if (!state())
+        return;
+
+    emit requestTreeDataUpdate();
+}
+
+void Manager::setFlatMode(bool flat)
+{
+    emit requestSetFlatMode(flat);
+}
+
+void Manager::onTreeDataUpdate(QSharedPointer<QStandardItem> result)
+{
+    // do nothing if Manager is disabled
+    if (!state())
+        return;
+
+    emit treeDataUpdate(result);
+}
+
+} // namespace Internal
+} // namespace ClassView
diff --git a/src/plugins/classview/classviewmanager.h b/src/plugins/classview/classviewmanager.h
new file mode 100644
index 0000000000000000000000000000000000000000..3fb99f30b4ae9e1377530e779cd2bf26ac83fe3f
--- /dev/null
+++ b/src/plugins/classview/classviewmanager.h
@@ -0,0 +1,247 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Denis Mingulov.
+**
+** 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 CLASSVIEWMANAGER_H
+#define CLASSVIEWMANAGER_H
+
+#include <QtCore/QObject>
+#include <QtCore/QScopedPointer>
+#include <QtCore/QSharedPointer>
+#include <QtGui/QStandardItem>
+
+#include <cplusplus/CppDocument.h>
+
+namespace ClassView {
+namespace Internal {
+
+class NavigationWidgetFactory;
+
+/*!
+   \class Manager
+   \brief Class View manager
+
+   Class View Manager. Interacts with other Qt Creator plugins - this is a proxy between them and
+   parser.
+   \a Parser is moved to a separate thread and is connected to \a Manager by signal/slots.
+   Manager's signals starting with 'request' are for Parser.
+ */
+
+class Manager : public QObject
+{
+    Q_OBJECT
+    Q_DISABLE_COPY(Manager)
+
+public:
+    /*!
+       \brief
+       \param widgetFactory NavigationWidgetFactory
+       \param parent Parent object
+     */
+    virtual ~Manager();
+
+    //! Get an instance of Manager
+    static Manager *instance(QObject *parent = 0);
+
+    /*!
+       \brief Lazy data population for a \a QStandardItemModel
+       \param item Item with has to be checked
+     */
+    bool canFetchMore(QStandardItem *item) const;
+
+    /*!
+       \brief Lazy data population for a \a QStandardItemModel
+       \param item Item with has to be checked
+       \param skipRoot Skip root item (is needed for the manual update, call not from model)
+     */
+    void fetchMore(QStandardItem *item, bool skipRoot = false);
+
+signals:
+    /*!
+       \brief Internal Manager state is changed.
+       \param state true if Manager is enabled, false otherwise
+       \sa setState, state
+     */
+    void stateChanged(bool state);
+
+    /*!
+       \brief Signal about a tree data update (to tree view).
+       \param result Item with the current tree
+     */
+    void treeDataUpdate(QSharedPointer<QStandardItem> result);
+
+    /*!
+       \brief Signal that a request for sending tree view has to be handled by listeners (parser).
+       \sa onRequestTreeDataUpdate
+     */
+    void requestTreeDataUpdate();
+
+    /*!
+       \brief Signal that document is updated (and has to be reparsed)
+       \param doc Updated document
+       \sa onDocumentUpdated
+     */
+    void requestDocumentUpdated(CPlusPlus::Document::Ptr doc);
+
+    /*!
+       \brief Signal that parser has to reset its internal state to the current (from code manager).
+     */
+    void requestResetCurrentState();
+
+    /*!
+       \brief Request to clear a cache by parser.
+     */
+    void requestClearCache();
+
+    /*!
+       \brief Request to clear a full cache by parser.
+     */
+    void requestClearCacheAll();
+
+    /*!
+       \brief Request to set the flat mode (without subprojects)
+       \param flat True to enable flat mode, false to disable
+     */
+    void requestSetFlatMode(bool flat);
+
+public slots:
+    /*!
+       \brief Open text editor for file \a fileName on line \a lineNumber and column \a column.
+       \param fileName File which has to be open
+       \param lineNumber Line
+       \param column Column
+     */
+    void gotoLocation(const QString &fileName, int line = 0, int column = 0);
+
+    /*!
+       \brief Open text editor for any of location in the list (correctly)
+       \param locations Symbol locations
+       \sa Manager::gotoLocations
+     */
+    void gotoLocations(const QList<QVariant> &locations);
+
+    /*!
+       \brief If somebody wants to receive the latest tree info, if a parsing is enabled then
+              a signal \a requestTreeDataUpdate will be emitted.
+       \sa requestTreeDataUpdate, NavigationWidget::requestDataUpdate
+     */
+    void onRequestTreeDataUpdate();
+
+    /*!
+       \brief Switch to flat mode (without subprojects)
+       \param flat True to enable flat mode, false to disable
+     */
+    void setFlatMode(bool flat);
+
+protected slots:
+    /*!
+       \brief Widget factory creates a widget, handle this situation.
+       \sa setState, state
+     */
+    void onWidgetIsCreated();
+
+    /*!
+       \brief Widget visibility is changed
+       \param visibility Visibility (for just 1 navi pane widget, there might be a lot of them)
+       \sa setState, state
+     */
+    void onWidgetVisibilityIsChanged(bool visibility);
+
+    /*!
+       \brief Reacts to the state changed signal, e.g. request currect code snapshot if needed etc.
+       \param state Current Manager state
+       \sa setState, state, stateChanged
+     */
+    void onStateChanged(bool state);
+
+    /*!
+       \brief Project list is changed (navigation pane visibility might be needed to update).
+     */
+    void onProjectListChanged();
+
+    /*!
+       \brief This slot should called when the code model manager state is changed for \a doc.
+              It will emit a signal \a documentUpdated if
+       \param doc Updated document.
+       \sa documentUpdated
+     */
+    void onDocumentUpdated(CPlusPlus::Document::Ptr doc);
+
+    /*!
+       \brief Progress manager started a task. Do what is needed if it is a parse task.
+       \param type Task index, should be CppTools::Constants::TASK_INDEX for us
+       \sa CppTools::Constants::TASK_INDEX
+     */
+    void onTaskStarted(const QString &type);
+
+    /*!
+       \brief Progress manager finished all task with specified type.
+              Do what is needed if it is a parse task.
+       \param type Task index, should be CppTools::Constants::TASK_INDEX for us
+       \sa CppTools::Constants::TASK_INDEX
+     */
+    void onAllTasksFinished(const QString &type);
+
+    /*!
+       \brief New tree data update (has to be sent to a tree view).
+       \param result Item with the current tree
+     */
+    void onTreeDataUpdate(QSharedPointer<QStandardItem> result);
+
+protected:
+    //! Perform an initialization
+    void initialize();
+
+    /*!
+       \brief Get internal Manager state. If it is disabled, signals about parsing request has not
+              to be emitted at all, if enabled - do parsing in the background even if navi pane
+              is not visible.
+       \return true if Manager is enabled, false otherwise
+       \sa setState, stateChanged
+     */
+    inline bool state() const;
+
+    /*!
+       \brief Set internal Manager state.
+       \param true if Manager has to be enabled, false otherwise
+       \sa state, stateChanged
+     */
+    void setState(bool state);
+
+private:
+    explicit Manager(QObject *parent = 0);
+
+private:
+    //! private class data pointer
+    QScopedPointer<struct ManagerPrivate> d_ptr;
+};
+
+} // namespace Internal
+} // namespace ClassView
+
+#endif // CLASSVIEWMANAGER_H
diff --git a/src/plugins/classview/classviewnavigationwidget.cpp b/src/plugins/classview/classviewnavigationwidget.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8420284d818e9d2fc14dad433c7a59bbfc0f18fc
--- /dev/null
+++ b/src/plugins/classview/classviewnavigationwidget.cpp
@@ -0,0 +1,253 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Denis Mingulov.
+**
+** 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 "classviewnavigationwidget.h"
+#include "ui_classviewnavigationwidget.h"
+#include "classviewtreeitemmodel.h"
+#include "classviewmanager.h"
+#include "classviewsymbollocation.h"
+#include "classviewsymbolinformation.h"
+#include "classviewutils.h"
+#include "classviewconstants.h"
+
+#include <utils/qtcassert.h>
+
+#include <QtCore/QDebug>
+#include <QtCore/QPointer>
+
+enum { debug = false };
+
+namespace ClassView {
+namespace Internal {
+
+///////////////////////////////// NavigationWidgetPrivate //////////////////////////////////
+
+/*!
+   \struct NavigationWidgetPrivate
+   \brief Internal data structures / methods for NavigationWidget
+ */
+
+struct NavigationWidgetPrivate
+{
+    NavigationWidgetPrivate() : ui(0) {}
+
+    //! Ui generated by Designer
+    Ui::NavigationWidget *ui;
+
+    //! current tree model
+    QPointer<TreeItemModel> treeModel;
+
+    //! full projects mode
+    QPointer<QToolButton> fullProjectsModeButton;
+};
+
+///////////////////////////////// NavigationWidget //////////////////////////////////
+
+
+NavigationWidget::NavigationWidget(QWidget *parent) :
+    QWidget(parent),
+    d_ptr(new NavigationWidgetPrivate())
+{
+    d_ptr->ui = new Ui::NavigationWidget;
+    d_ptr->ui->setupUi(this);
+
+    // tree model
+    d_ptr->treeModel = new TreeItemModel(this);
+    d_ptr->ui->treeView->setModel(d_ptr->treeModel);
+
+    // connect signal/slots
+    // selected item
+    connect(d_ptr->ui->treeView, SIGNAL(activated(QModelIndex)), SLOT(onItemActivated(QModelIndex)));
+
+    // connections to the manager
+    Manager *manager = Manager::instance();
+
+    connect(this, SIGNAL(visibilityChanged(bool)),
+            manager, SLOT(onWidgetVisibilityIsChanged(bool)));
+
+    connect(this, SIGNAL(requestGotoLocation(QString,int,int)),
+            manager, SLOT(gotoLocation(QString,int,int)));
+
+    connect(this, SIGNAL(requestGotoLocations(QList<QVariant>)),
+            manager, SLOT(gotoLocations(QList<QVariant>)));
+
+    connect(manager, SIGNAL(treeDataUpdate(QSharedPointer<QStandardItem>)),
+            this, SLOT(onDataUpdate(QSharedPointer<QStandardItem>)));
+
+    connect(this, SIGNAL(requestTreeDataUpdate()),
+            manager, SLOT(onRequestTreeDataUpdate()));
+}
+
+NavigationWidget::~NavigationWidget()
+{
+    delete d_ptr->fullProjectsModeButton;
+    delete d_ptr->ui;
+}
+
+void NavigationWidget::hideEvent(QHideEvent *event)
+{
+    emit visibilityChanged(false);
+    QWidget::hideEvent(event);
+}
+
+void NavigationWidget::showEvent(QShowEvent *event)
+{
+    emit visibilityChanged(true);
+
+    // request to update to the current state - to be sure
+    emit requestTreeDataUpdate();
+
+    QWidget::showEvent(event);
+}
+
+QList<QToolButton *> NavigationWidget::createToolButtons()
+{
+    QList<QToolButton *> list;
+
+    // full projects mode
+    if (!d_ptr->fullProjectsModeButton) {
+        // create a button
+        d_ptr->fullProjectsModeButton = new QToolButton();
+        d_ptr->fullProjectsModeButton->setIcon(
+                QIcon(QLatin1String(":/classview/images/hierarchicalmode.png")));
+        d_ptr->fullProjectsModeButton->setCheckable(true);
+        d_ptr->fullProjectsModeButton->setToolTip(tr("Show subprojects"));
+
+        // by default - not a flat mode
+        setFlatMode(false);
+
+        // connections
+        connect(d_ptr->fullProjectsModeButton, SIGNAL(toggled(bool)),
+                this, SLOT(onFullProjectsModeToggled(bool)));
+    }
+
+    list << d_ptr->fullProjectsModeButton;
+
+    return list;
+}
+
+bool NavigationWidget::flatMode() const
+{
+    QTC_ASSERT(d_ptr->fullProjectsModeButton, return false);
+
+    // button is 'full projects mode' - so it has to be inverted
+    return !d_ptr->fullProjectsModeButton->isChecked();
+}
+
+void NavigationWidget::setFlatMode(bool flatMode)
+{
+    QTC_ASSERT(d_ptr->fullProjectsModeButton, return);
+
+    // button is 'full projects mode' - so it has to be inverted
+    d_ptr->fullProjectsModeButton->setChecked(!flatMode);
+}
+
+void NavigationWidget::onFullProjectsModeToggled(bool state)
+{
+    // button is 'full projects mode' - so it has to be inverted
+    Manager::instance()->setFlatMode(!state);
+}
+
+void NavigationWidget::onItemActivated(const QModelIndex &index)
+{
+    if (!index.isValid())
+        return;
+
+    QList<QVariant> list = d_ptr->treeModel->data(index, Constants::SymbolLocationsRole).toList();
+
+    emit requestGotoLocations(list);
+}
+
+void NavigationWidget::onDataUpdate(QSharedPointer<QStandardItem> result)
+{
+    if (result.isNull())
+        return;
+
+    // if this is 1st call
+    bool expandRootItems = false;
+    if (d_ptr->treeModel->invisibleRootItem()->rowCount() == 0)
+        expandRootItems = true;
+
+    QTime timer;
+    if (debug)
+        timer.start();
+    // update is received. root item must be updated - and received information
+    // might be just a root - if a lazy data population is enabled.
+    // so expanded items must be parsed and 'fetched'
+
+    fetchExpandedItems(result.data(), d_ptr->treeModel->invisibleRootItem());
+
+    d_ptr->treeModel->moveRootToTarget(result.data());
+
+    // expand top level projects
+    QModelIndex sessionIndex;
+
+    for (int i = 0; i < d_ptr->treeModel->rowCount(sessionIndex); ++i)
+        d_ptr->ui->treeView->expand(d_ptr->treeModel->index(i, 0, sessionIndex));
+
+    if (debug)
+        qDebug() << "Class View:" << QDateTime::currentDateTime().toString()
+            << "TreeView is updated in" << timer.elapsed() << "msecs";
+}
+
+void NavigationWidget::fetchExpandedItems(QStandardItem *item, const QStandardItem *target) const
+{
+    if (!item || !target)
+        return;
+
+    const QModelIndex &parent = d_ptr->treeModel->indexFromItem(target);
+    if (d_ptr->ui->treeView->isExpanded(parent))
+        Manager::instance()->fetchMore(item, true);
+
+    int itemIndex = 0;
+    int targetIndex = 0;
+    int itemRows = item->rowCount();
+    int targetRows = target->rowCount();
+
+    while (itemIndex < itemRows && targetIndex < targetRows) {
+        QStandardItem *itemChild = item->child(itemIndex);
+        const QStandardItem *targetChild = target->child(targetIndex);
+
+        const SymbolInformation &itemInf = Utils::symbolInformationFromItem(itemChild);
+        const SymbolInformation &targetInf = Utils::symbolInformationFromItem(targetChild);
+
+        if (itemInf < targetInf) {
+            ++itemIndex;
+        } else if (itemInf == targetInf) {
+            fetchExpandedItems(itemChild, targetChild);
+            ++itemIndex;
+            ++targetIndex;
+        } else {
+            ++targetIndex;
+        }
+    }
+}
+
+} // namespace Internal
+} // namespace ClassView
diff --git a/src/plugins/classview/classviewnavigationwidget.h b/src/plugins/classview/classviewnavigationwidget.h
new file mode 100644
index 0000000000000000000000000000000000000000..d4317634533725637bb74aa5ebc0c1ab2d1e73b7
--- /dev/null
+++ b/src/plugins/classview/classviewnavigationwidget.h
@@ -0,0 +1,148 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Denis Mingulov.
+**
+** 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 CLASSVIEWNAVIGATIONWIDGET_H
+#define CLASSVIEWNAVIGATIONWIDGET_H
+
+#include <QtGui/QWidget>
+#include <QtGui/QToolButton>
+#include <QtGui/QStandardItem>
+#include <QtCore/QScopedPointer>
+#include <QtCore/QSharedPointer>
+#include <QtCore/QList>
+
+QT_FORWARD_DECLARE_CLASS(QModelIndex)
+
+namespace ClassView {
+namespace Internal {
+
+/*!
+   \class NavigationWidget
+   \brief A widget for the class view tree
+ */
+
+class NavigationWidget : public QWidget
+{
+    Q_OBJECT
+    Q_DISABLE_COPY(NavigationWidget)
+
+public:
+    explicit NavigationWidget(QWidget *parent = 0);
+    ~NavigationWidget();
+
+    /*!
+       \brief Create QToolbuttons for Navigation Pane Widget
+       \return List with created QToolButtons
+       \sa NavigationWidgetFactory::createWidget
+     */
+    QList<QToolButton *> createToolButtons();
+
+    /*!
+       \brief Get flat mode state
+       \return Flat mode state
+     */
+    bool flatMode() const;
+
+    /*!
+       \brief Set flat mode state
+       \param flatMode Flat mode state
+     */
+    void setFlatMode(bool flatMode);
+
+signals:
+    /*!
+       \brief Widget visibility is changed
+       \param visibility true is plugin becames visible, false otherwise
+     */
+    void visibilityChanged(bool visibility);
+
+    /*!
+       \brief Signal to request to go to location
+       \param name File which has to be open
+       \param line Line
+       \param column Column
+       \sa Manager::gotoLocation
+     */
+    void requestGotoLocation(const QString &name, int line, int column);
+
+    /*!
+       \brief Signal to request to go to any of location in the list
+       \param locations Symbol locations
+       \sa Manager::gotoLocations
+     */
+    void requestGotoLocations(const QList<QVariant> &locations);
+
+    /*!
+       \brief Signal that the widget wants to receive the latest tree info
+       \sa Manager::onRequestTreeDataUpdate
+     */
+    void requestTreeDataUpdate();
+
+public slots:
+    /*!
+       \brief Item is activated in the tree view
+       \param index Item index
+     */
+    void onItemActivated(const QModelIndex &index);
+
+    /*!
+       \brief Receive a new data for the tree
+       \param Result - root item
+     */
+    void onDataUpdate(QSharedPointer<QStandardItem> result);
+
+    /*!
+       \brief Full projects' mode button has been toggled
+       \param state Full projects' mode
+     */
+    void onFullProjectsModeToggled(bool state);
+
+protected:
+    /*!
+       \brief Fetch data for expanded items - to be sure that content will exist
+       \param item
+       \param target
+     */
+    void fetchExpandedItems(QStandardItem *item, const QStandardItem *target) const;
+
+    //! implements QWidget::hideEvent
+    void hideEvent(QHideEvent *event);
+
+    //! implements QWidget::showEvent
+    void showEvent(QShowEvent *event);
+
+private:
+    //! Private class data pointer
+    QScopedPointer<struct NavigationWidgetPrivate> d_ptr;
+};
+
+} // namespace Internal
+} // namespace ClassView
+
+#endif // CLASSVIEWNAVIGATIONWIDGET_H
diff --git a/src/plugins/classview/classviewnavigationwidget.ui b/src/plugins/classview/classviewnavigationwidget.ui
new file mode 100644
index 0000000000000000000000000000000000000000..0b0bf55a50f053bc31b0178df6d4dc5acf9c3866
--- /dev/null
+++ b/src/plugins/classview/classviewnavigationwidget.ui
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ClassView::Internal::NavigationWidget</class>
+ <widget class="QWidget" name="ClassView::Internal::NavigationWidget">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>300</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <property name="spacing">
+    <number>0</number>
+   </property>
+   <property name="margin">
+    <number>0</number>
+   </property>
+   <item>
+    <widget class="Utils::NavigationTreeView" name="treeView">
+     <property name="editTriggers">
+      <set>QAbstractItemView::NoEditTriggers</set>
+     </property>
+     <property name="headerHidden">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>Utils::NavigationTreeView</class>
+   <extends>QTreeView</extends>
+   <header>utils/navigationtreeview.h</header>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/plugins/classview/classviewnavigationwidgetfactory.cpp b/src/plugins/classview/classviewnavigationwidgetfactory.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2209c7fdc37f77c5ad31002fb4d1da1b02326ea9
--- /dev/null
+++ b/src/plugins/classview/classviewnavigationwidgetfactory.cpp
@@ -0,0 +1,150 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Denis Mingulov.
+**
+** 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 "classviewnavigationwidgetfactory.h"
+#include "classviewnavigationwidget.h"
+#include "classviewconstants.h"
+
+#include <coreplugin/icore.h>
+#include <extensionsystem/pluginmanager.h>
+#include <utils/qtcassert.h>
+
+#include <QtGui/QKeySequence>
+#include <QtCore/QSettings>
+
+namespace ClassView {
+namespace Internal {
+
+///////////////////////////////// NavigationWidget //////////////////////////////////
+
+/*!
+   \struct NavigationWidgetFactoryPrivate
+   \brief Private class data for \a NavigationWidgetFactory
+   \sa NavigationWidgetFactory
+ */
+struct NavigationWidgetFactoryPrivate
+{
+    //! constructor
+    NavigationWidgetFactoryPrivate() : naviPaneEnabled(false) {}
+
+    //! NavigationWidgetFactory instance
+    static NavigationWidgetFactory *instance;
+
+    //! Navigation pane visibility
+    bool naviPaneEnabled;
+};
+
+// static variable initialization
+NavigationWidgetFactory *NavigationWidgetFactoryPrivate::instance = 0;
+
+///////////////////////////////// NavigationWidgetFactory //////////////////////////////////
+
+NavigationWidgetFactory::NavigationWidgetFactory()
+    : d_ptr(new NavigationWidgetFactoryPrivate())
+{
+}
+
+NavigationWidgetFactory::~NavigationWidgetFactory()
+{
+    NavigationWidgetFactoryPrivate::instance = 0;
+}
+
+NavigationWidgetFactory *NavigationWidgetFactory::instance()
+{
+    if (!NavigationWidgetFactoryPrivate::instance)
+        NavigationWidgetFactoryPrivate::instance = new NavigationWidgetFactory();
+    return NavigationWidgetFactoryPrivate::instance;
+}
+
+QString NavigationWidgetFactory::displayName() const
+{
+    return tr("Class View");
+}
+
+QString NavigationWidgetFactory::id() const
+{
+    return QLatin1String(Constants::CLASSVIEWNAVIGATION_ID);
+}
+
+QKeySequence NavigationWidgetFactory::activationSequence() const
+{
+    return QKeySequence();
+}
+
+Core::NavigationView NavigationWidgetFactory::createWidget()
+{
+    Core::NavigationView navigationView;
+    NavigationWidget *widget = new NavigationWidget();
+    navigationView.widget = widget;
+    navigationView.dockToolBarWidgets = widget->createToolButtons();
+    emit widgetIsCreated();
+    return navigationView;
+}
+
+QString NavigationWidgetFactory::settingsPrefix(int position) const
+{
+    QChar sep('/');
+    QString group = QLatin1String(Constants::CLASSVIEW_SETTINGS_GROUP) + sep;
+    group += QLatin1String(Constants::CLASSVIEW_SETTINGS_TREEWIDGET_PREFIX)
+             + QString::number(position) + sep;
+    return  group;
+}
+
+void NavigationWidgetFactory::saveSettings(int position, QWidget *widget)
+{
+    NavigationWidget *pw = qobject_cast<NavigationWidget *>(widget);
+    QTC_ASSERT(pw, return);
+
+    QSettings *settings = Core::ICore::instance()->settings();
+    QTC_ASSERT(settings, return);
+
+    // .beginGroup is not used - to prevent simultaneous access
+    QString group = settingsPrefix(position);
+
+    // save settings
+    settings->setValue(group + Constants::CLASSVIEW_SETTINGS_FLATMODE, pw->flatMode());
+}
+
+void NavigationWidgetFactory::restoreSettings(int position, QWidget *widget)
+{
+    NavigationWidget *pw = qobject_cast<NavigationWidget *>(widget);
+    QTC_ASSERT(pw, return);
+
+    QSettings *settings = Core::ICore::instance()->settings();
+    QTC_ASSERT(settings, return);
+
+    // .beginGroup is not used - to prevent simultaneous access
+    QString group = settingsPrefix(position);
+
+    // load settings
+    pw->setFlatMode(settings->value(group + Constants::CLASSVIEW_SETTINGS_FLATMODE, false).toBool());
+}
+
+} // namespace Internal
+} // namespace ClassView
diff --git a/src/plugins/classview/classviewnavigationwidgetfactory.h b/src/plugins/classview/classviewnavigationwidgetfactory.h
new file mode 100644
index 0000000000000000000000000000000000000000..619a97d36a49eb77ebf51714761f31957b6bbc94
--- /dev/null
+++ b/src/plugins/classview/classviewnavigationwidgetfactory.h
@@ -0,0 +1,107 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Denis Mingulov.
+**
+** 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 CLASSVIEWNAVIGATIONWIDGETFACTORY_H
+#define CLASSVIEWNAVIGATIONWIDGETFACTORY_H
+
+#include <coreplugin/inavigationwidgetfactory.h>
+
+#include <QtCore/QScopedPointer>
+
+namespace ClassView {
+namespace Internal {
+
+/*!
+   \class NavigationWidgetFactory
+   \brief INavigationWidgetFactory implementation for Class View
+
+   INavigationWidgetFactory implementation for Class View. Singleton instance.
+   Supports \a setState publc slot to add/remove factory to \a ExtensionSystem::PluginManager.
+   Also supports some additional signals, \a widgetIsCreated and \a stateChanged.
+ */
+
+class NavigationWidgetFactory : public Core::INavigationWidgetFactory
+{
+    Q_OBJECT
+    Q_DISABLE_COPY(NavigationWidgetFactory)
+
+public:
+    //! destructor
+    virtual ~NavigationWidgetFactory();
+
+    //! get an instance
+    static NavigationWidgetFactory *instance();
+
+    // Core::INavigationWidgetFactory
+    //! \implements Core::INavigationWidgetFactory::displayName
+    QString displayName() const;
+
+    //! \implements Core::INavigationWidgetFactory::id
+    QString id() const;
+
+    //! \implements Core::INavigationWidgetFactory::activationSequence
+    QKeySequence activationSequence() const;
+
+    //! \implements Core::INavigationWidgetFactory::createWidget
+    Core::NavigationView createWidget();
+
+    //! \implements Core::INavigationWidgetFactory::saveSettings
+    void saveSettings(int position, QWidget *widget);
+
+    //! \implements Core::INavigationWidgetFactory::restoreSettings
+    void restoreSettings(int position, QWidget *widget);
+
+    // own functionality
+
+signals:
+    /*!
+       \brief Signal which informs that the widget factory creates a widget.
+     */
+    void widgetIsCreated();
+
+private:
+    //! Constructor
+    NavigationWidgetFactory();
+
+    /*!
+       \brief Get a settings prefix for the specified position
+       \param position Position
+       \return Settings prefix
+     */
+    QString settingsPrefix(int position) const;
+
+private:
+    //! private class data pointer
+    QScopedPointer<struct NavigationWidgetFactoryPrivate> d_ptr;
+};
+
+} // namespace Internal
+} // namespace ClassView
+
+#endif // CLASSVIEWNAVIGATIONWIDGETFACTORY_H
diff --git a/src/plugins/classview/classviewparser.cpp b/src/plugins/classview/classviewparser.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..32c55040699276300d92cb73bb271e525acd7239
--- /dev/null
+++ b/src/plugins/classview/classviewparser.cpp
@@ -0,0 +1,688 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Denis Mingulov.
+**
+** 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 "classviewparser.h"
+#include "classviewconstants.h"
+#include "classviewutils.h"
+
+// cplusplus shared library. the same folder (cplusplus)
+#include <Symbol.h>
+#include <Symbols.h>
+#include <Scope.h>
+#include <Name.h>
+
+// other
+#include <cplusplus/Overview.h>
+#include <cplusplus/Icons.h>
+#include <cpptools/cppmodelmanagerinterface.h>
+#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/session.h>
+#include <projectexplorer/project.h>
+#include <projectexplorer/projectnodes.h>
+#include <coreplugin/ifile.h>
+#include <utils/qtcassert.h>
+
+#include <QtGui/QStandardItem>
+#include <QtCore/QDebug>
+#include <QtCore/QHash>
+#include <QtCore/QSet>
+#include <QtCore/QTimer>
+#include <QtCore/QReadWriteLock>
+#include <QtCore/QReadLocker>
+#include <QtCore/QWriteLocker>
+
+enum { debug = false };
+
+namespace ClassView {
+namespace Internal {
+
+// ----------------------------- ParserPrivate ---------------------------------
+
+/*!
+   \struct ParserPrivate
+   \brief Private class data for \a Parser
+   \sa Parser
+ */
+struct ParserPrivate
+{
+    //! Constructor
+    ParserPrivate() : flatMode(false) {}
+
+    //! Get document from documentList
+    CPlusPlus::Document::Ptr document(const QString &fileName) const;
+
+    CPlusPlus::Overview overview;
+
+    //! timer
+    QPointer<QTimer> timer;
+
+    // documents
+    //! Documents read write lock
+    QReadWriteLock docLocker;
+
+    //! Current document list
+    QHash<QString, CPlusPlus::Document::Ptr> documentList;
+
+    //! Parsed documents' revision - to speed up computations
+    QHash<QString, unsigned> cachedDocTreesRevision;
+
+    //! Parsed documents - to speed up computations
+    QHash<QString, ParserTreeItem::ConstPtr> cachedDocTrees;
+
+    // project trees
+    //! Projects read write lock
+    QReadWriteLock prjLocker;
+
+    //! Parsed projects' revision - to speed up computations
+    QHash<QString, unsigned> cachedPrjTreesRevision;
+
+    //! Merged trees for projects. Not const - projects might be substracted/added
+    QHash<QString, ParserTreeItem::Ptr> cachedPrjTrees;
+
+    //! Cached file lists for projects (non-flat mode)
+    QHash<QString, QStringList> cachedPrjFileLists;
+
+    // other
+    //! List for files which has to be parsed
+    QSet<QString> fileList;
+
+    //! Root item read write lock
+    QReadWriteLock rootItemLocker;
+
+    //! Parsed root item
+    ParserTreeItem::ConstPtr rootItem;
+
+    //! Flat mode
+    bool flatMode;
+};
+
+CPlusPlus::Document::Ptr ParserPrivate::document(const QString &fileName) const
+{
+    if (!documentList.contains(fileName))
+        return CPlusPlus::Document::Ptr();
+    return documentList[fileName];
+}
+
+// ----------------------------- Parser ---------------------------------
+
+Parser::Parser(QObject *parent)
+    : QObject(parent),
+    d_ptr(new ParserPrivate())
+{
+    d_ptr->timer = new QTimer(this);
+    d_ptr->timer->setSingleShot(true);
+
+    // connect signal/slots
+    // internal data reset
+    connect(this, SIGNAL(resetDataDone()), SLOT(onResetDataDone()), Qt::QueuedConnection);
+
+    // timer for emitting changes
+    connect(d_ptr->timer, SIGNAL(timeout()), SLOT(requestCurrentState()), Qt::QueuedConnection);
+}
+
+Parser::~Parser()
+{
+}
+
+bool Parser::canFetchMore(QStandardItem *item) const
+{
+    ParserTreeItem::ConstPtr ptr = findItemByRoot(item);
+    if (ptr.isNull())
+        return false;
+    return ptr->canFetchMore(item);
+}
+
+void Parser::fetchMore(QStandardItem *item, bool skipRoot) const
+{
+    ParserTreeItem::ConstPtr ptr = findItemByRoot(item, skipRoot);
+    if (ptr.isNull())
+        return;
+    ptr->fetchMore(item);
+}
+
+void Parser::setFlatMode(bool flatMode)
+{
+    if (flatMode == d_ptr->flatMode)
+        return;
+
+    // change internal
+    d_ptr->flatMode = flatMode;
+
+    // regenerate and resend current tree
+    emitCurrentTree();
+}
+
+ParserTreeItem::ConstPtr Parser::findItemByRoot(const QStandardItem *item, bool skipRoot) const
+{
+    if (!item)
+        return ParserTreeItem::ConstPtr();
+
+    // go item by item to the root
+    QList<const QStandardItem *> uiList;
+    const QStandardItem *cur = item;
+    while(cur) {
+        uiList.append(cur);
+        cur = cur->parent();
+    }
+
+    if (skipRoot && uiList.count() > 0)
+        uiList.removeLast();
+
+    QReadLocker locker(&d_ptr->rootItemLocker);
+
+    // using internal root - search correct item
+    ParserTreeItem::ConstPtr internal = d_ptr->rootItem;
+
+    while(uiList.count() > 0) {
+        cur = uiList.last();
+        uiList.removeLast();
+        const SymbolInformation &inf = Utils::symbolInformationFromItem(cur);
+        internal = internal->child(inf);
+        if (internal.isNull())
+            break;
+    }
+
+    return internal;
+}
+
+ParserTreeItem::ConstPtr Parser::parse()
+{
+    QTime time;
+    if (debug)
+        time.start();
+
+    ParserTreeItem::Ptr rootItem(new ParserTreeItem());
+
+    // check all projects
+    QList<ProjectExplorer::Project *> projects = getProjectList();
+    foreach(const ProjectExplorer::Project *prj, projects) {
+        if (!prj)
+            continue;
+
+        ParserTreeItem::Ptr item;
+        if (!d_ptr->flatMode)
+            item = ParserTreeItem::Ptr(new ParserTreeItem());
+
+        QString prjName(prj->displayName());
+        QString prjType(prjName);
+        if (prj->file())
+            prjType = prj->file()->fileName();
+        SymbolInformation inf(prjName, prjType);
+
+        QStringList projectList = addProjectNode(item, prj->rootProjectNode());
+
+        if (d_ptr->flatMode) {
+            // use prj path (prjType) as a project id
+//            addProject(item, prj->files(ProjectExplorer::Project::ExcludeGeneratedFiles), prjType);
+            //! \todo return back, works too long
+            ParserTreeItem::Ptr flatItem = createFlatTree(projectList);
+            item.swap(flatItem);
+        }
+        item->setIcon(prj->rootProjectNode()->icon());
+        rootItem->appendChild(item, inf);
+    }
+
+    if (debug)
+        qDebug() << "Class View:" << QDateTime::currentDateTime().toString()
+            << "Parsed in " << time.elapsed() << "msecs.";
+
+    return rootItem;
+}
+
+void Parser::addProject(const ParserTreeItem::Ptr &item, const QStringList &fileList,
+                                 const QString &projectId)
+{
+    // recalculate cache tree if needed
+    ParserTreeItem::Ptr prj(getCachedOrParseProjectTree(fileList, projectId));
+    if (item.isNull())
+        return;
+
+    // if there is an item - copy project tree to that item
+    item->copy(prj);
+}
+
+void Parser::addSymbol(const ParserTreeItem::Ptr &item, const CPlusPlus::Symbol *symbol)
+{
+    if (item.isNull() || !symbol)
+        return;
+
+    // easy solution - lets add any scoped symbol and
+    // any symbol which does not contain :: in the name
+
+//    if (symbol->isDeclaration())
+//        return;
+
+    //! \todo collect statistics and reorder to optimize
+    if (symbol->isForwardClassDeclaration()
+        || symbol->isExtern()
+        || symbol->isFriend()
+        || symbol->isGenerated()
+        || symbol->isUsingNamespaceDirective()
+        || symbol->isUsingDeclaration()
+        )
+        return;
+
+    // skip static local functions
+//    if ((!symbol->scope() || symbol->scope()->owner()->isClass())
+//        && symbol->isStatic() && symbol->isFunction())
+//        return;
+
+
+    const CPlusPlus::Name *symbolName = symbol->name();
+    if (symbolName && symbolName->isQualifiedNameId())
+        return;
+
+    QString name = d_ptr->overview.prettyName(symbol->name()).trimmed();
+    QString type = d_ptr->overview.prettyType(symbol->type()).trimmed();
+    int iconType = CPlusPlus::Icons::iconTypeForSymbol(symbol);
+
+    SymbolInformation information(name, type, iconType);
+
+    ParserTreeItem::Ptr itemAdd;
+
+    // If next line will be removed, 5% speed up for the initial parsing.
+    // But there might be a problem for some files ???
+    // Better to improve qHash timing
+    itemAdd = item->child(information);
+
+    if (itemAdd.isNull())
+        itemAdd = ParserTreeItem::Ptr(new ParserTreeItem());
+
+    // locations are 1-based in Symbol, start with 0 for the editor
+    SymbolLocation location(symbol->fileName(), symbol->line(), symbol->column() - 1);
+    itemAdd->addSymbolLocation(location);
+
+    // prevent showing a content of the functions
+    if (!symbol->isFunction()) {
+        const CPlusPlus::ScopedSymbol *scopedSymbol = symbol->asScopedSymbol();
+        if (scopedSymbol) {
+            CPlusPlus::Scope *scope = scopedSymbol->members();
+            if (scope) {
+                CPlusPlus::Scope::iterator cur = scope->firstSymbol();
+                while (cur != scope->lastSymbol()) {
+                    const CPlusPlus::Symbol *curSymbol = *cur;
+                    ++cur;
+                    if (!curSymbol)
+                        continue;
+
+                    //                if (!symbol->isClass() && curSymbol->isStatic() && curSymbol->isFunction())
+                    //                        return;
+
+                    addSymbol(itemAdd, curSymbol);
+                }
+            }
+        }
+    }
+
+    bool appendChild = true;
+
+    // if item is empty and has not to be added
+    if (symbol->isNamespace() && itemAdd->childCount() == 0)
+        appendChild = false;
+
+    if (appendChild)
+        item->appendChild(itemAdd, information);
+}
+
+ParserTreeItem::Ptr Parser::createFlatTree(const QStringList &projectList)
+{
+    QReadLocker locker(&d_ptr->prjLocker);
+
+    ParserTreeItem::Ptr item(new ParserTreeItem());
+    foreach(const QString &project, projectList) {
+        if (!d_ptr->cachedPrjTrees.contains(project))
+            continue;
+        ParserTreeItem::ConstPtr list = d_ptr->cachedPrjTrees[project];
+        item->add(list);
+    }
+    return item;
+}
+
+ParserTreeItem::Ptr Parser::getParseProjectTree(const QStringList &fileList,
+                                                const QString &projectId)
+{
+    //! \todo Way to optimize - for documentUpdate - use old cached project and subtract
+    //! changed files only (old edition), and add curent editions
+    ParserTreeItem::Ptr item(new ParserTreeItem());
+    unsigned revision = 0;
+    foreach(const QString &file, fileList) {
+        // ? locker for document?..
+        const CPlusPlus::Document::Ptr &doc = d_ptr->document(file);
+        if (doc.isNull())
+            continue;
+
+        revision += doc->revision();
+
+        ParserTreeItem::ConstPtr list = getCachedOrParseDocumentTree(doc);
+        if (list.isNull())
+            continue;
+
+        // add list to out document
+        item->add(list);
+    }
+
+    // update the cache
+    if (!projectId.isEmpty()) {
+        QWriteLocker locker(&d_ptr->prjLocker);
+
+        d_ptr->cachedPrjTrees[projectId] = item;
+        d_ptr->cachedPrjTreesRevision[projectId] = revision;
+    }
+    return item;
+}
+
+ParserTreeItem::Ptr Parser::getCachedOrParseProjectTree(const QStringList &fileList,
+                                                const QString &projectId)
+{
+    d_ptr->prjLocker.lockForRead();
+
+    // calculate current revision
+    if (!projectId.isEmpty() && d_ptr->cachedPrjTrees.contains(projectId)) {
+        // calculate project's revision
+        unsigned revision = 0;
+        foreach(const QString &file, fileList) {
+            const CPlusPlus::Document::Ptr &doc = d_ptr->document(file);
+            if (doc.isNull())
+                continue;
+            revision += doc->revision();
+        }
+
+        // if even revision is the same, return cached project
+        if (revision == d_ptr->cachedPrjTreesRevision[projectId]) {
+            d_ptr->prjLocker.unlock();
+            return d_ptr->cachedPrjTrees[projectId];
+        }
+    }
+
+    d_ptr->prjLocker.unlock();
+    return getParseProjectTree(fileList, projectId);
+}
+
+ParserTreeItem::ConstPtr Parser::getParseDocumentTree(const CPlusPlus::Document::Ptr &doc)
+{
+    if (doc.isNull())
+        return ParserTreeItem::ConstPtr();
+
+    const QString &fileName = doc->fileName();
+    if (!d_ptr->fileList.contains(fileName))
+        return ParserTreeItem::ConstPtr();
+
+    ParserTreeItem::Ptr itemPtr(new ParserTreeItem());
+
+    unsigned total = doc->globalSymbolCount();
+    for (unsigned i = 0; i < total; i++)
+        addSymbol(itemPtr, doc->globalSymbolAt(i));
+
+    QWriteLocker locker(&d_ptr->docLocker);
+
+    d_ptr->cachedDocTrees[fileName] = itemPtr;
+    d_ptr->cachedDocTreesRevision[fileName] = doc->revision();
+    d_ptr->documentList[fileName] = doc;
+
+    return itemPtr;
+}
+
+ParserTreeItem::ConstPtr Parser::getCachedOrParseDocumentTree(const CPlusPlus::Document::Ptr &doc)
+{
+    if (doc.isNull())
+        return ParserTreeItem::ConstPtr();
+
+    const QString &fileName = doc->fileName();
+    d_ptr->docLocker.lockForRead();
+    if (d_ptr->cachedDocTrees.contains(fileName)
+        && d_ptr->cachedDocTreesRevision.contains(fileName)
+        && d_ptr->cachedDocTreesRevision[fileName] == doc->revision()) {
+        d_ptr->docLocker.unlock();
+        return d_ptr->cachedDocTrees[fileName];
+    } else {
+        d_ptr->docLocker.unlock();
+        return getParseDocumentTree(doc);
+    }
+}
+
+void Parser::parseDocument(const CPlusPlus::Document::Ptr &doc)
+{
+    if (doc.isNull())
+        return;
+
+    const QString &name = doc->fileName();
+
+    // if it is external file (not in any of our projects)
+    if (!d_ptr->fileList.contains(name))
+        return;
+
+    getParseDocumentTree(doc);
+
+    QTC_ASSERT(d_ptr->timer, return);
+
+    if (!d_ptr->timer->isActive())
+        d_ptr->timer->start(Constants::CLASSVIEW_EDITINGTREEUPDATE_DELAY);
+    return;
+}
+
+void Parser::clearCacheAll()
+{
+    d_ptr->docLocker.lockForWrite();
+
+    d_ptr->cachedDocTrees.clear();
+    d_ptr->cachedDocTreesRevision.clear();
+    d_ptr->documentList.clear();
+
+    d_ptr->docLocker.unlock();
+
+    clearCache();
+}
+
+void Parser::clearCache()
+{
+    QWriteLocker locker(&d_ptr->prjLocker);
+
+    // remove cached trees
+    d_ptr->cachedPrjFileLists.clear();
+
+    //! \todo where better to clear project's trees?
+    //! When file is add/removed from a particular project?..
+    d_ptr->cachedPrjTrees.clear();
+    d_ptr->cachedPrjTreesRevision.clear();
+}
+
+void Parser::setFileList(const QStringList &fileList)
+{
+    d_ptr->fileList.clear();
+    d_ptr->fileList = QSet<QString>::fromList(fileList);
+}
+
+void Parser::removeFiles(const QStringList &fileList)
+{
+    if (fileList.count() == 0)
+        return;
+
+    QWriteLocker lockerPrj(&d_ptr->prjLocker);
+    QWriteLocker lockerDoc(&d_ptr->docLocker);
+    foreach(const QString &name, fileList) {
+        d_ptr->fileList.remove(name);
+        d_ptr->cachedDocTrees.remove(name);
+        d_ptr->cachedDocTreesRevision.remove(name);
+        d_ptr->documentList.remove(name);
+        d_ptr->cachedPrjTrees.remove(name);
+        d_ptr->cachedPrjFileLists.clear();
+    }
+
+    emit filesAreRemoved();
+}
+
+void Parser::resetData(const CPlusPlus::Snapshot &snapshot)
+{
+    // clear internal cache
+    clearCache();
+
+    d_ptr->docLocker.lockForWrite();
+
+    // copy snapshot's documents
+    CPlusPlus::Snapshot::const_iterator cur = snapshot.begin();
+    CPlusPlus::Snapshot::const_iterator end = snapshot.end();
+    for(; cur != end; cur++)
+        d_ptr->documentList[cur.key()] = cur.value();
+
+    d_ptr->docLocker.unlock();
+
+    // recalculate file list
+    QStringList fileList;
+
+    // check all projects
+    QList<ProjectExplorer::Project *> projects = getProjectList();
+    foreach(const ProjectExplorer::Project *prj, projects) {
+        if (prj)
+            fileList += prj->files(ProjectExplorer::Project::ExcludeGeneratedFiles);
+    }
+    setFileList(fileList);
+
+    emit resetDataDone();
+}
+
+void Parser::resetDataToCurrentState()
+{
+    // get latest data
+    CppTools::CppModelManagerInterface *codeModel = CppTools::CppModelManagerInterface::instance();
+    if (codeModel)
+        resetData(codeModel->snapshot());
+}
+
+void Parser::onResetDataDone()
+{
+    // internal data is resetted, update a tree and send it back
+    emitCurrentTree();
+}
+
+void Parser::requestCurrentState()
+{
+    emitCurrentTree();
+}
+
+void Parser::emitCurrentTree()
+{
+    // stop timer if it is active right now
+    d_ptr->timer->stop();
+
+    d_ptr->rootItemLocker.lockForWrite();
+    d_ptr->rootItem = parse();
+    d_ptr->rootItemLocker.unlock();
+
+    // convert
+    QSharedPointer<QStandardItem> std(new QStandardItem());
+
+    d_ptr->rootItem->convertTo(std.data());
+
+    emit treeDataUpdate(std);
+}
+
+QStringList Parser::projectNodeFileList(const ProjectExplorer::FolderNode *node) const
+{
+    QStringList list;
+    if (!node)
+        return list;
+
+    QList<ProjectExplorer::FileNode *> fileNodes = node->fileNodes();
+    QList<ProjectExplorer::FolderNode *> subFolderNodes = node->subFolderNodes();
+
+    foreach(const ProjectExplorer::FileNode *file, fileNodes) {
+        if (file->isGenerated())
+            continue;
+
+        list << file->path();
+    }
+
+    foreach(const ProjectExplorer::FolderNode *folder, subFolderNodes) {
+        if (folder->nodeType() != ProjectExplorer::FolderNodeType)
+            continue;
+        list << projectNodeFileList(folder);
+    }
+
+    return list;
+}
+
+QStringList Parser::addProjectNode(const ParserTreeItem::Ptr &item,
+                                     const ProjectExplorer::ProjectNode *node)
+{
+    QStringList projectList;
+    if (!node)
+        return projectList;
+
+    const QString &nodePath = node->path();
+
+    // our own files
+    QStringList fileList;
+
+    // try to improve parsing speed by internal cache
+    if (d_ptr->cachedPrjFileLists.contains(nodePath)) {
+        fileList = d_ptr->cachedPrjFileLists[nodePath];
+    } else {
+        fileList = projectNodeFileList(node);
+        d_ptr->cachedPrjFileLists[nodePath] = fileList;
+    }
+    if (fileList.count() > 0) {
+        addProject(item, fileList, node->path());
+        projectList << node->path();
+    }
+
+    // subnodes
+    QList<ProjectExplorer::ProjectNode *> projectNodes = node->subProjectNodes();
+
+    foreach(const ProjectExplorer::ProjectNode *project, projectNodes) {
+        ParserTreeItem::Ptr itemPrj(new ParserTreeItem());
+        SymbolInformation information(project->displayName(), project->path());
+
+        projectList += addProjectNode(itemPrj, project);
+
+        itemPrj->setIcon(project->icon());
+
+        // append child if item is not null and there is at least 1 child
+        if (!item.isNull() && itemPrj->childCount() > 0)
+            item->appendChild(itemPrj, information);
+    }
+
+    return projectList;
+}
+
+QList<ProjectExplorer::Project *> Parser::getProjectList() const
+{
+    QList<ProjectExplorer::Project *> list;
+
+    // check all projects
+    ProjectExplorer::SessionManager *sessionManager
+            = ProjectExplorer::ProjectExplorerPlugin::instance()->session();
+    QTC_ASSERT(sessionManager, return list);
+
+    list = sessionManager->projects();
+
+    return list;
+}
+
+} // namespace Internal
+} // namespace ClassView
diff --git a/src/plugins/classview/classviewparser.h b/src/plugins/classview/classviewparser.h
new file mode 100644
index 0000000000000000000000000000000000000000..fb0eb651eb359725fff2600d132d5b642372bed6
--- /dev/null
+++ b/src/plugins/classview/classviewparser.h
@@ -0,0 +1,265 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Denis Mingulov.
+**
+** 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 CLASSVIEWPARSER_H
+#define CLASSVIEWPARSER_H
+
+#include <QtCore/QObject>
+
+#include "classviewparsertreeitem.h"
+
+#include <QtCore/QList>
+#include <QtGui/QStandardItem>
+#include <QtCore/QScopedPointer>
+#include <QtCore/QSharedPointer>
+
+#include <CPlusPlusForwardDeclarations.h>
+#include <cplusplus/CppDocument.h>
+#include <cpptools/cppmodelmanagerinterface.h>
+
+// might be changed to forward declaration - is not done to be less dependent
+#include <projectexplorer/projectnodes.h>
+#include <projectexplorer/project.h>
+
+namespace ClassView {
+namespace Internal {
+
+/*!
+   \class Parser
+   \brief Parse cpp information. Multithreading is supported.
+ */
+
+class Parser : public QObject
+{
+    Q_OBJECT
+
+public:
+    /*!
+       \brief Constructor
+     */
+    explicit Parser(QObject *parent = 0);
+    ~Parser();
+
+    /*!
+       \brief Lazy data population for a \a QStandardItemModel
+       \param item Item which has to be checked
+     */
+    bool canFetchMore(QStandardItem *item) const;
+
+    /*!
+       \brief Lazy data population for a \a QStandardItemModel
+       \param item Item which will be populated (if needed)
+       \param skipRoot Skip root item
+     */
+    void fetchMore(QStandardItem *item, bool skipRoot = false) const;
+
+signals:
+    //! File list is changed
+    void filesAreRemoved();
+
+    /*!
+       \brief Signal about a tree data update
+     */
+    void treeDataUpdate(QSharedPointer<QStandardItem> result);
+
+    /*!
+       \brief Signal that internal data
+       \sa resetData, resetDataToCurrentState
+     */
+    void resetDataDone();
+
+public slots:
+    /*!
+       \brief Request to clear full internal stored data.
+     */
+    void clearCacheAll();
+
+    /*!
+       \brief Request to clear internal stored data, it has to be regenerated on the next request.
+     */
+    void clearCache();
+
+    /*!
+       \brief Request to emit a signal with the current tree state
+     */
+    void requestCurrentState();
+
+    /*!
+       \brief Set file list for the parsing, files outside of this list will not be in any tree.
+       \param fileList Files which must be allowed for the parsing
+     */
+    void setFileList(const QStringList &fileList);
+
+    /*!
+       \brief Remove some files from the file list for the parsing.
+       \param fileList Files which must be removed from the parsing
+     */
+    void removeFiles(const QStringList &fileList);
+
+    /*!
+       \brief Fully reset internal state
+       \param snapshot Code parser snapshot
+     */
+    void resetData(const CPlusPlus::Snapshot &snapshot);
+
+    /*!
+       \brief Fully reset internal state - to the current state
+       \sa resetData
+     */
+    void resetDataToCurrentState();
+
+    /*!
+       \brief Parse document if it is in the project files and add a tree to the internal storage
+       \param doc Document which has to be parsed
+     */
+    void parseDocument(const CPlusPlus::Document::Ptr &doc);
+
+    /*!
+       \brief Switch to flat mode (without subprojects)
+       \param flat True to enable flat mode, false to disable
+     */
+    void setFlatMode(bool flat);
+
+protected slots:
+    /*!
+       \brief Internal data is changed, regenerate the tree
+       \sa resetDataDone
+     */
+    void onResetDataDone();
+
+protected:
+    /*!
+       \brief Parse one particular project and add result to the tree item
+       \param item Item where parsed project has to be stored
+       \param fileList Files
+       \param projectId Project id, is needed for prj cache
+     */
+    void addProject(const ParserTreeItem::Ptr &item, const QStringList &fileList,
+                    const QString &projectId = QString());
+
+    /*!
+       \brief Parse one particular symbol and add result to the tree item (as a parent)
+       \param item Item where parsed symbol has to be stored
+       \param symbol Symbol which has to be used as a source
+     */
+    void addSymbol(const ParserTreeItem::Ptr &item, const CPlusPlus::Symbol *symbol);
+
+    /*!
+       \brief Parse document if it is in the project files and add a tree to the internal storage.
+              Update internal cached tree for this document.
+       \param doc Document which has to be parsed
+       \return A tree
+       \sa parseDocument
+     */
+    ParserTreeItem::ConstPtr getParseDocumentTree(const CPlusPlus::Document::Ptr &doc);
+
+    /*!
+       \brief Get from the cache or parse document if it is in the project files
+              and add a tree to the internal storage
+       \param doc Document which has to be parsed
+       \return A tree
+       \sa parseDocument
+     */
+    ParserTreeItem::ConstPtr getCachedOrParseDocumentTree(const CPlusPlus::Document::Ptr &doc);
+
+    /*!
+       \brief Parse project and add a tree to the internal storage.
+              Update internal cached tree for this project.
+       \param fileList Documents which has to be added to the project
+       \param projectId Project id
+       \return A tree
+     */
+    ParserTreeItem::Ptr getParseProjectTree(const QStringList &fileList, const QString &projectId);
+
+    /*!
+       \brief Get from the cache (if valid) or parse project and add a tree to the internal storage.
+              Update internal cached tree for this project.
+       \param fileList Documents which has to be added to the project
+       \param projectId Project id
+       \return A tree
+     */
+    ParserTreeItem::Ptr getCachedOrParseProjectTree(const QStringList &fileList,
+                                                    const QString &projectId);
+
+    /*!
+       \brief Send a current tree to listeners
+     */
+    void emitCurrentTree();
+
+    /*!
+       \brief Parse the class and produce a new tree
+       \sa addProject
+     */
+    ParserTreeItem::ConstPtr parse();
+
+    /*!
+       \brief Find internal node for the specified UI item
+       \param item Item which has to be found
+       \param skipRoot Skip root item
+       \return Found internal node
+     */
+    ParserTreeItem::ConstPtr findItemByRoot(const QStandardItem *item, bool skipRoot = false) const;
+
+    /*!
+       \brief Generate projects like Project Explorer
+       \param item Item
+       \param node Root node
+       \return List of projects which were added to the item
+     */
+    QStringList addProjectNode(const ParserTreeItem::Ptr &item,
+                               const ProjectExplorer::ProjectNode *node);
+
+    /*!
+       \brief Generate project node file list
+       \param node Root node
+     */
+    QStringList projectNodeFileList(const ProjectExplorer::FolderNode *node) const;
+
+    /*!
+       \brief Get the current project list
+       \return Project list
+     */
+    QList<ProjectExplorer::Project *> getProjectList() const;
+
+    /*!
+       \brief Create flat tree from different projects
+       \param projectList List of projects
+       \return Flat tree
+     */
+    ParserTreeItem::Ptr createFlatTree(const QStringList &projectList);
+
+private:
+    //! Private class data pointer
+    QScopedPointer<struct ParserPrivate> d_ptr;
+};
+
+} // namespace Internal
+} // namespace ClassView
+
+#endif // CLASSVIEWPARSER_H
diff --git a/src/plugins/classview/classviewparsertreeitem.cpp b/src/plugins/classview/classviewparsertreeitem.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..16e1a66573318367561fae628b30dcf043610df6
--- /dev/null
+++ b/src/plugins/classview/classviewparsertreeitem.cpp
@@ -0,0 +1,373 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Denis Mingulov.
+**
+** 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 "classviewparsertreeitem.h"
+#include "classviewsymbollocation.h"
+#include "classviewsymbolinformation.h"
+#include "classviewconstants.h"
+#include "classviewutils.h"
+
+#include <QtCore/QHash>
+#include <QtCore/QPair>
+#include <QtGui/QIcon>
+#include <QtGui/QStandardItem>
+#include <QtCore/QMutex>
+
+#include <QtCore/QDebug>
+
+enum { debug = true };
+
+namespace ClassView {
+namespace Internal {
+
+///////////////////////////////// ParserTreeItemPrivate //////////////////////////////////
+
+/*!
+   \struct ParserTreeItemPrivate
+   \brief Private class data for \a ParserTreeItem
+   \sa ParserTreeItem
+ */
+struct ParserTreeItemPrivate
+{
+    //! symbol locations
+    QSet<SymbolLocation> symbolLocations;
+
+    //! symbol informations
+    QHash<SymbolInformation, ParserTreeItem::Ptr> symbolInformations;
+
+    //! An icon
+    QIcon icon;
+};
+
+///////////////////////////////// ParserTreeItem //////////////////////////////////
+
+ParserTreeItem::ParserTreeItem() :
+    d_ptr(new ParserTreeItemPrivate())
+{
+}
+
+ParserTreeItem::~ParserTreeItem()
+{
+}
+
+ParserTreeItem &ParserTreeItem::operator=(const ParserTreeItem &other)
+{
+    d_ptr->symbolLocations = other.d_ptr->symbolLocations;
+    d_ptr->icon = other.d_ptr->icon;
+    d_ptr->symbolInformations.clear();
+    return *this;
+}
+
+void ParserTreeItem::copy(const ParserTreeItem::ConstPtr &from)
+{
+    if (from.isNull())
+        return;
+
+    d_ptr->symbolLocations = from->d_ptr->symbolLocations;
+    d_ptr->icon = from->d_ptr->icon;
+    d_ptr->symbolInformations = from->d_ptr->symbolInformations;
+}
+
+void ParserTreeItem::copyTree(const ParserTreeItem::ConstPtr &target)
+{
+    if (target.isNull())
+        return;
+
+    // copy content
+    d_ptr->symbolLocations = target->d_ptr->symbolLocations;
+    d_ptr->icon = target->d_ptr->icon;
+    d_ptr->symbolInformations.clear();
+
+    // reserve memory
+//    int amount = qMin(100 , target->d_ptr->symbolInformations.count() * 2);
+//    d_ptr->symbolInformations.reserve(amount);
+
+    // every child
+    QHash<SymbolInformation, ParserTreeItem::Ptr>::const_iterator cur =
+            target->d_ptr->symbolInformations.constBegin();
+    QHash<SymbolInformation, ParserTreeItem::Ptr>::const_iterator end =
+            target->d_ptr->symbolInformations.constEnd();
+
+    for(; cur != end; cur++) {
+        ParserTreeItem::Ptr item(new ParserTreeItem());
+        item->copyTree(cur.value());
+        appendChild(item, cur.key());
+    }
+}
+
+void ParserTreeItem::addSymbolLocation(const SymbolLocation &location)
+{
+    d_ptr->symbolLocations.insert(location);
+}
+
+void ParserTreeItem::addSymbolLocation(const QSet<SymbolLocation> &locations)
+{
+    d_ptr->symbolLocations.unite(locations);
+}
+
+void ParserTreeItem::removeSymbolLocation(const SymbolLocation &location)
+{
+    d_ptr->symbolLocations.remove(location);
+}
+
+void ParserTreeItem::removeSymbolLocations(const QSet<SymbolLocation> &locations)
+{
+    d_ptr->symbolLocations.subtract(locations);
+}
+
+QSet<SymbolLocation> ParserTreeItem::symbolLocations() const
+{
+    return d_ptr->symbolLocations;
+}
+
+void ParserTreeItem::appendChild(const ParserTreeItem::Ptr &item, const SymbolInformation &inf)
+{
+    // removeChild must be used to remove an item
+    if (item.isNull())
+        return;
+
+    d_ptr->symbolInformations[inf] = item;
+}
+
+void ParserTreeItem::removeChild(const SymbolInformation &inf)
+{
+    d_ptr->symbolInformations.remove(inf);
+}
+
+ParserTreeItem::Ptr ParserTreeItem::child(const SymbolInformation &inf) const
+{
+    if (!d_ptr->symbolInformations.contains(inf))
+        return ParserTreeItem::Ptr();
+    return d_ptr->symbolInformations[inf];
+}
+
+int ParserTreeItem::childCount() const
+{
+    return d_ptr->symbolInformations.count();
+}
+
+QIcon ParserTreeItem::icon() const
+{
+    return d_ptr->icon;
+}
+
+void ParserTreeItem::setIcon(const QIcon &icon)
+{
+    d_ptr->icon = icon;
+}
+
+void ParserTreeItem::add(const ParserTreeItem::ConstPtr &target)
+{
+    if (target.isNull())
+        return;
+
+    // add locations
+    d_ptr->symbolLocations = d_ptr->symbolLocations.unite(target->d_ptr->symbolLocations);
+
+    // add childs
+    // every target child
+    QHash<SymbolInformation, ParserTreeItem::Ptr>::const_iterator cur =
+            target->d_ptr->symbolInformations.constBegin();
+    QHash<SymbolInformation, ParserTreeItem::Ptr>::const_iterator end =
+            target->d_ptr->symbolInformations.constEnd();
+    while(cur != end) {
+        const SymbolInformation &inf = cur.key();
+        const ParserTreeItem::Ptr &targetChild = cur.value();
+        if (d_ptr->symbolInformations.contains(inf)) {
+            // this item has the same child node
+            const ParserTreeItem::Ptr &child = d_ptr->symbolInformations[inf];
+            if (!child.isNull()) {
+                child->add(targetChild);
+            } else {
+                ParserTreeItem::Ptr add(new ParserTreeItem());
+                add->copyTree(targetChild);
+                d_ptr->symbolInformations[inf] = add;
+            }
+        } else {
+            ParserTreeItem::Ptr add(new ParserTreeItem());
+            add->copyTree(targetChild);
+            d_ptr->symbolInformations[inf] = add;
+        }
+        // next item
+        ++cur;
+    }
+}
+
+void ParserTreeItem::subtract(const ParserTreeItem::ConstPtr &target)
+{
+    if (target.isNull())
+        return;
+
+    // every target child
+    QHash<SymbolInformation, ParserTreeItem::Ptr>::const_iterator cur =
+            target->d_ptr->symbolInformations.constBegin();
+    QHash<SymbolInformation, ParserTreeItem::Ptr>::const_iterator end =
+            target->d_ptr->symbolInformations.constEnd();
+    while(cur != end) {
+        const SymbolInformation &inf = cur.key();
+        if (d_ptr->symbolInformations.contains(inf)) {
+            // this item has the same child node
+            if (!d_ptr->symbolInformations[inf].isNull())
+                d_ptr->symbolInformations[inf]->subtract(cur.value());
+            if (d_ptr->symbolInformations[inf].isNull()
+                || d_ptr->symbolInformations[inf]->childCount() == 0)
+                d_ptr->symbolInformations.remove(inf);
+        }
+        // next item
+        ++cur;
+    }
+}
+
+void ParserTreeItem::convertTo(QStandardItem *item, bool recursive) const
+{
+    if (!item)
+        return;
+
+    QMap<SymbolInformation, ParserTreeItem::Ptr> map;
+
+    // convert to map - to sort it
+    QHash<SymbolInformation, ParserTreeItem::Ptr>::const_iterator curHash =
+            d_ptr->symbolInformations.constBegin();
+    QHash<SymbolInformation, ParserTreeItem::Ptr>::const_iterator endHash =
+            d_ptr->symbolInformations.constEnd();
+    while(curHash != endHash) {
+        map.insert(curHash.key(), curHash.value());
+        ++curHash;
+    }
+
+    // add to item
+    QMap<SymbolInformation, ParserTreeItem::Ptr>::const_iterator cur = map.constBegin();
+    QMap<SymbolInformation, ParserTreeItem::Ptr>::const_iterator end = map.constEnd();
+    while(cur != end) {
+        const SymbolInformation &inf = cur.key();
+        ParserTreeItem::Ptr ptr = cur.value();
+
+        QStandardItem *add = new QStandardItem();
+        Utils::setSymbolInformationToItem(inf, add);
+        if (!ptr.isNull()) {
+            // icon
+            add->setIcon(ptr->icon());
+
+            // locations
+            add->setData(Utils::locationsToRole(ptr->symbolLocations()),
+                         Constants::SymbolLocationsRole);
+
+            if (recursive)
+                cur.value()->convertTo(add, false);
+        }
+        item->appendRow(add);
+        ++cur;
+    }
+}
+
+bool ParserTreeItem::canFetchMore(QStandardItem *item) const
+{
+    if (!item)
+        return false;
+
+    // incremental data population - so we have to check children
+    // count subchildren of both - current QStandardItem and our internal
+
+    // for the current UI item
+    int storedChildren = 0;
+    for (int i = 0; i < item->rowCount(); i++) {
+        QStandardItem *child = item->child(i);
+        if (!child)
+            continue;
+        storedChildren += child->rowCount();
+    }
+    // children for the internal state
+    int internalChildren = 0;
+    QHash<SymbolInformation, ParserTreeItem::Ptr>::const_iterator curHash =
+            d_ptr->symbolInformations.constBegin();
+    QHash<SymbolInformation, ParserTreeItem::Ptr>::const_iterator endHash =
+            d_ptr->symbolInformations.constEnd();
+    while(curHash != endHash) {
+        const ParserTreeItem::Ptr &child = curHash.value();
+        if (!child.isNull()) {
+            internalChildren += child->childCount();
+            // if there is already more items than stored, then can be stopped right now
+            if (internalChildren > storedChildren)
+                break;
+        }
+        ++curHash;
+    }
+
+    if(storedChildren < internalChildren)
+        return true;
+
+    return false;
+}
+
+void ParserTreeItem::fetchMore(QStandardItem *item) const
+{
+    if (!item)
+        return;
+
+    for (int i = 0; i < item->rowCount(); i++) {
+        QStandardItem *child = item->child(i);
+        if (!child)
+            continue;
+
+        const SymbolInformation &childInf = Utils::symbolInformationFromItem(child);
+
+        if (d_ptr->symbolInformations.contains(childInf)) {
+            const ParserTreeItem::Ptr &childPtr = d_ptr->symbolInformations[childInf];
+            if (childPtr.isNull())
+                continue;
+
+            // create a standard
+            QScopedPointer<QStandardItem> state(new QStandardItem());
+            childPtr->convertTo(state.data(), false);
+
+            Utils::fetchItemToTarget(child, state.data());
+        }
+    }
+}
+
+void ParserTreeItem::debugDump(int ident) const
+{
+    QHash<SymbolInformation, ParserTreeItem::Ptr>::const_iterator curHash =
+            d_ptr->symbolInformations.constBegin();
+    QHash<SymbolInformation, ParserTreeItem::Ptr>::const_iterator endHash =
+            d_ptr->symbolInformations.constEnd();
+    while(curHash != endHash) {
+        const SymbolInformation &inf = curHash.key();
+        qDebug() << QString(2*ident, QChar(' ')) << inf.iconType() << inf.name() << inf.type()
+                << curHash.value().isNull();
+        if (!curHash.value().isNull())
+            curHash.value()->debugDump(ident + 1);
+
+        ++curHash;
+    }
+}
+
+} // namespace Internal
+} // namespace ClassView
+
diff --git a/src/plugins/classview/classviewparsertreeitem.h b/src/plugins/classview/classviewparsertreeitem.h
new file mode 100644
index 0000000000000000000000000000000000000000..054aee26f733d6046c1246a55a0e14ca46f6e2aa
--- /dev/null
+++ b/src/plugins/classview/classviewparsertreeitem.h
@@ -0,0 +1,190 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Denis Mingulov.
+**
+** 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 CLASSVIEWPARSERTREEITEM_H
+#define CLASSVIEWPARSERTREEITEM_H
+
+#include "classviewsymbollocation.h"
+#include "classviewsymbolinformation.h"
+
+#include <QtCore/QSharedPointer>
+#include <QtCore/QScopedPointer>
+
+QT_FORWARD_DECLARE_CLASS(QStandardItem)
+
+namespace ClassView {
+namespace Internal {
+
+/*!
+   \class ParserTreeItem
+   \brief Item for the internal Class View Tree
+
+   Item for Class View Tree.
+   Not virtual - to speed up its work.
+ */
+
+class ParserTreeItem
+{
+public:
+    typedef QSharedPointer<ParserTreeItem> Ptr;
+    typedef QSharedPointer<const ParserTreeItem> ConstPtr;
+
+public:
+    ParserTreeItem();
+    ~ParserTreeItem();
+
+    /*!
+       \brief Copy content of \a from item with children to this one.
+       \param from 'From' item
+     */
+    void copyTree(const ParserTreeItem::ConstPtr &from);
+
+    /*!
+       \brief Copy of \a from item to this one.
+       \param from 'From' item
+     */
+    void copy(const ParserTreeItem::ConstPtr &from);
+
+    /*!
+       \brief Add information about symbol location
+       \param location Filled \a SymbolLocation struct with a correct information
+       \sa SymbolLocation, removeSymbolLocation, symbolLocations
+     */
+    void addSymbolLocation(const SymbolLocation &location);
+
+    /*!
+       \brief Add information about symbol locations
+       \param locations Filled \a SymbolLocation struct with a correct information
+       \sa SymbolLocation, removeSymbolLocation, symbolLocations
+     */
+    void addSymbolLocation(const QSet<SymbolLocation> &locations);
+
+    /*!
+       \brief Remove information about symbol location
+       \param location Filled \a SymbolLocation struct with a correct information
+       \sa SymbolLocation, addSymbolLocation, symbolLocations
+     */
+    void removeSymbolLocation(const SymbolLocation &location);
+
+    /*!
+       \brief Remove information about symbol locations
+       \param locations Filled \a SymbolLocation struct with a correct information
+       \sa SymbolLocation, addSymbolLocation, symbolLocations
+     */
+    void removeSymbolLocations(const QSet<SymbolLocation> &locations);
+
+    /*!
+       \brief Get information about symbol positions
+       \sa SymbolLocation, addSymbolLocation, removeSymbolLocation
+     */
+    QSet<SymbolLocation> symbolLocations() const;
+
+    /*!
+       \brief Append child
+       \param item Child item
+       \param inf Symbol information
+     */
+    void appendChild(const ParserTreeItem::Ptr &item, const SymbolInformation &inf);
+
+    /*!
+       \brief Remove child
+       \param inf SymbolInformation which has to be removed
+     */
+    void removeChild(const SymbolInformation &inf);
+
+    /*!
+       \brief Get an item
+       \param inf Symbol information about needed child
+       \return Found child
+     */
+    ParserTreeItem::Ptr child(const SymbolInformation &inf) const;
+
+    /*!
+       \brief How many children
+       \return Amount of chilren
+     */
+    int childCount() const;
+
+    /*!
+       \brief Append this item to the \a QStandardIten item
+       \param item QStandardItem
+       \param recursive Do it recursively for the tree items or not (might be needed for
+                        the lazy data population
+
+     */
+    void convertTo(QStandardItem *item, bool recursive = true) const;
+
+    // additional properties
+    //! Assigned icon
+    QIcon icon() const;
+
+    //! Set an icon for this tree node
+    void setIcon(const QIcon &icon);
+
+    /*!
+       \brief Add an internal state with \a target.
+       \param target Item which contains the correct current state
+     */
+    void add(const ParserTreeItem::ConstPtr &target);
+
+    /*!
+       \brief Subtract an internal state with \a target.
+       \param target Item which contains the subtrahend
+     */
+    void subtract(const ParserTreeItem::ConstPtr &target);
+
+    /*!
+       \brief Lazy data population for a \a QStandardItemModel
+       \param item Item which has to be checked
+     */
+    bool canFetchMore(QStandardItem *item) const;
+
+    /*!
+       \brief Lazy data population for a \a QStandardItemModel
+       \param item Item which will be populated (if needed)
+     */
+    void fetchMore(QStandardItem *item) const;
+
+    /*!
+       \brief Debug dump
+     */
+    void debugDump(int ident = 0) const;
+
+protected:
+    ParserTreeItem &operator=(const ParserTreeItem &other);
+
+private:
+    //! Private class data pointer
+    QScopedPointer<struct ParserTreeItemPrivate> d_ptr;
+};
+
+} // namespace Internal
+} // namespace ClassView
+
+#endif // CLASSVIEWPARSERTREEITEM_H
diff --git a/src/plugins/classview/classviewplugin.cpp b/src/plugins/classview/classviewplugin.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..fc69b461ccf36ccf3829a86880cfe080fa36ac8c
--- /dev/null
+++ b/src/plugins/classview/classviewplugin.cpp
@@ -0,0 +1,89 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Denis Mingulov.
+**
+** 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 "classviewplugin.h"
+#include "classviewmanager.h"
+#include "classviewnavigationwidgetfactory.h"
+
+#include <QtCore/QtPlugin>
+
+namespace ClassView {
+namespace Internal {
+
+///////////////////////////////// PluginPrivate //////////////////////////////////
+/*!
+   \struct PluginPrivate
+   \brief Private class data for \a Plugin
+   \sa Plugin
+ */
+struct PluginPrivate
+{
+    //! Pointer to Navi Widget Factory
+    QPointer<NavigationWidgetFactory> navigationWidgetFactory;
+
+    //! Pointer to Manager
+    QPointer<Manager> manager;
+};
+
+///////////////////////////////// Plugin //////////////////////////////////
+
+Plugin::Plugin()
+    : d_ptr(new PluginPrivate())
+{
+}
+
+Plugin::~Plugin()
+{
+}
+
+bool Plugin::initialize(const QStringList &arguments, QString *errorMessage)
+{
+    Q_UNUSED(arguments)
+    Q_UNUSED(errorMessage)
+
+    // create a navigation widget factory
+    d_ptr->navigationWidgetFactory = NavigationWidgetFactory::instance();
+
+    // add to ExtensionSystem
+    addAutoReleasedObject(d_ptr->navigationWidgetFactory);
+
+    // create manager
+    d_ptr->manager = Manager::instance(this);
+
+    return true;
+}
+
+void Plugin::extensionsInitialized()
+{
+}
+
+} // namespace Internal
+} // namespace ClassView
+
+Q_EXPORT_PLUGIN(ClassView::Internal::Plugin)
diff --git a/src/plugins/classview/classviewplugin.h b/src/plugins/classview/classviewplugin.h
new file mode 100644
index 0000000000000000000000000000000000000000..b2094597db2fb7459030b0c2083b79cb7598ba9b
--- /dev/null
+++ b/src/plugins/classview/classviewplugin.h
@@ -0,0 +1,71 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Denis Mingulov.
+**
+** 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 CLASSVIEWPLUGIN_H
+#define CLASSVIEWPLUGIN_H
+
+#include <extensionsystem/iplugin.h>
+
+#include <QtCore/QScopedPointer>
+
+namespace ClassView {
+namespace Internal {
+
+/*!
+   \class Plugin
+   \brief Base class for Class View plugin (class/namespaces in the navigation pane)
+ */
+
+class Plugin : public ExtensionSystem::IPlugin
+{
+    Q_OBJECT
+    Q_DISABLE_COPY(Plugin)
+
+public:
+    //! Constructor
+    Plugin();
+
+    //! Destructor
+    virtual ~Plugin();
+
+    //! \implements ExtensionSystem::IPlugin::initialize
+    bool initialize(const QStringList &arguments, QString *error_message = 0);
+
+    //! \implements ExtensionSystem::IPlugin::extensionsInitialized
+    void extensionsInitialized();
+
+private:
+    //! private class data pointer
+    QScopedPointer<struct PluginPrivate> d_ptr;
+};
+
+} // namespace Internal
+} // namespace ClassView
+
+#endif // CLASSVIEWPLUGIN_H
diff --git a/src/plugins/classview/classviewsymbolinformation.cpp b/src/plugins/classview/classviewsymbolinformation.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..209e809c4a5e81122f20ae2beeb4f54f93170072
--- /dev/null
+++ b/src/plugins/classview/classviewsymbolinformation.cpp
@@ -0,0 +1,81 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Denis Mingulov.
+**
+** 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 "classviewsymbolinformation.h"
+#include "classviewutils.h"
+
+#include <QtCore/QPair>
+#include <QtCore/QHash>
+
+namespace ClassView {
+namespace Internal {
+
+SymbolInformation::SymbolInformation() :
+    m_iconType(INT_MIN),
+    m_hash(0)
+{
+}
+
+SymbolInformation::SymbolInformation(const QString &valueName, const QString &valueType,
+                                     int valueIconType) :
+    m_iconType(valueIconType),
+    m_name(valueName),
+    m_type(valueType)
+{
+    // calculate hash
+    m_hash = qHash(qMakePair(m_iconType, qMakePair(m_name, m_type)));
+}
+
+int SymbolInformation::iconTypeSortOrder() const
+{
+    return Utils::iconTypeSortOrder(m_iconType);
+}
+
+bool SymbolInformation::operator<(const SymbolInformation &other) const
+{
+    // comparsion is not a critical for speed
+    if (iconType() != other.iconType()) {
+        int l = iconTypeSortOrder();
+        int r = other.iconTypeSortOrder();
+        if (l < r)
+            return true;
+        if (l > r)
+            return false;
+    }
+
+    int cmp = name().compare(other.name(), Qt::CaseInsensitive);
+    if (cmp < 0)
+        return true;
+    if (cmp > 0)
+        return false;
+    return type().compare(other.type(), Qt::CaseInsensitive) < 0;
+}
+
+} // namespace Internal
+} // namespace ClassView
diff --git a/src/plugins/classview/classviewsymbolinformation.h b/src/plugins/classview/classviewsymbolinformation.h
new file mode 100644
index 0000000000000000000000000000000000000000..988fb0f0b7396ea091058abf96dda9e0766c925a
--- /dev/null
+++ b/src/plugins/classview/classviewsymbolinformation.h
@@ -0,0 +1,89 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Denis Mingulov.
+**
+** 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 CLASSVIEWSYMBOLINFORMATION_H
+#define CLASSVIEWSYMBOLINFORMATION_H
+
+#include <QtCore/QMetaType>
+#include <QtCore/QString>
+
+namespace ClassView {
+namespace Internal {
+
+/*!
+   \class SymbolInformation
+   \brief
+ */
+
+class SymbolInformation
+{
+public:
+    SymbolInformation();
+    SymbolInformation(const QString &name, const QString &type, int iconType = INT_MIN);
+
+    bool operator<(const SymbolInformation &other) const;
+
+    inline const QString &name() const { return m_name; }
+    inline const QString &type() const { return m_type; }
+    inline int iconType() const { return m_iconType; }
+    inline uint hash() const { return m_hash; }
+
+    /*!
+       \brief Get an icon type sort order. Not pre-calculated - is needed for converting
+              to Standard Item only.
+       \return Sort order number.
+     */
+    int iconTypeSortOrder() const;
+
+private:
+    int m_iconType; //!< icon type
+    QString m_name; //!< symbol name (e.g. SymbolInformation)
+    QString m_type; //!< symbol type (e.g. (int char))
+
+    uint m_hash;    //!< precalculated hash value - to speed up qHash
+};
+
+} // namespace Internal
+} // namespace ClassView
+
+inline bool operator==(const ClassView::Internal::SymbolInformation &a,
+                       const ClassView::Internal::SymbolInformation &b)
+{
+    return a.iconType() == b.iconType() && a.name() == b.name() && a.type() == b.type();
+}
+
+//! qHash overload for QHash/QSet
+inline uint qHash(const ClassView::Internal::SymbolInformation &information)
+{
+    return information.hash();
+}
+
+Q_DECLARE_METATYPE(ClassView::Internal::SymbolInformation)
+
+#endif // CLASSVIEWSYMBOLINFORMATION_H
diff --git a/src/plugins/classview/classviewsymbollocation.cpp b/src/plugins/classview/classviewsymbollocation.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d245b06e9343c608dd1de141e36726f9f4661a40
--- /dev/null
+++ b/src/plugins/classview/classviewsymbollocation.cpp
@@ -0,0 +1,57 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Denis Mingulov.
+**
+** 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 "classviewsymbollocation.h"
+#include <QtCore/QPair>
+#include <QtCore/QHash>
+
+namespace ClassView {
+namespace Internal {
+
+SymbolLocation::SymbolLocation() :
+    m_line(0),
+    m_column(0),
+    m_hash(0)
+{
+}
+
+SymbolLocation::SymbolLocation(QString file, int lineNumber, int columnNumber) :
+    m_fileName(file),
+    m_line(lineNumber),
+    m_column(columnNumber)
+{
+    if (m_column < 0)
+        m_column = 0;
+
+    // pre-computate hash value
+    m_hash = qHash(qMakePair(m_fileName, qMakePair(m_line, m_column)));
+}
+
+} // namespace Internal
+} // namespace ClassView
diff --git a/src/plugins/classview/classviewsymbollocation.h b/src/plugins/classview/classviewsymbollocation.h
new file mode 100644
index 0000000000000000000000000000000000000000..b886a2470f6bb614742a72a7e9a180861f31792a
--- /dev/null
+++ b/src/plugins/classview/classviewsymbollocation.h
@@ -0,0 +1,82 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Denis Mingulov.
+**
+** 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 CLASSVIEWSYMBOLLOCATION_H
+#define CLASSVIEWSYMBOLLOCATION_H
+
+#include <QtCore/QMetaType>
+#include <QtCore/QString>
+
+namespace ClassView {
+namespace Internal {
+
+/*!
+   \class SymbolLocation
+   \brief Special struct to store information about symbol location (to find which exactly location
+   has to be open when the user clicks on any tree item. It might be used in QSet/QHash.
+ */
+class SymbolLocation
+{
+public:
+    //! Default constructor
+    SymbolLocation();
+
+    //! Constructor
+    SymbolLocation(QString file, int lineNumber = 0, int columnNumber = 0);
+
+    inline const QString &fileName() const { return m_fileName; }
+    inline int line() const { return m_line; }
+    inline int column() const { return m_column; }
+    inline int hash() const { return m_hash; }
+
+private:
+    QString m_fileName; //!< file name
+    int m_line;         //!< line number
+    int m_column;       //!< column
+    int m_hash;         //!< precalculated hash value for the object, to speed up qHash
+};
+
+} // namespace Internal
+} // namespace ClassView
+
+inline bool operator==(const ClassView::Internal::SymbolLocation &a,
+                       const ClassView::Internal::SymbolLocation &b)
+{
+    return a.line() == b.line() && a.column() == b.column() && a.fileName() == b.fileName();
+}
+
+//! qHash overload for QHash/QSet
+inline uint qHash(const ClassView::Internal::SymbolLocation &location)
+{
+    return location.hash();
+}
+
+Q_DECLARE_METATYPE(ClassView::Internal::SymbolLocation)
+
+#endif // CLASSVIEWSYMBOLLOCATION_H
diff --git a/src/plugins/classview/classviewtreeitemmodel.cpp b/src/plugins/classview/classviewtreeitemmodel.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5ec992cdb26e5df58f3826c484d01f86e2064707
--- /dev/null
+++ b/src/plugins/classview/classviewtreeitemmodel.cpp
@@ -0,0 +1,129 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Denis Mingulov.
+**
+** 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 "classviewtreeitemmodel.h"
+#include "classviewconstants.h"
+#include "classviewmanager.h"
+#include "classviewutils.h"
+
+#include <cplusplus/Icons.h>
+
+namespace ClassView {
+namespace Internal {
+
+///////////////////////////////// TreeItemModelPrivate //////////////////////////////////
+
+/*!
+   \struct TreeItemModelPrivate
+   \brief Private class data for \a TreeItemModel
+   \sa TreeItemModel
+ */
+struct TreeItemModelPrivate
+{
+    //! icon provider
+    CPlusPlus::Icons icons;
+};
+
+///////////////////////////////// TreeItemModel //////////////////////////////////
+
+TreeItemModel::TreeItemModel(QObject *parent)
+    : QStandardItemModel(parent),
+    d_ptr(new TreeItemModelPrivate())
+{
+}
+
+TreeItemModel::~TreeItemModel()
+{
+}
+
+QVariant TreeItemModel::data(const QModelIndex &index, int role) const
+{
+    if (!index.isValid())
+        return QStandardItemModel::data(index, role);
+
+    switch (role) {
+    case Qt::DecorationRole: {
+            QVariant iconType = data(index, Constants::IconTypeRole);
+            if (iconType.isValid()) {
+                bool ok = false;
+                int type = iconType.toInt(&ok);
+                if (ok && type >= 0)
+                    return d_ptr->icons.iconForType(static_cast<CPlusPlus::Icons::IconType>(type));
+            }
+        }
+        break;
+    case Qt::ToolTipRole:
+    case Qt::DisplayRole: {
+            const SymbolInformation &inf = Utils::symbolInformationFromItem(itemFromIndex(index));
+
+            if (inf.name() == inf.type() || inf.iconType() < 0)
+                return inf.name();
+
+            QString name(inf.name());
+
+            if (!inf.type().isEmpty())
+                name += QLatin1String(" ") + inf.type();
+
+            return name;
+        }
+        break;
+    default:
+        break;
+    }
+
+    return QStandardItemModel::data(index, role);
+}
+
+bool TreeItemModel::canFetchMore(const QModelIndex &parent) const
+{
+    if (!parent.isValid())
+        return false;
+
+    return Manager::instance()->canFetchMore(itemFromIndex(parent));
+}
+
+void TreeItemModel::fetchMore(const QModelIndex &parent)
+{
+    if (!parent.isValid())
+        return;
+
+    return Manager::instance()->fetchMore(itemFromIndex(parent));
+}
+
+void TreeItemModel::moveRootToTarget(const QStandardItem *target)
+{
+    emit layoutAboutToBeChanged();
+
+    Utils::moveItemToTarget(invisibleRootItem(), target);
+
+    emit layoutChanged();
+}
+
+} // namespace Internal
+} // namespace ClassView
diff --git a/src/plugins/classview/classviewtreeitemmodel.h b/src/plugins/classview/classviewtreeitemmodel.h
new file mode 100644
index 0000000000000000000000000000000000000000..45bcf99796fed63644e76896761f1e2c1edd05b9
--- /dev/null
+++ b/src/plugins/classview/classviewtreeitemmodel.h
@@ -0,0 +1,77 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Denis Mingulov.
+**
+** 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 CLASSVIEWTREEITEMMODEL_H
+#define CLASSVIEWTREEITEMMODEL_H
+
+#include <QtGui/QStandardItemModel>
+#include <QtCore/QModelIndex>
+#include <QtCore/QScopedPointer>
+#include <QtCore/QSet>
+
+namespace ClassView {
+namespace Internal {
+
+/*!
+   \class TreeItemModel
+   \brief Model for Class View Tree
+ */
+
+class TreeItemModel : public QStandardItemModel
+{
+    Q_OBJECT
+
+public:
+    explicit TreeItemModel(QObject *parent=0);
+    virtual ~TreeItemModel();
+
+    /*!
+       \brief move root item to the target
+       \param target Target item
+     */
+    void moveRootToTarget(const QStandardItem *target);
+
+    //! \implements QStandardItemModel::data
+    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+
+    //! \implements QStandardItemModel::canFetchMore
+    virtual bool canFetchMore(const QModelIndex &parent) const;
+
+    //! \implements QStandardItemModel::fetchMore
+    virtual void fetchMore(const QModelIndex &parent);
+
+private:
+    //! private class data pointer
+    QScopedPointer<struct TreeItemModelPrivate> d_ptr;
+};
+
+} // namespace Internal
+} // namespace ClassView
+
+#endif // CLASSVIEWTREEMODEL_H
diff --git a/src/plugins/classview/classviewutils.cpp b/src/plugins/classview/classviewutils.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..244a55e9035f5737edc1e0eb5dd04c274f2a6545
--- /dev/null
+++ b/src/plugins/classview/classviewutils.cpp
@@ -0,0 +1,232 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Denis Mingulov.
+**
+** 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 "classviewutils.h"
+#include "classviewconstants.h"
+#include "classviewsymbolinformation.h"
+
+// needed for the correct sorting order
+#include <cplusplus/Icons.h>
+
+#include <QtGui/QStandardItem>
+#include <QtCore/QDebug>
+
+namespace ClassView {
+namespace Constants {
+
+//! Default icon sort order
+const int IconSortOrder[] = {
+    CPlusPlus::Icons::NamespaceIconType,
+    CPlusPlus::Icons::EnumIconType,
+    CPlusPlus::Icons::ClassIconType,
+    CPlusPlus::Icons::FuncPublicIconType,
+    CPlusPlus::Icons::FuncProtectedIconType,
+    CPlusPlus::Icons::FuncPrivateIconType,
+    CPlusPlus::Icons::SignalIconType,
+    CPlusPlus::Icons::SlotPublicIconType,
+    CPlusPlus::Icons::SlotProtectedIconType,
+    CPlusPlus::Icons::SlotPrivateIconType,
+    CPlusPlus::Icons::VarPublicIconType,
+    CPlusPlus::Icons::VarProtectedIconType,
+    CPlusPlus::Icons::VarPrivateIconType,
+    CPlusPlus::Icons::EnumeratorIconType,
+    CPlusPlus::Icons::KeywordIconType,
+    CPlusPlus::Icons::MacroIconType,
+    CPlusPlus::Icons::UnknownIconType
+};
+
+} // namespace Constants
+
+namespace Internal {
+
+Utils::Utils()
+{
+}
+
+QList<QVariant> Utils::locationsToRole(const QSet<SymbolLocation> &locations)
+{
+    QList<QVariant> locationsVar;
+    foreach(const SymbolLocation &loc, locations)
+        locationsVar.append(QVariant::fromValue(loc));
+
+    return locationsVar;
+}
+
+QSet<SymbolLocation> Utils::roleToLocations(const QList<QVariant> &locationsVar)
+{
+    QSet<SymbolLocation> locations;
+    foreach(const QVariant &loc, locationsVar) {
+        if (loc.canConvert<SymbolLocation>()) {
+            locations.insert(loc.value<SymbolLocation>());
+        }
+    }
+
+    return locations;
+}
+
+int Utils::iconTypeSortOrder(int icon)
+{
+    static QHash<int, int> sortOrder;
+
+    // initialization
+    if (sortOrder.count() == 0) {
+        for (unsigned i = 0 ;
+             i < sizeof(Constants::IconSortOrder) / sizeof(Constants::IconSortOrder[0]) ; ++i)
+            sortOrder.insert(Constants::IconSortOrder[i], sortOrder.count());
+    }
+
+    // if it is missing - return the same value
+    if (!sortOrder.contains(icon))
+        return icon;
+
+    return sortOrder[icon];
+}
+
+QStandardItem *Utils::setSymbolInformationToItem(const SymbolInformation &information,
+                                                 QStandardItem *item)
+{
+    Q_ASSERT(item);
+
+    item->setData(information.name(), Constants::SymbolNameRole);
+    item->setData(information.type(), Constants::SymbolTypeRole);
+    item->setData(information.iconType(), Constants::IconTypeRole);
+
+    return item;
+}
+
+SymbolInformation Utils::symbolInformationFromItem(const QStandardItem *item)
+{
+    Q_ASSERT(item);
+
+    if (!item)
+        return SymbolInformation();
+
+    const QString &name = item->data(Constants::SymbolNameRole).toString();
+    const QString &type = item->data(Constants::SymbolTypeRole).toString();
+    int iconType = 0;
+
+    QVariant var = item->data(Constants::IconTypeRole);
+    bool ok = false;
+    int value;
+    if (var.isValid())
+        value = var.toInt(&ok);
+    if (ok)
+        iconType = value;
+
+    return SymbolInformation(name, type, iconType);
+}
+
+void Utils::fetchItemToTarget(QStandardItem *item, const QStandardItem *target)
+{
+    if (!item || !target)
+        return;
+
+    int itemIndex = 0;
+    int targetIndex = 0;
+    int itemRows = item->rowCount();
+    int targetRows = target->rowCount();
+
+    while (itemIndex < itemRows && targetIndex < targetRows) {
+        const QStandardItem *itemChild = item->child(itemIndex);
+        const QStandardItem *targetChild = target->child(targetIndex);
+
+        const SymbolInformation &itemInf = symbolInformationFromItem(itemChild);
+        const SymbolInformation &targetInf = symbolInformationFromItem(targetChild);
+
+        if (itemInf < targetInf) {
+            ++itemIndex;
+        } else if (itemInf == targetInf) {
+            ++itemIndex;
+            ++targetIndex;
+        } else {
+            item->insertRow(itemIndex, targetChild->clone());
+            ++itemIndex;
+            ++itemRows;
+            ++targetIndex;
+        }
+    }
+
+    // append
+    while (targetIndex < targetRows) {
+        item->appendRow(target->child(targetIndex)->clone());
+        ++targetIndex;
+    }
+}
+
+void Utils::moveItemToTarget(QStandardItem *item, const QStandardItem *target)
+{
+    if (!item || !target)
+        return;
+
+    int itemIndex = 0;
+    int targetIndex = 0;
+    int itemRows = item->rowCount();
+    int targetRows = target->rowCount();
+
+    while (itemIndex < itemRows && targetIndex < targetRows) {
+        QStandardItem *itemChild = item->child(itemIndex);
+        const QStandardItem *targetChild = target->child(targetIndex);
+
+        const SymbolInformation &itemInf = Utils::symbolInformationFromItem(itemChild);
+        const SymbolInformation &targetInf = Utils::symbolInformationFromItem(targetChild);
+
+        if (itemInf < targetInf) {
+            item->removeRow(itemIndex);
+            --itemRows;
+        } else if (itemInf == targetInf) {
+            moveItemToTarget(itemChild, targetChild);
+            ++itemIndex;
+            ++targetIndex;
+        } else {
+            item->insertRow(itemIndex, targetChild->clone());
+            moveItemToTarget(item->child(itemIndex), targetChild);
+            ++itemIndex;
+            ++itemRows;
+            ++targetIndex;
+        }
+    }
+
+    // append
+    while (targetIndex < targetRows) {
+        item->appendRow(target->child(targetIndex)->clone());
+        moveItemToTarget(item->child(itemIndex), target->child(targetIndex));
+        ++itemIndex;
+        ++itemRows;
+        ++targetIndex;
+    }
+
+    // remove end of item
+    while (itemIndex < itemRows) {
+        item->removeRow(itemIndex);
+        --itemRows;
+    }
+}
+
+} // namespace Internal
+} // namespace ClassView
diff --git a/src/plugins/classview/classviewutils.h b/src/plugins/classview/classviewutils.h
new file mode 100644
index 0000000000000000000000000000000000000000..3a7987b995885a236e9bd8c034642a2208023c66
--- /dev/null
+++ b/src/plugins/classview/classviewutils.h
@@ -0,0 +1,110 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Denis Mingulov.
+**
+** 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 CLASSVIEWUTILS_H
+#define CLASSVIEWUTILS_H
+
+#include "classviewsymbollocation.h"
+#include "classviewsymbolinformation.h"
+#include <QtCore/QVariant>
+#include <QtCore/QList>
+#include <QtCore/QSet>
+
+QT_FORWARD_DECLARE_CLASS(QStandardItem)
+
+namespace ClassView {
+namespace Internal {
+
+/*!
+   \class Utils
+   \brief Some common utils
+ */
+
+class Utils
+{
+    //! Private constructor
+    Utils();
+public:
+
+    /*!
+       \brief convert internal location container to QVariant compatible
+       \param locations Set of SymbolLocations
+       \return List of variant locations (can be added to an item's data)
+     */
+    static QList<QVariant> locationsToRole(const QSet<SymbolLocation> &locations);
+
+    /*!
+       \brief convert QVariant location container to internal
+       \param locations List of variant locations (from an item's data)
+       \return Set of SymbolLocations
+     */
+    static QSet<SymbolLocation> roleToLocations(const QList<QVariant> &locations);
+
+    /*!
+       \brief Returns sort order value for the icon type
+       \param iconType Icon type
+       \return Sort order value for the provided icon type
+     */
+    static int iconTypeSortOrder(int iconType);
+
+    /*!
+       \brief Get symbol information for the \a QStandardItem
+       \param item Item
+       \return Filled symbol information.
+     */
+    static SymbolInformation symbolInformationFromItem(const QStandardItem *item);
+
+    /*!
+       \brief Set symbol information to the \a QStandardItem
+       \param information
+       \param item Item
+       \return Filled item
+     */
+    static QStandardItem *setSymbolInformationToItem(const SymbolInformation &information,
+                                                     QStandardItem *item);
+
+    /*!
+       \brief Update an item to the target. (sorted, for fetching)
+       \param item Source item
+       \param target Target item
+     */
+    static void fetchItemToTarget(QStandardItem *item, const QStandardItem *target);
+
+    /*!
+       \brief Move an item to the target. (sorted)
+       \param item Source item
+       \param target Target item
+     */
+    static void moveItemToTarget(QStandardItem *item, const QStandardItem *target);
+};
+
+} // namespace Internal
+} // namespace ClassView
+
+#endif // CLASSVIEWUTILS_H
diff --git a/src/plugins/classview/images/hierarchicalmode.png b/src/plugins/classview/images/hierarchicalmode.png
new file mode 100644
index 0000000000000000000000000000000000000000..88432d2cb10c43de91fdb7ec7989285090747b0a
Binary files /dev/null and b/src/plugins/classview/images/hierarchicalmode.png differ
diff --git a/src/plugins/cppeditor/cppchecksymbols.cpp b/src/plugins/cppeditor/cppchecksymbols.cpp
index b38ba8e879284c3f8990ea19952a0e45cbc79bac..90261bb979b1ee8dd43b8ec2efa5acf0ebf0adf3 100644
--- a/src/plugins/cppeditor/cppchecksymbols.cpp
+++ b/src/plugins/cppeditor/cppchecksymbols.cpp
@@ -408,11 +408,11 @@ void CheckSymbols::checkName(NameAST *ast)
             const QByteArray id = QByteArray::fromRawData(ident->chars(), ident->size());
             if (_potentialTypes.contains(id)) {
                 Scope *scope = findScope(ast);
-                const QList<Symbol *> candidates = _context.lookup(ast->name, scope);
+                const QList<LookupItem> candidates = _context.lookup(ast->name, scope);
                 addTypeUsage(candidates, ast);
             } else if (_potentialMembers.contains(id)) {
                 Scope *scope = findScope(ast);
-                const QList<Symbol *> candidates = _context.lookup(ast->name, scope);
+                const QList<LookupItem> candidates = _context.lookup(ast->name, scope);
                 addMemberUsage(candidates, ast);
             }
         }
@@ -426,11 +426,11 @@ void CheckSymbols::checkMemberName(NameAST *ast)
             const QByteArray id = QByteArray::fromRawData(ident->chars(), ident->size());
             if (_potentialMembers.contains(id)) {
                 Scope *scope = findScope(ast);
-                const QList<Symbol *> candidates = _context.lookup(ast->name, scope);
+                const QList<LookupItem> candidates = _context.lookup(ast->name, scope);
                 addMemberUsage(candidates, ast);
             } else if (_potentialMembers.contains(id)) {
                 Scope *scope = findScope(ast);
-                const QList<Symbol *> candidates = _context.lookup(ast->name, scope);
+                const QList<LookupItem> candidates = _context.lookup(ast->name, scope);
                 addMemberUsage(candidates, ast);
             }
         }
@@ -500,7 +500,7 @@ bool CheckSymbols::visit(TypenameTypeParameterAST *ast)
             const QByteArray id = QByteArray::fromRawData(templId->chars(), templId->size());
             if (_potentialTypes.contains(id)) {
                 Scope *scope = findScope(_templateDeclarationStack.back());
-                const QList<Symbol *> candidates = _context.lookup(ast->name->name, scope);
+                const QList<LookupItem> candidates = _context.lookup(ast->name->name, scope);
                 addTypeUsage(candidates, ast->name);
             }
         }
@@ -582,7 +582,7 @@ void CheckSymbols::addTypeUsage(ClassOrNamespace *b, NameAST *ast)
     //qDebug() << "added use" << oo(ast->name) << line << column << length;
 }
 
-void CheckSymbols::addTypeUsage(const QList<Symbol *> &candidates, NameAST *ast)
+void CheckSymbols::addTypeUsage(const QList<LookupItem> &candidates, NameAST *ast)
 {
     unsigned startToken = ast->firstToken();
     if (DestructorNameAST *dtor = ast->asDestructorName())
@@ -596,7 +596,8 @@ void CheckSymbols::addTypeUsage(const QList<Symbol *> &candidates, NameAST *ast)
     getTokenStartPosition(startToken, &line, &column);
     const unsigned length = tok.length();
 
-    foreach (Symbol *c, candidates) {
+    foreach (const LookupItem &r, candidates) {
+        Symbol *c = r.declaration();
         if (c->isUsingDeclaration()) // skip using declarations...
             continue;
         else if (c->isUsingNamespaceDirective()) // ... and using namespace directives.
@@ -612,7 +613,7 @@ void CheckSymbols::addTypeUsage(const QList<Symbol *> &candidates, NameAST *ast)
     }
 }
 
-void CheckSymbols::addMemberUsage(const QList<Symbol *> &candidates, NameAST *ast)
+void CheckSymbols::addMemberUsage(const QList<LookupItem> &candidates, NameAST *ast)
 {
     unsigned startToken = ast->firstToken();
     if (DestructorNameAST *dtor = ast->asDestructorName())
@@ -626,8 +627,11 @@ void CheckSymbols::addMemberUsage(const QList<Symbol *> &candidates, NameAST *as
     getTokenStartPosition(startToken, &line, &column);
     const unsigned length = tok.length();
 
-    foreach (Symbol *c, candidates) {
-        if (! c->isDeclaration())
+    foreach (const LookupItem &r, candidates) {
+        Symbol *c = r.declaration();
+        if (! c)
+            continue;
+        else if (! c->isDeclaration())
             continue;
         else if (c->isTypedef())
             continue;
diff --git a/src/plugins/cppeditor/cppchecksymbols.h b/src/plugins/cppeditor/cppchecksymbols.h
index bb996fb691d9cc2ee0f7e5347e3a215e865cac7a..8db7fda967d643b8bfbc4bdaef8bcde00979fce5 100644
--- a/src/plugins/cppeditor/cppchecksymbols.h
+++ b/src/plugins/cppeditor/cppchecksymbols.h
@@ -84,11 +84,11 @@ protected:
     void checkName(NameAST *ast);
     void checkNamespace(NameAST *name);
     void addTypeUsage(ClassOrNamespace *b, NameAST *ast);
-    void addTypeUsage(const QList<Symbol *> &candidates, NameAST *ast);
+    void addTypeUsage(const QList<LookupItem> &candidates, NameAST *ast);
     void addTypeUsage(const Use &use);
 
     void checkMemberName(NameAST *ast);
-    void addMemberUsage(const QList<Symbol *> &candidates, NameAST *ast);
+    void addMemberUsage(const QList<LookupItem> &candidates, NameAST *ast);
 
     virtual bool preVisit(AST *);
 
diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp
index 663bc73f6226fa8eabf6edd122bb5b6c10368b52..9dae26316d091fe29db29dfbd27a628d0f64cfdc 100644
--- a/src/plugins/cppeditor/cppeditor.cpp
+++ b/src/plugins/cppeditor/cppeditor.cpp
@@ -995,8 +995,9 @@ void CPPEditor::switchDeclarationDefinition()
             LookupContext context(thisDocument, snapshot);
 
             Function *functionDefinition = functionScope->owner()->asFunction();
-            const QList<Symbol *> declarations = context.lookup(functionDefinition->name(), functionDefinition->scope());
-            foreach (Symbol *decl, declarations) {
+            const QList<LookupItem> declarations = context.lookup(functionDefinition->name(), functionDefinition->scope());
+            foreach (const LookupItem &r, declarations) {
+                Symbol *decl = r.declaration();
                 // TODO: check decl.
                 openCppEditorAt(linkToSymbol(decl));
                 break;
diff --git a/src/plugins/cppeditor/cppoutline.cpp b/src/plugins/cppeditor/cppoutline.cpp
index 4e9fcfdbdaf6ed21b44cd7f1ae81b3c62a841e2d..14d8b0b9e9301de0e8cb01fcb6333b9b86f9965f 100644
--- a/src/plugins/cppeditor/cppoutline.cpp
+++ b/src/plugins/cppeditor/cppoutline.cpp
@@ -18,16 +18,11 @@ enum {
 };
 
 CppOutlineTreeView::CppOutlineTreeView(QWidget *parent) :
-    QTreeView(parent)
+    Utils::NavigationTreeView(parent)
 {
     // see also QmlJSOutlineTreeView
     setFocusPolicy(Qt::NoFocus);
-    setFrameStyle(QFrame::NoFrame);
-    setAttribute(Qt::WA_MacShowFocusRect, false);
-    setUniformRowHeights(true);
     setHeaderHidden(true);
-    setTextElideMode(Qt::ElideNone);
-    setIndentation(20);
     setExpandsOnDoubleClick(false);
 }
 
diff --git a/src/plugins/cppeditor/cppoutline.h b/src/plugins/cppeditor/cppoutline.h
index d007b9689de001d03db487328b17d2ecbe317f4d..a9f2e65e0fbc705002ed53bdbc8c6b06334636fb 100644
--- a/src/plugins/cppeditor/cppoutline.h
+++ b/src/plugins/cppeditor/cppoutline.h
@@ -3,6 +3,7 @@
 
 #include "cppeditor.h"
 
+#include <utils/navigationtreeview.h>
 #include <texteditor/ioutlinewidget.h>
 
 #include <QtGui/QSortFilterProxyModel>
@@ -11,7 +12,7 @@
 namespace CppEditor {
 namespace Internal {
 
-class CppOutlineTreeView : public QTreeView
+class CppOutlineTreeView : public Utils::NavigationTreeView
 {
     Q_OBJECT
 public:
diff --git a/src/plugins/cppeditor/cppquickfix.cpp b/src/plugins/cppeditor/cppquickfix.cpp
index b717d632541392c1cc55635d29e5702b6f5d7979..15c827bc89b4e5abc19fbff55870b03237498a50 100644
--- a/src/plugins/cppeditor/cppquickfix.cpp
+++ b/src/plugins/cppeditor/cppquickfix.cpp
@@ -920,7 +920,8 @@ public:
                 ClassOrNamespace *b = context.lookupType(function);
                 if (b) {
                     // Do we have a tr method?
-                    foreach(Symbol *s, b->find(trName)) {
+                    foreach(const LookupItem &r, b->find(trName)) {
+                        Symbol *s = r.declaration();
                         if (s->type()->isFunctionType()) {
                             m_option = useTr;
                             // no context required for tr
@@ -1302,9 +1303,10 @@ protected:
             if (Enum *e = result.declaration()->type()->asEnumType())
                 return e;
             if (NamedType *namedType = fst->asNamedType()) {
-                QList<Symbol *> candidates =
+                QList<LookupItem> candidates =
                         typeOfExpression.context().lookup(namedType->name(), scope);
-                foreach (Symbol *candidate, candidates) {
+                foreach (const LookupItem &r, candidates) {
+                    Symbol *candidate = r.declaration();
                     if (Enum *e = candidate->asEnum()) {
                         return e;
                     }
diff --git a/src/plugins/cpptools/cppcodecompletion.cpp b/src/plugins/cpptools/cppcodecompletion.cpp
index 7b4303731e6e8fa6122acc4d28e2774d2915f0ca..44f8b861fac7507500271249d9d0346de503a545 100644
--- a/src/plugins/cpptools/cppcodecompletion.cpp
+++ b/src/plugins/cpptools/cppcodecompletion.cpp
@@ -1175,11 +1175,13 @@ bool CppCodeCompletion::completeConstructorOrFunction(const QList<LookupItem> &r
 
             if (NamedType *namedTy = ty->asNamedType()) {
                 if (ClassOrNamespace *b = context.lookupType(namedTy->name(), scope)) {
-                    foreach (Symbol *overload, b->lookup(functionCallOp)) {
+                    foreach (const LookupItem &r, b->lookup(functionCallOp)) {
+                        Symbol *overload = r.declaration();
                         FullySpecifiedType overloadTy = overload->type().simplified();
 
-                        if (Function *funTy = overloadTy->asFunctionType())
+                        if (Function *funTy = overloadTy->asFunctionType()) {
                             functions.append(funTy);
+                        }
                     }
                 }
             }
diff --git a/src/plugins/help/help.pro b/src/plugins/help/help.pro
index 706675e9fb494340f6c419a775d9a6f95c54a8ba..890779e9b0e9145c4788a1647194ff045d6aec30 100644
--- a/src/plugins/help/help.pro
+++ b/src/plugins/help/help.pro
@@ -26,6 +26,7 @@ HEADERS += \
     openpagesmodel.h \
     openpagesswitcher.h \
     openpageswidget.h \
+    remotehelpfilter.h \
     searchwidget.h \
     xbelsupport.h
 
@@ -46,12 +47,14 @@ SOURCES += \
     openpagesmodel.cpp \
     openpagesswitcher.cpp \
     openpageswidget.cpp \
+    remotehelpfilter.cpp \
     searchwidget.cpp \
     xbelsupport.cpp
 
 FORMS += docsettingspage.ui \
     filtersettingspage.ui \
-    generalsettingspage.ui
+    generalsettingspage.ui \
+    remotehelpfilter.ui
 
 RESOURCES += help.qrc
 include(../../shared/help/help.pri)
diff --git a/src/plugins/help/helpplugin.cpp b/src/plugins/help/helpplugin.cpp
index 7b6b0af5303e830cfdcf6aac0fd3954782ec6369..d06e0ccda6133889cb0fe34484cc84e1d176afdb 100644
--- a/src/plugins/help/helpplugin.cpp
+++ b/src/plugins/help/helpplugin.cpp
@@ -44,6 +44,7 @@
 #include "indexwindow.h"
 #include "openpagesmanager.h"
 #include "openpagesmodel.h"
+#include "remotehelpfilter.h"
 #include "searchwidget.h"
 
 #include <coreplugin/actionmanager/actionmanager.h>
@@ -300,6 +301,11 @@ bool HelpPlugin::initialize(const QStringList &arguments, QString *error)
     connect(helpIndexFilter, SIGNAL(linkActivated(QUrl)), this,
         SLOT(switchToHelpMode(QUrl)));
 
+    RemoteHelpFilter *remoteHelpFilter = new RemoteHelpFilter();
+    addAutoReleasedObject(remoteHelpFilter);
+    connect(remoteHelpFilter, SIGNAL(linkActivated(QUrl)), this,
+        SLOT(switchToHelpMode(QUrl)));
+
     QDesktopServices::setUrlHandler("qthelp", this, "handleHelpRequest");
     connect(m_core->modeManager(), SIGNAL(currentModeChanged(Core::IMode*)),
         this, SLOT(modeChanged(Core::IMode*)));
diff --git a/src/plugins/help/remotehelpfilter.cpp b/src/plugins/help/remotehelpfilter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8fcbeae3eda29313be429c888274306892a9b307
--- /dev/null
+++ b/src/plugins/help/remotehelpfilter.cpp
@@ -0,0 +1,172 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 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 "remotehelpfilter.h"
+
+#include <QtCore/QUrl>
+
+namespace Help {
+    namespace Internal {
+
+RemoteFilterOptions::RemoteFilterOptions(RemoteHelpFilter *filter, QWidget *parent)
+    : QDialog(parent)
+    , m_filter(filter)
+{
+    m_ui.setupUi(this);
+    m_ui.shortcutEdit->setText(m_filter->shortcutString());
+    m_ui.limitCheck->setChecked(!m_filter->isIncludedByDefault());
+    foreach (const QString &url, m_filter->remoteUrls()) {
+        QListWidgetItem *item = new QListWidgetItem(url);
+        m_ui.listWidget->addItem(item);
+        item->setFlags(item->flags() | Qt::ItemIsEditable);
+    }
+
+    connect(m_ui.add, SIGNAL(clicked()), this, SLOT(addNewItem()));
+    connect(m_ui.remove, SIGNAL(clicked()), this, SLOT(removeItem()));
+}
+
+void RemoteFilterOptions::addNewItem()
+{
+    QListWidgetItem *item = new QListWidgetItem(tr("Double click to edit item."));
+    m_ui.listWidget->addItem(item);
+    item->setSelected(true);
+    item->setFlags(item->flags() | Qt::ItemIsEditable);
+    m_ui.listWidget->editItem(item);
+}
+
+void RemoteFilterOptions::removeItem()
+{
+    if (QListWidgetItem *item = m_ui.listWidget->currentItem()) {
+        m_ui.listWidget->removeItemWidget(item);
+        delete item;
+    }
+}
+
+// -- RemoteHelpFilter
+
+RemoteHelpFilter::RemoteHelpFilter()
+{
+    setIncludedByDefault(false);
+    setShortcutString(QLatin1String("r"));
+    m_remoteUrls.append(QLatin1String("http://www.bing.com/search?q=%1"));
+    m_remoteUrls.append(QLatin1String("http://www.google.com/search?q=%1"));
+    m_remoteUrls.append(QLatin1String("http://search.yahoo.com/search?p=%1"));
+    m_remoteUrls.append(QLatin1String("http://www.cplusplus.com/reference/stl/%1"));
+    m_remoteUrls.append(QLatin1String("http://en.wikipedia.org/w/index.php?search=%1"));
+}
+
+RemoteHelpFilter::~RemoteHelpFilter()
+{
+}
+
+QString RemoteHelpFilter::displayName() const
+{
+    return tr("Online documentation");
+}
+
+QString RemoteHelpFilter::id() const
+{
+    return QLatin1String("RemoteHelpFilter");
+}
+
+Locator::ILocatorFilter::Priority RemoteHelpFilter::priority() const
+{
+    return Medium;
+}
+
+QList<Locator::FilterEntry> RemoteHelpFilter::matchesFor(const QString &pattern)
+{
+    QList<Locator::FilterEntry> entries;
+    foreach (const QString &url, m_remoteUrls) {
+        entries.append(Locator::FilterEntry(this, url.arg(pattern), QVariant(),
+            m_icon));
+    }
+    return entries;
+}
+
+void RemoteHelpFilter::accept(Locator::FilterEntry selection) const
+{
+    const QString &url = selection.displayName;
+    if (!url.isEmpty()) {
+        emit linkActivated(url);
+    }
+}
+
+void RemoteHelpFilter::refresh(QFutureInterface<void> &future)
+{
+    Q_UNUSED(future)
+    // Nothing to refresh
+}
+
+QByteArray RemoteHelpFilter::saveState() const
+{
+    QByteArray value;
+    QDataStream out(&value, QIODevice::WriteOnly);
+    out << m_remoteUrls.join(QLatin1String("^"));
+    out << shortcutString();
+    out << isIncludedByDefault();
+    return value;
+}
+
+bool RemoteHelpFilter::restoreState(const QByteArray &state)
+{
+    QDataStream in(state);
+
+    QString value;
+    in >> value;
+    m_remoteUrls = value.split(QLatin1String("^"), QString::SkipEmptyParts);
+
+    QString shortcut;
+    in >> shortcut;
+    setShortcutString(shortcut);
+
+    bool defaultFilter;
+    in >> defaultFilter;
+    setIncludedByDefault(defaultFilter);
+
+    return true;
+}
+
+bool RemoteHelpFilter::openConfigDialog(QWidget *parent, bool &needsRefresh)
+{
+    Q_UNUSED(needsRefresh)
+    RemoteFilterOptions optionsDialog(this, parent);
+    if (optionsDialog.exec() == QDialog::Accepted) {
+        m_remoteUrls.clear();
+        setIncludedByDefault(!optionsDialog.m_ui.limitCheck->isChecked());
+        setShortcutString(optionsDialog.m_ui.shortcutEdit->text().trimmed());
+        for (int i = 0; i < optionsDialog.m_ui.listWidget->count(); ++i)
+            m_remoteUrls.append(optionsDialog.m_ui.listWidget->item(i)->text());
+        return true;
+    }
+    return true;
+}
+
+    } // namespace Internal
+} // namespace Help
diff --git a/src/plugins/help/remotehelpfilter.h b/src/plugins/help/remotehelpfilter.h
new file mode 100644
index 0000000000000000000000000000000000000000..2799ebe6c2208bfcd78224f881e8d7bc4914d5d7
--- /dev/null
+++ b/src/plugins/help/remotehelpfilter.h
@@ -0,0 +1,90 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 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 REMOTEHELPFILTER_H
+#define REMOTEHELPFILTER_H
+
+#include "ui_remotehelpfilter.h"
+
+#include <locator/ilocatorfilter.h>
+
+#include <QtGui/QIcon>
+
+namespace Help {
+    namespace Internal {
+
+class RemoteHelpFilter : public Locator::ILocatorFilter
+{
+    Q_OBJECT
+public:
+    RemoteHelpFilter();
+    ~RemoteHelpFilter();
+
+    // ILocatorFilter
+    QString displayName() const;
+    QString id() const;
+    Priority priority() const;
+    QList<Locator::FilterEntry> matchesFor(const QString &entry);
+    void accept(Locator::FilterEntry selection) const;
+    void refresh(QFutureInterface<void> &future);
+    QByteArray saveState() const;
+    bool restoreState(const QByteArray &state);
+    bool openConfigDialog(QWidget *parent, bool &needsRefresh);
+
+    QStringList remoteUrls() const { return m_remoteUrls; }
+
+signals:
+    void linkActivated(const QUrl &url) const;
+
+private:
+    QIcon m_icon;
+    QStringList m_remoteUrls;
+};
+
+class RemoteFilterOptions : public QDialog
+{
+    Q_OBJECT
+    friend class RemoteHelpFilter;
+
+public:
+    RemoteFilterOptions(RemoteHelpFilter *filter, QWidget *parent = 0);
+
+private slots:
+    void addNewItem();
+    void removeItem();
+
+private:
+    RemoteHelpFilter *m_filter;
+    Ui::RemoteFilterOptions m_ui;
+};
+
+    } // namespace Internal
+} // namespace Help
+
+#endif // REMOTEHELPFILTER_H
diff --git a/src/plugins/help/remotehelpfilter.ui b/src/plugins/help/remotehelpfilter.ui
new file mode 100644
index 0000000000000000000000000000000000000000..1461573b0813f325465b79d9d31f8acf8ffc2470
--- /dev/null
+++ b/src/plugins/help/remotehelpfilter.ui
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Help::Internal::RemoteFilterOptions</class>
+ <widget class="QDialog" name="Help::Internal::RemoteFilterOptions">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>340</width>
+    <height>179</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Filter configuration</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout_2">
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <item>
+      <widget class="QLabel" name="label">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="text">
+        <string>Prefix:</string>
+       </property>
+       <property name="buddy">
+        <cstring>shortcutEdit</cstring>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QLineEdit" name="shortcutEdit">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QCheckBox" name="limitCheck">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="text">
+        <string>Limit to prefix</string>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout_2">
+     <item>
+      <widget class="QListWidget" name="listWidget"/>
+     </item>
+     <item>
+      <layout class="QVBoxLayout" name="verticalLayout">
+       <item>
+        <widget class="QToolButton" name="add">
+         <property name="minimumSize">
+          <size>
+           <width>21</width>
+           <height>21</height>
+          </size>
+         </property>
+         <property name="text">
+          <string>+</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QToolButton" name="remove">
+         <property name="minimumSize">
+          <size>
+           <width>21</width>
+           <height>21</height>
+          </size>
+         </property>
+         <property name="text">
+          <string>-</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <spacer name="verticalSpacer">
+         <property name="orientation">
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>20</width>
+           <height>20</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+      </layout>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>Help::Internal::RemoteFilterOptions</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>248</x>
+     <y>254</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>157</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>Help::Internal::RemoteFilterOptions</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>316</x>
+     <y>260</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>286</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro
index f66ea479776ba96f6522b8e91c5b1b5d829a49bf..094668d4c0f26059250af95c16b687b94b41eaac 100644
--- a/src/plugins/plugins.pro
+++ b/src/plugins/plugins.pro
@@ -34,6 +34,7 @@ SUBDIRS   = plugin_coreplugin \
             plugin_genericprojectmanager \
             plugin_qmljseditor \
             plugin_mercurial \
+            plugin_classview \
             debugger/dumper.pro
 
 contains(QT_CONFIG, declarative) {
@@ -208,3 +209,9 @@ plugin_mercurial.subdir = mercurial
 plugin_mercurial.depends = plugin_vcsbase
 plugin_mercurial.depends += plugin_projectexplorer
 plugin_mercurial.depends += plugin_coreplugin
+
+plugin_classview.subdir = classview
+plugin_classview.depends = plugin_coreplugin
+plugin_classview.depends += plugin_cpptools
+plugin_classview.depends += plugin_projectexplorer
+plugin_classview.depends += plugin_texteditor
diff --git a/src/plugins/projectexplorer/projecttreewidget.cpp b/src/plugins/projectexplorer/projecttreewidget.cpp
index 56495cf6394352f86f0812e78d2ec13e947f035e..d6fd7a5f62c55d417aaaa9afc9f2128aafd35d96 100644
--- a/src/plugins/projectexplorer/projecttreewidget.cpp
+++ b/src/plugins/projectexplorer/projecttreewidget.cpp
@@ -38,6 +38,7 @@
 #include <coreplugin/icore.h>
 #include <coreplugin/editormanager/editormanager.h>
 #include <utils/qtcassert.h>
+#include <utils/navigationtreeview.h>
 
 #include <QtCore/QDebug>
 #include <QtCore/QSettings>
@@ -57,14 +58,12 @@ namespace {
     bool debug = false;
 }
 
-class ProjectTreeView : public QTreeView
+class ProjectTreeView : public Utils::NavigationTreeView
 {
 public:
     ProjectTreeView()
     {
         setEditTriggers(QAbstractItemView::EditKeyPressed);
-        setFrameStyle(QFrame::NoFrame);
-        setIndentation(indentation() * 9/10);
         {
             QHeaderView *treeHeader = header();
             treeHeader->setVisible(false);
@@ -72,41 +71,8 @@ public:
             treeHeader->setStretchLastSection(true);
         }
         setContextMenuPolicy(Qt::CustomContextMenu);
-        setUniformRowHeights(true);
-        setTextElideMode(Qt::ElideNone);
 //        setExpandsOnDoubleClick(false);
-        setAttribute(Qt::WA_MacShowFocusRect, false);
     }
-
-protected:
-    // This is a workaround to stop Qt from redrawing the project tree every
-    // time the user opens or closes a menu when it has focus. Would be nicer to
-    // fix it in Qt.
-    void focusInEvent(QFocusEvent *event)
-    {
-        if (event->reason() != Qt::PopupFocusReason)
-            QTreeView::focusInEvent(event);
-    }
-
-    void focusOutEvent(QFocusEvent *event)
-    {
-        if (event->reason() != Qt::PopupFocusReason)
-            QTreeView::focusOutEvent(event);
-    }
-
-#ifdef Q_WS_MAC
-    void keyPressEvent(QKeyEvent *event)
-    {
-        if ((event->key() == Qt::Key_Return
-                || event->key() == Qt::Key_Enter)
-                && event->modifiers() == 0
-                && currentIndex().isValid()) {
-            emit activated(currentIndex());
-            return;
-        }
-        QTreeView::keyPressEvent(event);
-    }
-#endif
 };
 
 /*!
diff --git a/src/plugins/qmljseditor/qmljseditor.cpp b/src/plugins/qmljseditor/qmljseditor.cpp
index 1ab408485db96ad73c2b28a87db70f43ea21c850..3cf317bd2ad439bc08dcf08c93d8f16101e28933 100644
--- a/src/plugins/qmljseditor/qmljseditor.cpp
+++ b/src/plugins/qmljseditor/qmljseditor.cpp
@@ -35,6 +35,7 @@
 #include "qmloutlinemodel.h"
 
 #include <qmljs/qmljsindenter.h>
+#include <qmljs/qmljsbind.h>
 #include <qmljs/qmljscheck.h>
 #include <qmljs/qmljsdocument.h>
 #include <qmljs/qmljsicontextpane.h>
@@ -525,6 +526,12 @@ QList<AST::Node *> SemanticInfo::astPath(int cursorPosition) const
     return path;
 }
 
+static bool importContainsCursor(UiImport *importAst, unsigned cursorPosition)
+{
+    return cursorPosition >= importAst->firstSourceLocation().begin()
+           && cursorPosition <= importAst->lastSourceLocation().end();
+}
+
 AST::Node *SemanticInfo::nodeUnderCursor(int pos) const
 {
     if (! document)
@@ -532,6 +539,19 @@ AST::Node *SemanticInfo::nodeUnderCursor(int pos) const
 
     const unsigned cursorPosition = pos;
 
+    foreach (const Bind::ImportInfo &import, document->bind()->fileImports()) {
+        if (importContainsCursor(import.ast, cursorPosition))
+            return import.ast;
+    }
+    foreach (const Bind::ImportInfo &import, document->bind()->directoryImports()) {
+        if (importContainsCursor(import.ast, cursorPosition))
+            return import.ast;
+    }
+    foreach (const Bind::ImportInfo &import, document->bind()->libraryImports()) {
+        if (importContainsCursor(import.ast, cursorPosition))
+            return import.ast;
+    }
+
     CollectASTNodes nodes;
     nodes.accept(document->ast());
 
@@ -1226,6 +1246,19 @@ TextEditor::BaseTextEditor::Link QmlJSTextEditor::findLinkAt(const QTextCursor &
 
     AST::Node *node = semanticInfo.nodeUnderCursor(cursorPosition);
 
+    if (AST::UiImport *importAst = cast<AST::UiImport *>(node)) {
+        // if it's a file import, link to the file
+        foreach (const Bind::ImportInfo &import, semanticInfo.document->bind()->fileImports()) {
+            if (import.ast == importAst) {
+                BaseTextEditor::Link link(import.name);
+                link.begin = importAst->firstSourceLocation().begin();
+                link.end = importAst->lastSourceLocation().end();
+                return link;
+            }
+        }
+        return Link();
+    }
+
     LookupContext::Ptr lookupContext = LookupContext::create(semanticInfo.document, semanticInfo.snapshot, semanticInfo.astPath(cursorPosition));
     const Interpreter::Value *value = lookupContext->evaluate(node);
 
diff --git a/src/plugins/qmljseditor/qmljsoutline.cpp b/src/plugins/qmljseditor/qmljsoutline.cpp
index 7831670eec72410e9e11e836cd9f15de773b3708..c349dfc9ed9d04edb610c461e1f8a21cef11c64d 100644
--- a/src/plugins/qmljseditor/qmljsoutline.cpp
+++ b/src/plugins/qmljseditor/qmljsoutline.cpp
@@ -17,16 +17,11 @@ namespace QmlJSEditor {
 namespace Internal {
 
 QmlJSOutlineTreeView::QmlJSOutlineTreeView(QWidget *parent) :
-    QTreeView(parent)
+    Utils::NavigationTreeView(parent)
 {
     // see also CppOutlineTreeView
     setFocusPolicy(Qt::NoFocus);
-    setFrameStyle(QFrame::NoFrame);
-    setAttribute(Qt::WA_MacShowFocusRect, false);
-    setUniformRowHeights(true);
     setHeaderHidden(true);
-    setTextElideMode(Qt::ElideNone);
-    setIndentation(20);
     setExpandsOnDoubleClick(false);
 }
 
diff --git a/src/plugins/qmljseditor/qmljsoutline.h b/src/plugins/qmljseditor/qmljsoutline.h
index 15221210cb94e211e351c529708597ffd31b5220..27c2e4f8d408edc68a1d56dc8de5b62407f4eef4 100644
--- a/src/plugins/qmljseditor/qmljsoutline.h
+++ b/src/plugins/qmljseditor/qmljsoutline.h
@@ -3,6 +3,7 @@
 
 #include "qmljseditor.h"
 
+#include <utils/navigationtreeview.h>
 #include <texteditor/ioutlinewidget.h>
 
 #include <QtGui/QTreeView>
@@ -19,7 +20,7 @@ class Editor;
 namespace QmlJSEditor {
 namespace Internal {
 
-class QmlJSOutlineTreeView : public QTreeView
+class QmlJSOutlineTreeView : public Utils::NavigationTreeView
 {
     Q_OBJECT
 public:
diff --git a/src/shared/cplusplus/FullySpecifiedType.cpp b/src/shared/cplusplus/FullySpecifiedType.cpp
index da6c16a54a2de19c504bde4590c609c3424ead4a..764c56a1ccbfc6735eba8dce0ec96fe1c3c42cfb 100644
--- a/src/shared/cplusplus/FullySpecifiedType.cpp
+++ b/src/shared/cplusplus/FullySpecifiedType.cpp
@@ -235,6 +235,12 @@ FullySpecifiedType FullySpecifiedType::simplified() const
     return *this;
 }
 
+unsigned FullySpecifiedType::flags() const
+{ return _flags; }
+
+void FullySpecifiedType::setFlags(unsigned flags)
+{ _flags = flags; }
+
 void FullySpecifiedType::copySpecifiers(const FullySpecifiedType &type)
 {
     // class storage specifiers
diff --git a/src/shared/cplusplus/FullySpecifiedType.h b/src/shared/cplusplus/FullySpecifiedType.h
index 7905df162de6c95e3977ef0392ff8ca582a66e13..2d0824556a0d49d0a59771da63e14d1c3c5b30b4 100644
--- a/src/shared/cplusplus/FullySpecifiedType.h
+++ b/src/shared/cplusplus/FullySpecifiedType.h
@@ -134,6 +134,9 @@ public:
 
     void copySpecifiers(const FullySpecifiedType &type);
 
+    unsigned flags() const;
+    void setFlags(unsigned flags);
+
 private:
     Type *_type;
     struct Flags {
diff --git a/tests/auto/cplusplus/lookup/tst_lookup.cpp b/tests/auto/cplusplus/lookup/tst_lookup.cpp
index fdf432704e39990f1806214682eb9bb2dac0acb6..6aae4b0b7926d8cf8aeace186a8ab7e85a144638 100644
--- a/tests/auto/cplusplus/lookup/tst_lookup.cpp
+++ b/tests/auto/cplusplus/lookup/tst_lookup.cpp
@@ -64,6 +64,13 @@ private Q_SLOTS:
     void class_with_baseclass();
     void class_with_protocol_with_protocol();
     void iface_impl_scoping();
+
+    // template instantiation:
+    void templates_1();
+    void templates_2();
+    void templates_3();
+    void templates_4();
+    void templates_5();
 };
 
 void tst_Lookup::base_class_defined_1()
@@ -169,14 +176,14 @@ void tst_Lookup::simple_class_1()
     QVERIFY(klass->symbols().contains(impl));
 
     // check method resolving:
-    QList<Symbol *> results = context.lookup(allocMethodImpl->name(), impl->members());
+    QList<LookupItem> results = context.lookup(allocMethodImpl->name(), impl->members());
     QCOMPARE(results.size(), 2);
-    QCOMPARE(results.at(0), allocMethodIface);
-    QCOMPARE(results.at(1), allocMethodImpl);
+    QCOMPARE(results.at(0).declaration(), allocMethodIface);
+    QCOMPARE(results.at(1).declaration(), allocMethodImpl);
 
     results = context.lookup(deallocMethod->name(), impl->members());
     QCOMPARE(results.size(), 1);
-    QCOMPARE(results.at(0), deallocMethod);
+    QCOMPARE(results.at(0).declaration(), deallocMethod);
 }
 
 void tst_Lookup::class_with_baseclass()
@@ -230,13 +237,13 @@ void tst_Lookup::class_with_baseclass()
     QVERIFY(objClass != 0);
     QVERIFY(objClass->symbols().contains(baseZoo));
 
-    QList<Symbol *> results = context.lookup(baseDecl->name(), zooImpl->members());
+    QList<LookupItem> results = context.lookup(baseDecl->name(), zooImpl->members());
     QCOMPARE(results.size(), 1);
-    QCOMPARE(results.at(0), baseDecl);
+    QCOMPARE(results.at(0).declaration(), baseDecl);
 
     results = context.lookup(baseMethod->name(), zooImpl->members());
     QCOMPARE(results.size(), 1);
-    QCOMPARE(results.at(0), baseMethod);
+    QCOMPARE(results.at(0).declaration(), baseMethod);
 }
 
 void tst_Lookup::class_with_protocol_with_protocol()
@@ -279,20 +286,20 @@ void tst_Lookup::class_with_protocol_with_protocol()
     const LookupContext context(doc, snapshot);
 
     {
-        const QList<Symbol *> candidates = context.lookup(P1->name(), zooImpl->scope());
+        const QList<LookupItem> candidates = context.lookup(P1->name(), zooImpl->scope());
         QCOMPARE(candidates.size(), 1);
-        QVERIFY(candidates.contains(P1));
+        QVERIFY(candidates.at(0).declaration() == P1);
     }
 
     {
-        const QList<Symbol *> candidates = context.lookup(P2->protocolAt(0)->name(), zooImpl->scope());
+        const QList<LookupItem> candidates = context.lookup(P2->protocolAt(0)->name(), zooImpl->scope());
         QCOMPARE(candidates.size(), 1);
-        QVERIFY(candidates.contains(P1));
+        QVERIFY(candidates.first().declaration() == P1);
     }
 
-    QList<Symbol *> results = context.lookup(p1method->name(), zooImpl->members());
+    QList<LookupItem> results = context.lookup(p1method->name(), zooImpl->members());
     QCOMPARE(results.size(), 1);
-    QCOMPARE(results.at(0), p1method);
+    QCOMPARE(results.at(0).declaration(), p1method);
 }
 
 void tst_Lookup::iface_impl_scoping()
@@ -341,9 +348,9 @@ void tst_Lookup::iface_impl_scoping()
         QVERIFY(arg->name()->identifier());
         QCOMPARE(arg->name()->identifier()->chars(), "arg");
 
-        const QList<Symbol *> candidates = context.lookup(arg->name(), method1Body->scope());
+        const QList<LookupItem> candidates = context.lookup(arg->name(), method1Body->scope());
         QCOMPARE(candidates.size(), 1);
-        QVERIFY(candidates.at(0)->type()->asIntegerType());
+        QVERIFY(candidates.at(0).declaration()->type()->asIntegerType());
     }
 
     Declaration *method2 = iface->memberAt(1)->asDeclaration();
@@ -351,11 +358,174 @@ void tst_Lookup::iface_impl_scoping()
     QCOMPARE(method2->identifier()->chars(), "method2");
 
     { // verify if we can resolve "method2" in the body
-        const QList<Symbol *> candidates = context.lookup(method2->name(), method1Body->scope());
+        const QList<LookupItem> candidates = context.lookup(method2->name(), method1Body->scope());
         QCOMPARE(candidates.size(), 1);
-        QCOMPARE(candidates.at(0), method2);
+        QCOMPARE(candidates.at(0).declaration(), method2);
     }
 }
 
+void tst_Lookup::templates_1()
+{
+    const QByteArray source = "\n"
+            "namespace std {\n"
+            "    template <typename T>\n"
+            "    struct _List_iterator {\n"
+            "        T data;\n"
+            "    };\n"
+            "\n"
+            "    template <typename T>\n"
+            "    struct list {\n"
+            "        typedef _List_iterator<T> iterator;\n"
+            "\n"
+            "        iterator begin();\n"
+            "        _List_iterator<T> end();\n"
+            "    };\n"
+            "}\n"
+            "\n"
+            "struct Point {\n"
+            "    int x, y;\n"
+            "};\n"
+            "\n"
+            "int main()\n"
+            "{\n"
+            "    std::list<Point> l;\n"
+            "    l.begin();  // std::_List_iterator<Point> .. and not only _List_iterator<Point>\n"
+            "    l.end(); // std::_List_iterator<Point>\n"
+            "}\n";
+    Document::Ptr doc = Document::create("templates_1");
+    doc->setSource(source);
+    doc->parse();
+    doc->check();
+
+    QVERIFY(doc->diagnosticMessages().isEmpty());
+}
+
+void tst_Lookup::templates_2()
+{
+    const QByteArray source = "\n"
+            "template <typename T1>\n"
+            "struct Node {\n"
+            "    T1 value;\n"
+            "    Node *next;\n"
+            "    Node<T1> *other_next;\n"
+            "};\n"
+            "\n"
+            "template <typename T2>\n"
+            "struct List {\n"
+            "    Node<T2> *elements;\n"
+            "};\n"
+            "\n"
+            "int main()\n"
+            "{\n"
+            "    List<int> *e;\n"
+            "    e->elements; // Node<int> *\n"
+            "    e->elements->next; // Node<int> *\n"
+            "    e->elements->other_next; // Node<int> *\n"
+            "}\n"
+;
+    Document::Ptr doc = Document::create("templates_2");
+    doc->setSource(source);
+    doc->parse();
+    doc->check();
+
+    QVERIFY(doc->diagnosticMessages().isEmpty());
+}
+
+void tst_Lookup::templates_3()
+{
+    const QByteArray source = "\n"
+            "struct Point {\n"
+            "    int x, y;\n"
+            "};\n"
+            "\n"
+            "template <typename T = Point>\n"
+            "struct List {\n"
+            "    const T &at(int);\n"
+            "};\n"
+            "\n"
+            "int main()\n"
+            "{\n"
+            "    List<> l;\n"
+            "    l.at(0); // const Point &\n"
+            "}\n";
+    Document::Ptr doc = Document::create("templates_3");
+    doc->setSource(source);
+    doc->parse();
+    doc->check();
+
+    QVERIFY(doc->diagnosticMessages().isEmpty());
+}
+
+void tst_Lookup::templates_4()
+{
+    const QByteArray source = "\n"
+            "template <typename T>\n"
+            "struct Allocator {\n"
+            "    typedef T *pointer_type;\n"
+            "    typedef T &reference_type;\n"
+            "};\n"
+            "\n"
+            "template <typename T>\n"
+            "struct SharedPtr {\n"
+            "    typedef typename Allocator<T>::pointer_type pointer_type;\n"
+            "    typedef typename Allocator<T>::reference_type reference_type;\n"
+            "\n"
+            "    pointer_type operator->();\n"
+            "    reference_type operator*();\n"
+            "\n"
+            "    pointer_type data();\n"
+            "    reference_type get();\n"
+            "\n"
+            "};\n"
+            "\n"
+            "struct Point {\n"
+            "    int x,y;\n"
+            "};\n"
+            "\n"
+            "int main()\n"
+            "{\n"
+            "    SharedPtr<Point> l;\n"
+            "\n"
+            "    l->x; // int\n"
+            "    (*l); // Point &\n"
+            "}\n";
+    Document::Ptr doc = Document::create("templates_4");
+    doc->setSource(source);
+    doc->parse();
+    doc->check();
+
+    QVERIFY(doc->diagnosticMessages().isEmpty());
+}
+
+void tst_Lookup::templates_5()
+{
+    const QByteArray source = "\n"
+            "struct Point {\n"
+            "    int x,y;\n"
+            "};\n"
+            "\n"
+            "template <typename _Tp>\n"
+            "struct Allocator {\n"
+            "    typedef const _Tp &const_reference;\n"
+            "\n"
+            "    const_reference get();\n"
+            "};\n"
+            "\n"
+            "int main()\n"
+            "{\n"
+            "    Allocator<Point>::const_reference r = pt;\n"
+            "    //r.; // const Point &\n"
+            "\n"
+            "    Allocator<Point> a;\n"
+            "    a.get(); // const Point &\n"
+            "}\n";
+    Document::Ptr doc = Document::create("templates_5");
+    doc->setSource(source);
+    doc->parse();
+    doc->check();
+
+    QVERIFY(doc->diagnosticMessages().isEmpty());
+}
+
 QTEST_APPLESS_MAIN(tst_Lookup)
 #include "tst_lookup.moc"