diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp
index a25d67c60d01e100163231f6eef7eeef7012b2ab..9913d2a2897542c015d40d474467ae26fd8d2db8 100644
--- a/src/plugins/cppeditor/cppeditor.cpp
+++ b/src/plugins/cppeditor/cppeditor.cpp
@@ -1755,6 +1755,9 @@ void CPPEditor::unCommentSelection()
 
 CPPEditor::Link CPPEditor::linkToSymbol(CPlusPlus::Symbol *symbol)
 {
+    if (!symbol)
+        return Link();
+
     const QString fileName = QString::fromUtf8(symbol->fileName(),
                                                symbol->fileNameLength());
     unsigned line = symbol->line();
diff --git a/src/plugins/cppeditor/cppeditor.h b/src/plugins/cppeditor/cppeditor.h
index 40fe6b1e6cc5df9c3bdf8200bcc3860e0dc7a333..994bfacb675f809896cd75b30845581770110934 100644
--- a/src/plugins/cppeditor/cppeditor.h
+++ b/src/plugins/cppeditor/cppeditor.h
@@ -180,6 +180,10 @@ public:
     void setObjCEnabled(bool onoff);
     bool isObjCEnabled() const;
 
+    bool openLink(const Link &link) { return openCppEditorAt(link); }
+
+    static Link linkToSymbol(CPlusPlus::Symbol *symbol);
+
 Q_SIGNALS:
     void outlineModelIndexChanged(const QModelIndex &index);
 
@@ -267,13 +271,10 @@ private:
     void abortRename();
 
     Link findLinkAt(const QTextCursor &, bool resolveTarget = true);
-    bool openLink(const Link &link) { return openCppEditorAt(link); }
     bool openCppEditorAt(const Link &);
 
     QModelIndex indexForPosition(int line, int column, const QModelIndex &rootIndex = QModelIndex()) const;
 
-    static Link linkToSymbol(CPlusPlus::Symbol *symbol);
-
     CppTools::CppModelManagerInterface *m_modelManager;
 
     QComboBox *m_outlineCombo;
diff --git a/src/plugins/cppeditor/cppeditor.pro b/src/plugins/cppeditor/cppeditor.pro
index be74639661a83382bbc9eb0a575ac8fd8c8b1772..4e37070300310c130753b89786f49a27a9d14d9c 100644
--- a/src/plugins/cppeditor/cppeditor.pro
+++ b/src/plugins/cppeditor/cppeditor.pro
@@ -20,8 +20,9 @@ HEADERS += cppplugin.h \
     cppsemanticinfo.h \
     cppoutline.h \
     cppdeclfromdef.h \
-    cpplocalsymbols.h
-
+    cpplocalsymbols.h \
+    cpptypehierarchy.h \
+    cppelementevaluator.h
 SOURCES += cppplugin.cpp \
     cppeditor.cpp \
     cpphighlighter.cpp \
@@ -35,8 +36,9 @@ SOURCES += cppplugin.cpp \
     cppsemanticinfo.cpp \
     cppoutline.cpp \
     cppdeclfromdef.cpp \
-    cpplocalsymbols.cpp
-
+    cpplocalsymbols.cpp \
+    cpptypehierarchy.cpp \
+    cppelementevaluator.cpp
 RESOURCES += cppeditor.qrc
-
-OTHER_FILES += CppEditor.pluginspec CppEditor.mimetypes.xml
+OTHER_FILES += CppEditor.pluginspec \
+    CppEditor.mimetypes.xml
diff --git a/src/plugins/cppeditor/cppeditorconstants.h b/src/plugins/cppeditor/cppeditorconstants.h
index 192cd83df5c9448e45eb09b715d3fac6652b2079..8993e03a28df4f9f19cdc7114da6474940c83c21 100644
--- a/src/plugins/cppeditor/cppeditorconstants.h
+++ b/src/plugins/cppeditor/cppeditorconstants.h
@@ -48,6 +48,9 @@ const char * const FIND_REFERENCES = "CppEditor.FindReferences";
 const char * const JUMP_TO_DEFINITION = "CppEditor.JumpToDefinition";
 const char * const UPDATE_CODEMODEL = "CppEditor.UpdateCodeModel";
 
+const char * const TYPE_HIERARCHY_ID = "CppEditor.TypeHierarchy";
+const char * const OPEN_TYPE_HIERARCHY = "CppEditor.OpenTypeHierarchy";
+
 const char * const HEADER_FILE_TYPE = "CppHeaderFiles";
 const char * const SOURCE_FILE_TYPE = "CppSourceFiles";
 
diff --git a/src/plugins/cppeditor/cppelementevaluator.cpp b/src/plugins/cppeditor/cppelementevaluator.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2902051d6acce4384789306cddc1a7be2e93b02b
--- /dev/null
+++ b/src/plugins/cppeditor/cppelementevaluator.cpp
@@ -0,0 +1,500 @@
+/**************************************************************************
+**
+** 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 "cppelementevaluator.h"
+
+#include <coreplugin/ifile.h>
+#include <cpptools/cppmodelmanagerinterface.h>
+
+#include <FullySpecifiedType.h>
+#include <Names.h>
+#include <CoreTypes.h>
+#include <Scope.h>
+#include <Symbol.h>
+#include <Symbols.h>
+#include <cplusplus/ExpressionUnderCursor.h>
+#include <cplusplus/Overview.h>
+#include <cplusplus/TypeOfExpression.h>
+#include <cplusplus/LookupContext.h>
+#include <cplusplus/LookupItem.h>
+#include <cplusplus/Icons.h>
+
+#include <QtCore/QDir>
+#include <QtCore/QFileInfo>
+#include <QtCore/QSet>
+#include <QtCore/QQueue>
+
+using namespace CppEditor;
+using namespace Internal;
+using namespace CPlusPlus;
+
+namespace {
+    void moveCursorToEndOfName(QTextCursor *tc) {
+        QTextDocument *doc = tc->document();
+        if (!doc)
+            return;
+
+        QChar ch = doc->characterAt(tc->position());
+        while (ch.isLetterOrNumber() || ch == QLatin1Char('_')) {
+            tc->movePosition(QTextCursor::NextCharacter);
+            ch = doc->characterAt(tc->position());
+        }
+    }
+}
+
+CppElementEvaluator::CppElementEvaluator(CPPEditor *editor) :
+    m_editor(editor),
+    m_modelManager(CppTools::CppModelManagerInterface::instance()),
+    m_tc(editor->textCursor()),
+    m_lookupBaseClasses(false)
+{}
+
+void CppElementEvaluator::setTextCursor(const QTextCursor &tc)
+{ m_tc = tc; }
+
+void CppElementEvaluator::setLookupBaseClasses(const bool lookup)
+{ m_lookupBaseClasses = lookup; }
+
+QSharedPointer<CppElement> CppElementEvaluator::identifyCppElement()
+{
+    m_element.clear();
+    evaluate();
+    return m_element;
+}
+
+// @todo: Consider refactoring code from CPPEditor::findLinkAt into here.
+void CppElementEvaluator::evaluate()
+{
+    if (!m_modelManager)
+        return;
+
+    const Snapshot &snapshot = m_modelManager->snapshot();
+    Document::Ptr doc = snapshot.document(m_editor->file()->fileName());
+    if (!doc)
+        return;
+
+    int line = 0;
+    int column = 0;
+    const int pos = m_tc.position();
+    m_editor->convertPosition(pos, &line, &column);
+
+    if (!matchDiagnosticMessage(doc, line)) {
+        if (!matchIncludeFile(doc, line) && !matchMacroInUse(doc, pos)) {
+            moveCursorToEndOfName(&m_tc);
+
+            // Fetch the expression's code
+            ExpressionUnderCursor expressionUnderCursor;
+            const QString &expression = expressionUnderCursor(m_tc);
+            Scope *scope = doc->scopeAt(line, column);
+
+            TypeOfExpression typeOfExpression;
+            typeOfExpression.init(doc, snapshot);
+            const QList<LookupItem> &lookupItems = typeOfExpression(expression, scope);
+            if (lookupItems.isEmpty())
+                return;
+
+            const LookupItem &lookupItem = lookupItems.first(); // ### TODO: select best candidate.
+            handleLookupItemMatch(snapshot, lookupItem, typeOfExpression.context());
+        }
+    }
+}
+
+bool CppElementEvaluator::matchDiagnosticMessage(const CPlusPlus::Document::Ptr &document,
+                                                 unsigned line)
+{
+    foreach (const Document::DiagnosticMessage &m, document->diagnosticMessages()) {
+        if (m.line() == line) {
+            m_element = QSharedPointer<CppElement>(new CppDiagnosis(m));
+            return true;
+        }
+    }
+    return false;
+}
+
+bool CppElementEvaluator::matchIncludeFile(const CPlusPlus::Document::Ptr &document, unsigned line)
+{
+    foreach (const Document::Include &includeFile, document->includes()) {
+        if (includeFile.line() == line) {
+            m_element = QSharedPointer<CppElement>(new CppInclude(includeFile));
+            return true;
+        }
+    }
+    return false;
+}
+
+bool CppElementEvaluator::matchMacroInUse(const CPlusPlus::Document::Ptr &document, unsigned pos)
+{
+    foreach (const Document::MacroUse &use, document->macroUses()) {
+        if (use.contains(pos)) {
+            const unsigned begin = use.begin();
+            const QString &name = use.macro().name();
+            if (pos < begin + name.length()) {
+                m_element = QSharedPointer<CppElement>(new CppMacro(use.macro()));
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+void CppElementEvaluator::handleLookupItemMatch(const Snapshot &snapshot,
+                                                const LookupItem &lookupItem,
+                                                const LookupContext &context)
+{
+    Symbol *declaration = lookupItem.declaration();
+    if (!declaration) {
+        const QString &type = Overview().prettyType(lookupItem.type(), QString());
+        m_element = QSharedPointer<CppElement>(new Unknown(type));
+    } else {
+        const FullySpecifiedType &type = declaration->type();
+        if (declaration->isNamespace()) {
+            m_element = QSharedPointer<CppElement>(new CppNamespace(declaration));
+        } else if (declaration->isClass() || declaration->isForwardClassDeclaration()) {
+            if (declaration->isForwardClassDeclaration())
+                if (Symbol *classDeclaration = snapshot.findMatchingClassDeclaration(declaration))
+                    declaration = classDeclaration;
+            CppClass *cppClass = new CppClass(declaration);
+            if (m_lookupBaseClasses)
+                cppClass->lookupBases(declaration, context);
+            m_element = QSharedPointer<CppElement>(cppClass);
+        } else if (declaration->isEnum() || declaration->scope()->isEnum()) {
+            m_element = QSharedPointer<CppElement>(new CppEnum(declaration));
+        } else if (declaration->isTypedef()) {
+            m_element = QSharedPointer<CppElement>(new CppTypedef(declaration));
+        } else if (declaration->isFunction() || (type.isValid() && type->isFunctionType())) {
+            m_element = QSharedPointer<CppElement>(new CppFunction(declaration));
+        } else if (declaration->isDeclaration() && type.isValid()) {
+            m_element = QSharedPointer<CppElement>(
+                new CppVariable(declaration, context, lookupItem.scope()));
+        } else {
+            m_element = QSharedPointer<CppElement>(new CppDeclarableElement(declaration));
+        }
+    }
+}
+
+// CppElement
+CppElement::CppElement() : m_helpCategory(CppHoverHandler::HelpCandidate::Unknown)
+{}
+
+CppElement::~CppElement()
+{}
+
+void CppElement::setHelpCategory(const CppHoverHandler::HelpCandidate::Category &cat)
+{ m_helpCategory = cat; }
+
+const CppHoverHandler::HelpCandidate::Category &CppElement::helpCategory() const
+{ return m_helpCategory; }
+
+void CppElement::setHelpIdCandidates(const QStringList &candidates)
+{ m_helpIdCandidates = candidates; }
+
+void CppElement::addHelpIdCandidate(const QString &candidate)
+{ m_helpIdCandidates.append(candidate); }
+
+const QStringList &CppElement::helpIdCandidates() const
+{ return m_helpIdCandidates; }
+
+void CppElement::setHelpMark(const QString &mark)
+{ m_helpMark = mark; }
+
+const QString &CppElement::helpMark() const
+{ return m_helpMark; }
+
+void CppElement::setLink(const CPPEditor::Link &link)
+{ m_link = link; }
+
+const CPPEditor::Link &CppElement::link() const
+{ return m_link; }
+
+void CppElement::setTooltip(const QString &tooltip)
+{ m_tooltip = tooltip; }
+
+const QString &CppElement::tooltip() const
+{ return m_tooltip; }
+
+
+// Unknown
+Unknown::Unknown(const QString &type) : CppElement(), m_type(type)
+{
+    setTooltip(m_type);
+}
+
+Unknown::~Unknown()
+{}
+
+const QString &Unknown::type() const
+{ return m_type; }
+
+// CppDiagnosis
+CppDiagnosis::CppDiagnosis(const Document::DiagnosticMessage &message) :
+    CppElement(), m_text(message.text())
+{
+    setTooltip(m_text);
+}
+
+CppDiagnosis::~CppDiagnosis()
+{}
+
+const QString &CppDiagnosis::text() const
+{ return m_text; }
+
+// CppInclude
+CppInclude::~CppInclude()
+{}
+
+CppInclude::CppInclude(const Document::Include &includeFile) :
+    CppElement(),
+    m_path(QDir::toNativeSeparators(includeFile.fileName())),
+    m_fileName(QFileInfo(includeFile.fileName()).fileName())
+{
+    setHelpCategory(CppHoverHandler::HelpCandidate::Brief);
+    setHelpIdCandidates(QStringList(m_fileName));
+    setHelpMark(m_fileName);
+    setLink(CPPEditor::Link(m_path));
+    setTooltip(m_path);
+}
+
+const QString &CppInclude::path() const
+{ return m_path; }
+
+const QString &CppInclude::fileName() const
+{ return m_fileName; }
+
+// CppMacro
+CppMacro::CppMacro(const Macro &macro) : CppElement()
+{
+    setHelpCategory(CppHoverHandler::HelpCandidate::Macro);
+    setHelpIdCandidates(QStringList(macro.name()));
+    setHelpMark(macro.name());
+    setLink(CPPEditor::Link(macro.fileName(), macro.line()));
+    setTooltip(macro.toString());
+}
+
+CppMacro::~CppMacro()
+{}
+
+// CppDeclarableElement
+CppDeclarableElement::CppDeclarableElement(Symbol *declaration) : CppElement()
+{
+    const FullySpecifiedType &type = declaration->type();
+
+    Overview overview;
+    overview.setShowArgumentNames(true);
+    overview.setShowReturnTypes(true);
+
+    m_icon = Icons().iconForSymbol(declaration);
+    m_name = overview.prettyName(declaration->name());
+    if (declaration->scope()->isClass() ||
+        declaration->scope()->isNamespace() ||
+        declaration->scope()->isEnum()) {
+        m_qualifiedName = overview.prettyName(LookupContext::fullyQualifiedName(declaration));
+    } else {
+        m_qualifiedName = m_name;
+    }
+
+    if (declaration->isClass() ||
+        declaration->isNamespace() ||
+        declaration->isForwardClassDeclaration() ||
+        declaration->isEnum()) {
+        m_type = m_qualifiedName;
+    } else {
+        m_type = overview.prettyType(type, m_qualifiedName);
+    }
+
+    setTooltip(m_type);
+    setLink(CPPEditor::linkToSymbol(declaration));
+
+    QStringList helpIds;
+    helpIds << m_name << m_qualifiedName;
+    setHelpIdCandidates(helpIds);
+    setHelpMark(m_name);
+}
+
+CppDeclarableElement::~CppDeclarableElement()
+{}
+
+void CppDeclarableElement::setName(const QString &name)
+{ m_name = name; }
+
+const QString &CppDeclarableElement::name() const
+{ return m_name; }
+
+void CppDeclarableElement::setQualifiedName(const QString &name)
+{ m_qualifiedName = name; }
+
+const QString &CppDeclarableElement::qualifiedName() const
+{ return m_qualifiedName; }
+
+void CppDeclarableElement::setType(const QString &type)
+{ m_type = type; }
+
+const QString &CppDeclarableElement::type() const
+{ return m_type; }
+
+void CppDeclarableElement::setIcon(const QIcon &icon)
+{ m_icon = icon; }
+
+const QIcon &CppDeclarableElement::icon() const
+{ return m_icon; }
+
+// CppNamespace
+CppNamespace::CppNamespace(Symbol *declaration) : CppDeclarableElement(declaration)
+{
+    setHelpCategory(CppHoverHandler::HelpCandidate::ClassOrNamespace);
+}
+
+CppNamespace::~CppNamespace()
+{}
+
+// CppClass
+CppClass::CppClass(Symbol *declaration) : CppDeclarableElement(declaration)
+{
+    setHelpCategory(CppHoverHandler::HelpCandidate::ClassOrNamespace);
+}
+
+CppClass::~CppClass()
+{}
+
+void CppClass::lookupBases(Symbol *declaration, const CPlusPlus::LookupContext &context)
+{
+    typedef QPair<ClassOrNamespace *, CppClass *> Data;
+
+    if (ClassOrNamespace *clazz = context.lookupType(declaration)) {
+        QSet<ClassOrNamespace *> visited;
+
+        QQueue<Data> q;
+        q.enqueue(qMakePair(clazz, this));
+        while (!q.isEmpty()) {
+            Data current = q.dequeue();
+            clazz = current.first;
+            visited.insert(clazz);
+            const QList<ClassOrNamespace *> &bases = clazz->usings();
+            foreach (ClassOrNamespace *baseClass, bases) {
+                const QList<Symbol *> &symbols = baseClass->symbols();
+                foreach (Symbol *symbol, symbols) {
+                    if (symbol->isClass() && (
+                        clazz = context.lookupType(symbol)) &&
+                        !visited.contains(clazz)) {
+                        CppClass baseCppClass(symbol);
+                        CppClass *cppClass = current.second;
+                        cppClass->m_bases.append(baseCppClass);
+                        q.enqueue(qMakePair(clazz, &cppClass->m_bases.last()));
+                    }
+                }
+            }
+        }
+    }
+}
+
+const QList<CppClass> &CppClass::bases() const
+{ return m_bases; }
+
+// CppFunction
+CppFunction::CppFunction(Symbol *declaration) : CppDeclarableElement(declaration)
+{
+    setHelpCategory(CppHoverHandler::HelpCandidate::Function);
+
+    const FullySpecifiedType &type = declaration->type();
+
+    // Functions marks can be found either by the main overload or signature based
+    // (with no argument names and no return). Help ids have no signature at all.
+    Overview overview;
+    overview.setShowDefaultArguments(false);
+    setHelpMark(overview.prettyType(type, name()));
+
+    overview.setShowFunctionSignatures(false);
+    addHelpIdCandidate(overview.prettyName(declaration->name()));
+}
+
+CppFunction::~CppFunction()
+{}
+
+// CppEnum
+CppEnum::CppEnum(Symbol *declaration) : CppDeclarableElement(declaration)
+{
+    setHelpCategory(CppHoverHandler::HelpCandidate::Enum);
+
+    if (declaration->scope()->isEnum()) {
+        Symbol *enumSymbol = declaration->scope()->asEnum();
+        Overview overview;
+        setHelpMark(overview.prettyName(enumSymbol->name()));
+        setTooltip(overview.prettyName(LookupContext::fullyQualifiedName(enumSymbol)));
+    }
+}
+
+CppEnum::~CppEnum()
+{}
+
+// CppTypedef
+CppTypedef::CppTypedef(Symbol *declaration) :
+    CppDeclarableElement(declaration)
+{
+    setHelpCategory(CppHoverHandler::HelpCandidate::Typedef);
+}
+
+CppTypedef::~CppTypedef()
+{}
+
+// CppVariable
+CppVariable::CppVariable(Symbol *declaration, const LookupContext &context, Scope *scope) :
+    CppDeclarableElement(declaration)
+{
+    const FullySpecifiedType &type = declaration->type();
+
+    const Name *typeName = 0;
+    if (type->isNamedType()) {
+        typeName = type->asNamedType()->name();
+    } else if (type->isPointerType() || type->isReferenceType()) {
+        FullySpecifiedType associatedType;
+        if (type->isPointerType())
+            associatedType = type->asPointerType()->elementType();
+        else
+            associatedType = type->asReferenceType()->elementType();
+        if (associatedType->isNamedType())
+            typeName = associatedType->asNamedType()->name();
+    }
+
+    if (typeName) {
+        if (ClassOrNamespace *clazz = context.lookupType(typeName, scope)) {
+            if (!clazz->symbols().isEmpty()) {
+                Overview overview;
+                Symbol *symbol = clazz->symbols().at(0);
+                const QString &name =
+                    overview.prettyName(LookupContext::fullyQualifiedName(symbol));
+                setTooltip(name);
+                setHelpCategory(CppHoverHandler::HelpCandidate::ClassOrNamespace);
+                setHelpMark(name);
+                setHelpIdCandidates(QStringList(name));
+            }
+        }
+    }
+}
+
+CppVariable::~CppVariable()
+{}
diff --git a/src/plugins/cppeditor/cppelementevaluator.h b/src/plugins/cppeditor/cppelementevaluator.h
new file mode 100644
index 0000000000000000000000000000000000000000..92a454877b25786d682c95668f29ac39ba66f5f6
--- /dev/null
+++ b/src/plugins/cppeditor/cppelementevaluator.h
@@ -0,0 +1,238 @@
+/**************************************************************************
+**
+** 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 CPPHIGHLEVELMODEL_H
+#define CPPHIGHLEVELMODEL_H
+
+#include "cppeditor.h"
+#include "cpphoverhandler.h"
+
+#include <cplusplus/CppDocument.h>
+#include <cplusplus/Overview.h>
+
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtCore/QSharedPointer>
+#include <QtGui/QTextCursor>
+#include <QtGui/QIcon>
+
+namespace CPlusPlus {
+class LookupItem;
+class LookupContext;
+}
+
+namespace CppTools {
+class CppModelManagerInterface;
+}
+
+namespace CppEditor {
+namespace Internal {
+
+class CPPEditor;
+class CppElement;
+
+class CppElementEvaluator
+{
+public:
+    CppElementEvaluator(CPPEditor *editor);
+
+    void setTextCursor(const QTextCursor &tc);
+    void setLookupBaseClasses(const bool lookup);
+
+    QSharedPointer<CppElement> identifyCppElement();
+
+private:
+    void evaluate();
+    bool matchDiagnosticMessage(const CPlusPlus::Document::Ptr &document, unsigned line);
+    bool matchIncludeFile(const CPlusPlus::Document::Ptr &document, unsigned line);
+    bool matchMacroInUse(const CPlusPlus::Document::Ptr &document, unsigned pos);
+    void handleLookupItemMatch(const CPlusPlus::Snapshot &snapshot,
+                               const CPlusPlus::LookupItem &lookupItem,
+                               const CPlusPlus::LookupContext &lookupContext);
+
+    CPPEditor *m_editor;
+    CppTools::CppModelManagerInterface *m_modelManager;
+    QTextCursor m_tc;
+    bool m_lookupBaseClasses;
+    QSharedPointer<CppElement> m_element;
+};
+
+class CppElement
+{
+public:
+    virtual ~CppElement();
+
+    const CppHoverHandler::HelpCandidate::Category &helpCategory() const;
+    const QStringList &helpIdCandidates() const;
+    const QString &helpMark() const;
+    const CPPEditor::Link &link() const;
+    const QString &tooltip() const;
+
+protected:
+    CppElement();
+
+    void setHelpCategory(const CppHoverHandler::HelpCandidate::Category &category);
+    void setLink(const CPPEditor::Link &link);
+    void setTooltip(const QString &tooltip);
+    void setHelpIdCandidates(const QStringList &candidates);
+    void addHelpIdCandidate(const QString &candidate);
+    void setHelpMark(const QString &mark);
+
+private:
+    CppHoverHandler::HelpCandidate::Category m_helpCategory;
+    QStringList m_helpIdCandidates;
+    QString m_helpMark;
+    CPPEditor::Link m_link;
+    QString m_tooltip;
+};
+
+class Unknown : public CppElement
+{
+public:
+    Unknown(const QString &type);
+    virtual ~Unknown();
+
+    const QString &type() const;
+
+private:
+    QString m_type;
+};
+
+class CppDiagnosis : public CppElement
+{
+public:
+    CppDiagnosis(const CPlusPlus::Document::DiagnosticMessage &message);
+    virtual ~CppDiagnosis();
+
+    const QString &text() const;
+
+private:
+    QString m_text;
+};
+
+class CppInclude : public CppElement
+{
+public:
+    CppInclude(const CPlusPlus::Document::Include &includeFile);
+    virtual ~CppInclude();
+
+    const QString &path() const;
+    const QString &fileName() const;
+
+private:
+    QString m_path;
+    QString m_fileName;
+};
+
+class CppMacro : public CppElement
+{
+public:
+    CppMacro(const CPlusPlus::Macro &macro);
+    virtual ~CppMacro();
+};
+
+class CppDeclarableElement : public CppElement
+{
+public:
+    CppDeclarableElement(CPlusPlus::Symbol *declaration);
+    virtual ~CppDeclarableElement();
+
+    const QString &name() const;
+    const QString &qualifiedName() const;
+    const QString &type() const;
+    const QIcon &icon() const;
+
+protected:
+    void setName(const QString &name);
+    void setQualifiedName(const QString &name);
+    void setType(const QString &type);
+    void setIcon(const QIcon &icon);
+
+private:
+    QString m_name;
+    QString m_qualifiedName;
+    QString m_type;
+    QIcon m_icon;
+};
+
+class CppNamespace : public CppDeclarableElement
+{
+public:
+    CppNamespace(CPlusPlus::Symbol *declaration);
+    virtual ~CppNamespace();
+};
+
+class CppClass : public CppDeclarableElement
+{
+public:
+    CppClass(CPlusPlus::Symbol *declaration);
+    virtual ~CppClass();
+
+    void lookupBases(CPlusPlus::Symbol *declaration, const CPlusPlus::LookupContext &context);
+
+    const QList<CppClass> &bases() const;
+
+private:
+    QList<CppClass> m_bases;
+};
+
+class CppFunction : public CppDeclarableElement
+{
+public:
+    CppFunction(CPlusPlus::Symbol *declaration);
+    virtual ~CppFunction();
+};
+
+class CppEnum : public CppDeclarableElement
+{
+public:
+    CppEnum(CPlusPlus::Symbol *declaration);
+    virtual ~CppEnum();
+};
+
+class CppTypedef : public CppDeclarableElement
+{
+public:
+    CppTypedef(CPlusPlus::Symbol *declaration);
+    virtual ~CppTypedef();
+};
+
+class CppVariable : public CppDeclarableElement
+{
+public:
+    CppVariable(CPlusPlus::Symbol *declaration,
+                const CPlusPlus::LookupContext &context,
+                CPlusPlus::Scope *scope);
+    virtual ~CppVariable();
+};
+
+} // namespace Internal
+} // namespace CppEditor
+
+#endif // CPPHIGHLEVELMODEL_H
diff --git a/src/plugins/cppeditor/cpphoverhandler.cpp b/src/plugins/cppeditor/cpphoverhandler.cpp
index 0d4d24241b7a65f562c12d3e92e0040fe11b9a54..15922d906ed9d780ddf276709e23e048027eaffe 100644
--- a/src/plugins/cppeditor/cpphoverhandler.cpp
+++ b/src/plugins/cppeditor/cpphoverhandler.cpp
@@ -29,6 +29,7 @@
 
 #include "cpphoverhandler.h"
 #include "cppeditor.h"
+#include "cppelementevaluator.h"
 
 #include <coreplugin/editormanager/ieditor.h>
 #include <coreplugin/editormanager/editormanager.h>
@@ -37,29 +38,9 @@
 #include <texteditor/itexteditor.h>
 #include <texteditor/basetexteditor.h>
 
-#include <FullySpecifiedType.h>
-#include <Names.h>
-#include <CoreTypes.h>
-#include <Scope.h>
-#include <Symbol.h>
-#include <Symbols.h>
-#include <cplusplus/ExpressionUnderCursor.h>
-#include <cplusplus/Overview.h>
-#include <cplusplus/TypeOfExpression.h>
-#include <cplusplus/LookupContext.h>
-#include <cplusplus/LookupItem.h>
-
-#include <QtCore/QSet>
-#include <QtCore/QDir>
-#include <QtCore/QFileInfo>
-#include <QtCore/QtAlgorithms>
-#include <QtCore/QStringBuilder>
 #include <QtGui/QTextCursor>
 
-#include <algorithm>
-
 using namespace CppEditor::Internal;
-using namespace CPlusPlus;
 using namespace Core;
 
 namespace {
@@ -70,73 +51,13 @@ namespace {
         else
             return name.right(name.length() - index - 1);
     }
-
-    void moveCursorToEndOfName(QTextCursor *tc) {
-        QTextDocument *doc = tc->document();
-        if (!doc)
-            return;
-
-        QChar ch = doc->characterAt(tc->position());
-        while (ch.isLetterOrNumber() || ch == QLatin1Char('_')) {
-            tc->movePosition(QTextCursor::NextCharacter);
-            ch = doc->characterAt(tc->position());
-        }
-    }
-
-    void buildClassHierarchyHelper(ClassOrNamespace *classSymbol,
-                                   const LookupContext &context,
-                                   const Overview &overview,
-                                   QList<QStringList> *hierarchy,
-                                   QSet<ClassOrNamespace *> *visited) {
-        visited->insert(classSymbol);
-        const QList<ClassOrNamespace *> &bases = classSymbol->usings();
-        foreach (ClassOrNamespace *baseClass, bases) {
-            const QList<Symbol *> &symbols = baseClass->symbols();
-            foreach (Symbol *baseSymbol, symbols) {
-                if (baseSymbol->isClass() && (
-                    classSymbol = context.lookupType(baseSymbol)) &&
-                    !visited->contains(classSymbol)) {
-                    const QString &qualifiedName = overview.prettyName(
-                            LookupContext::fullyQualifiedName(baseSymbol));
-                    if (!qualifiedName.isEmpty()) {
-                        hierarchy->back().append(qualifiedName);
-                        buildClassHierarchyHelper(classSymbol,
-                                                  context,
-                                                  overview,
-                                                  hierarchy,
-                                                  visited);
-                        hierarchy->append(hierarchy->back());
-                        hierarchy->back().removeLast();
-                    }
-                }
-            }
-        }
-    }
-
-    void buildClassHierarchy(Symbol *symbol,
-                             const LookupContext &context,
-                             const Overview &overview,
-                             QList<QStringList> *hierarchy) {
-        if (ClassOrNamespace *classSymbol = context.lookupType(symbol)) {
-            hierarchy->append(QStringList());
-            QSet<ClassOrNamespace *> visited;
-            buildClassHierarchyHelper(classSymbol, context, overview, hierarchy, &visited);
-            hierarchy->removeLast();
-        }
-    }
-
-    struct ClassHierarchyComp
-    {
-        bool operator()(const QStringList &a, const QStringList &b)
-        { return a.size() < b.size(); }
-    };
 }
 
-CppHoverHandler::CppHoverHandler(QObject *parent) : BaseHoverHandler(parent), m_modelManager(0)
-{
-    m_modelManager =
-        ExtensionSystem::PluginManager::instance()->getObject<CppTools::CppModelManagerInterface>();
-}
+CppHoverHandler::CppHoverHandler(QObject *parent) : BaseHoverHandler(parent)
+{}
+
+CppHoverHandler::~CppHoverHandler()
+{}
 
 bool CppHoverHandler::acceptEditor(IEditor *editor)
 {
@@ -148,191 +69,25 @@ bool CppHoverHandler::acceptEditor(IEditor *editor)
 
 void CppHoverHandler::identifyMatch(TextEditor::ITextEditor *editor, int pos)
 {
-    if (!m_modelManager)
-        return;
-
-    const Snapshot &snapshot = m_modelManager->snapshot();
-    Document::Ptr doc = snapshot.document(editor->file()->fileName());
-    if (!doc)
+    CPPEditor *cppEditor = qobject_cast<CPPEditor *>(editor->widget());
+    if (!cppEditor)
         return;
 
-    int line = 0;
-    int column = 0;
-    editor->convertPosition(pos, &line, &column);
-
-    if (!matchDiagnosticMessage(doc, line)) {
-        if (!matchIncludeFile(doc, line) && !matchMacroInUse(doc, pos)) {
-            TextEditor::BaseTextEditor *baseEditor = baseTextEditor(editor);
-            if (!baseEditor)
-                return;
-
-            bool extraSelectionTooltip = false;
-            if (!baseEditor->extraSelectionTooltip(pos).isEmpty()) {
-                setToolTip(baseEditor->extraSelectionTooltip(pos));
-                extraSelectionTooltip = true;
-            }
-
-            QTextCursor tc(baseEditor->document());
-            tc.setPosition(pos);
-            moveCursorToEndOfName(&tc);
-
-            // Fetch the expression's code
-            ExpressionUnderCursor expressionUnderCursor;
-            const QString &expression = expressionUnderCursor(tc);
-            Scope *scope = doc->scopeAt(line, column);
-
-            TypeOfExpression typeOfExpression;
-            typeOfExpression.init(doc, snapshot);
-            const QList<LookupItem> &lookupItems = typeOfExpression(expression, scope);
-            if (lookupItems.isEmpty())
-                return;
-
-            const LookupItem &lookupItem = lookupItems.first(); // ### TODO: select best candidate.
-            handleLookupItemMatch(lookupItem, typeOfExpression.context(), !extraSelectionTooltip);
-        }
-    }
-}
-
-bool CppHoverHandler::matchDiagnosticMessage(const CPlusPlus::Document::Ptr &document,
-                                             unsigned line)
-{
-    foreach (const Document::DiagnosticMessage &m, document->diagnosticMessages()) {
-        if (m.line() == line) {
-            setToolTip(m.text());
-            return true;
-        }
-    }
-    return false;
-}
-
-bool CppHoverHandler::matchIncludeFile(const CPlusPlus::Document::Ptr &document, unsigned line)
-{
-    foreach (const Document::Include &includeFile, document->includes()) {
-        if (includeFile.line() == line) {
-            setToolTip(QDir::toNativeSeparators(includeFile.fileName()));
-            const QString &fileName = QFileInfo(includeFile.fileName()).fileName();
-            addHelpCandidate(HelpCandidate(fileName, fileName, HelpCandidate::Brief));
-            return true;
-        }
-    }
-    return false;
-}
-
-bool CppHoverHandler::matchMacroInUse(const CPlusPlus::Document::Ptr &document, unsigned pos)
-{
-    foreach (const Document::MacroUse &use, document->macroUses()) {
-        if (use.contains(pos)) {
-            const unsigned begin = use.begin();
-            const QString &name = use.macro().name();
-            if (pos < begin + name.length()) {
-                setToolTip(use.macro().toString());
-                addHelpCandidate(HelpCandidate(name, name, HelpCandidate::Macro));
-                return true;
-            }
-        }
-    }
-    return false;
-}
-
-void CppHoverHandler::handleLookupItemMatch(const LookupItem &lookupItem,
-                                            const LookupContext &context,
-                                            const bool assignTooltip)
-{
-    Symbol *matchingDeclaration = lookupItem.declaration();
-    FullySpecifiedType matchingType = lookupItem.type();
-
-    Overview overview;
-    overview.setShowArgumentNames(true);
-    overview.setShowReturnTypes(true);
-
-    if (!matchingDeclaration && assignTooltip) {
-        setToolTip(overview.prettyType(matchingType, QString()));
+    if (!cppEditor->extraSelectionTooltip(pos).isEmpty()) {
+        setToolTip(cppEditor->extraSelectionTooltip(pos));
     } else {
-        QString name;
-        if (matchingDeclaration->scope()->isClass() ||
-            matchingDeclaration->scope()->isNamespace() ||
-            matchingDeclaration->scope()->isEnum()) {
-            name.append(overview.prettyName(
-                LookupContext::fullyQualifiedName(matchingDeclaration)));
-
-            if (matchingDeclaration->isClass() ||
-                matchingDeclaration->isForwardClassDeclaration()) {
-                buildClassHierarchy(matchingDeclaration, context, overview, &m_classHierarchy);
-            }
-        } else {
-            name.append(overview.prettyName(matchingDeclaration->name()));
-        }
-
-        if (assignTooltip) {
-            if (matchingDeclaration->isClass() ||
-                matchingDeclaration->isNamespace() ||
-                matchingDeclaration->isForwardClassDeclaration() ||
-                matchingDeclaration->isEnum()) {
-                setToolTip(name);
-            } else {
-                setToolTip(overview.prettyType(matchingType, name));
-            }
-        }
-
-        HelpCandidate::Category helpCategory = HelpCandidate::Unknown;
-        if (matchingDeclaration->isNamespace() ||
-            matchingDeclaration->isClass() ||
-            matchingDeclaration->isForwardClassDeclaration()) {
-            helpCategory = HelpCandidate::ClassOrNamespace;
-        } else if (matchingDeclaration->isEnum() ||
-                   matchingDeclaration->scope()->isEnum()) {
-            helpCategory = HelpCandidate::Enum;
-        } else if (matchingDeclaration->isTypedef()) {
-            helpCategory = HelpCandidate::Typedef;
-        } else if (matchingDeclaration->isFunction() ||
-                  (matchingType.isValid() && matchingType->isFunctionType())){
-            helpCategory = HelpCandidate::Function;
-        } else if (matchingDeclaration->isDeclaration() && matchingType.isValid()) {
-            const Name *typeName = 0;
-            if (matchingType->isNamedType()) {
-                typeName = matchingType->asNamedType()->name();
-            } else if (matchingType->isPointerType() || matchingType->isReferenceType()) {
-                FullySpecifiedType type;
-                if (matchingType->isPointerType())
-                    type = matchingType->asPointerType()->elementType();
-                else
-                    type = matchingType->asReferenceType()->elementType();
-                if (type->isNamedType())
-                    typeName = type->asNamedType()->name();
-            }
-
-            if (typeName) {
-                if (ClassOrNamespace *clazz = context.lookupType(typeName, lookupItem.scope())) {
-                    if (!clazz->symbols().isEmpty()) {
-                        Symbol *symbol = clazz->symbols().at(0);
-                        matchingDeclaration = symbol;
-                        name = overview.prettyName(LookupContext::fullyQualifiedName(symbol));
-                        setToolTip(name);
-                        buildClassHierarchy(symbol, context, overview, &m_classHierarchy);
-                        helpCategory = HelpCandidate::ClassOrNamespace;
-                    }
-                }
-            }
-        }
-
-        if (helpCategory != HelpCandidate::Unknown) {
-            QString docMark = overview.prettyName(matchingDeclaration->name());
-
-            if (matchingType.isValid() && matchingType->isFunctionType()) {
-                // Functions marks can be found either by the main overload or signature based
-                // (with no argument names and no return). Help ids have no signature at all.
-                overview.setShowArgumentNames(false);
-                overview.setShowReturnTypes(false);
-                docMark = overview.prettyType(matchingType, docMark);
-                overview.setShowFunctionSignatures(false);
-                const QString &functionName = overview.prettyName(matchingDeclaration->name());
-                addHelpCandidate(HelpCandidate(functionName, docMark, helpCategory));
-            } else if (matchingDeclaration->scope()->isEnum()) {
-                Symbol *enumSymbol = matchingDeclaration->scope()->asEnum();
-                docMark = overview.prettyName(enumSymbol->name());
-            }
-
-            addHelpCandidate(HelpCandidate(name, docMark, helpCategory));
+        QTextCursor tc(cppEditor->document());
+        tc.setPosition(pos);
+
+        CppElementEvaluator evaluator(cppEditor);
+        evaluator.setTextCursor(tc);
+        QSharedPointer<CppElement> cppElement = evaluator.identifyCppElement();
+        if (!cppElement.isNull()) {
+            setToolTip(cppElement->tooltip());
+            foreach (const QString &helpId, cppElement->helpIdCandidates())
+                addHelpCandidate(HelpCandidate(helpId,
+                                               cppElement->helpMark(),
+                                               cppElement->helpCategory()));
         }
     }
 }
@@ -356,122 +111,9 @@ void CppHoverHandler::evaluateHelpCandidates()
 }
 
 void CppHoverHandler::decorateToolTip(TextEditor::ITextEditor *editor)
-{
-    if (!m_classHierarchy.isEmpty())
-        generateDiagramTooltip(extendToolTips(editor));
-    else
-        generateNormalTooltip(extendToolTips(editor));
-}
-
-void CppHoverHandler::generateDiagramTooltip(const bool extendTooltips)
-{
-    QString clazz = toolTip();
-
-    qSort(m_classHierarchy.begin(), m_classHierarchy.end(), ClassHierarchyComp());
-
-    // Remove duplicates (in case there are any).
-    m_classHierarchy.erase(std::unique(m_classHierarchy.begin(), m_classHierarchy.end()),
-                           m_classHierarchy.end());
-
-    QStringList directBaseClasses;
-    foreach (const QStringList &hierarchy, m_classHierarchy) {
-        if (hierarchy.size() > 1)
-            break;
-        directBaseClasses.append(hierarchy.at(0));
-    }
-
-    QString diagram(QLatin1String("<table>"));
-    for (int i = 0; i < directBaseClasses.size(); ++i) {
-        if (i == 0) {
-            diagram.append(QString(
-                "<tr><td>%1</td><td>"
-                "<img src=\":/cppeditor/images/rightarrow.png\"></td>"
-                "<td>%2</td></tr>").arg(toolTip()).arg(directBaseClasses.at(i)));
-        } else {
-            diagram.append(QString(
-                "<tr><td></td><td>"
-                "<img src=\":/cppeditor/images/larrow.png\"></td>"
-                "<td>%1</td></tr>").arg(directBaseClasses.at(i)));
-        }
-    }
-    diagram.append(QLatin1String("</table>"));
-    setToolTip(diagram);
-
-    if (matchingHelpCandidate() != -1) {
-        appendToolTip(getDocContents(extendTooltips));
-    } else {
-        // Look for documented base classes. Diagram the nearest one or the nearest ones (in
-        // the case there are many at the same level).
-        int helpLevel = 0;
-        QList<int> baseClassesWithHelp;
-        for (int i = 0; i < m_classHierarchy.size(); ++i) {
-            const QStringList &hierarchy = m_classHierarchy.at(i);
-            if (helpLevel != 0 && hierarchy.size() != helpLevel)
-                break;
-
-            bool exists = false;
-            QString name = hierarchy.last();
-            if (helpIdExists(name)) {
-                exists = true;
-            } else {
-                name = removeClassNameQualification(name);
-                if (helpIdExists(name)) {
-                    exists = true;
-                    m_classHierarchy[i].last() = name;
-                }
-            }
-            if (exists) {
-                baseClassesWithHelp.append(i);
-                if (helpLevel == 0)
-                    helpLevel = hierarchy.size();
-            }
-        }
-
-        if (!baseClassesWithHelp.isEmpty()) {
-            // Choose the first one as the help match.
-            QString base = m_classHierarchy.at(baseClassesWithHelp.at(0)).last();
-            HelpCandidate help(base, base, HelpCandidate::ClassOrNamespace);
-            addHelpCandidate(help);
-            setMatchingHelpCandidate(helpCandidates().size() - 1);
-
-            if (baseClassesWithHelp.size() == 1 && helpLevel == 1) {
-                appendToolTip(getDocContents(help, extendTooltips));
-            } else {
-                foreach (int hierarchyIndex, baseClassesWithHelp) {
-                    appendToolTip(QLatin1String("<p>"));
-                    const QStringList &hierarchy = m_classHierarchy.at(hierarchyIndex);
-                    Q_ASSERT(helpLevel <= hierarchy.size());
-
-                    // Following contents are inside tables so they are on the exact same
-                    // alignment as the top level diagram.
-                    diagram = QString(QLatin1String("<table><tr><td>%1</td>")).arg(clazz);
-                    for (int i = 0; i < helpLevel; ++i) {
-                        diagram.append(
-                            QLatin1String("<td><img src=\":/cppeditor/images/rightarrow.png\">"
-                                          "</td><td>") %
-                            hierarchy.at(i) %
-                            QLatin1String("</td>"));
-                    }
-                    diagram.append(QLatin1String("</tr></table>"));
-
-                    base = hierarchy.at(helpLevel - 1);
-                    const QString &contents =
-                        getDocContents(HelpCandidate(base, base, HelpCandidate::Brief), false);
-                    if (!contents.isEmpty()) {
-                        appendToolTip(diagram % QLatin1String("<table><tr><td>") %
-                                      contents % QLatin1String("</td></tr></table>"));
-                    }
-                    appendToolTip(QLatin1String("</p>"));
-                }
-            }
-        }
-    }
-}
-
-void CppHoverHandler::generateNormalTooltip(const bool extendTooltips)
 {
     if (matchingHelpCandidate() != -1) {
-        const QString &contents = getDocContents(extendTooltips);
+        const QString &contents = getDocContents(extendToolTips(editor));
         if (!contents.isEmpty()) {
             HelpCandidate::Category cat = helpCandidate(matchingHelpCandidate()).m_category;
             if (cat == HelpCandidate::ClassOrNamespace)
@@ -486,8 +128,3 @@ void CppHoverHandler::generateNormalTooltip(const bool extendTooltips)
         }
     }
 }
-
-void CppHoverHandler::resetExtras()
-{
-    m_classHierarchy.clear();
-}
diff --git a/src/plugins/cppeditor/cpphoverhandler.h b/src/plugins/cppeditor/cpphoverhandler.h
index 1fab49b1d2e06658b23a81f3435745e97f02c394..6c7de5cd1fb0e16890968bdf24460f48823ae29f 100644
--- a/src/plugins/cppeditor/cpphoverhandler.h
+++ b/src/plugins/cppeditor/cpphoverhandler.h
@@ -30,26 +30,14 @@
 #ifndef CPPHOVERHANDLER_H
 #define CPPHOVERHANDLER_H
 
-#include <cplusplus/CppDocument.h>
 #include <texteditor/basehoverhandler.h>
 
 #include <QtCore/QObject>
-#include <QtCore/QList>
-#include <QtCore/QStringList>
-
-namespace CPlusPlus {
-class LookupItem;
-class LookupContext;
-}
 
 namespace Core {
 class IEditor;
 }
 
-namespace CppTools {
-class CppModelManagerInterface;
-}
-
 namespace TextEditor {
 class ITextEditor;
 }
@@ -62,26 +50,13 @@ class CppHoverHandler : public TextEditor::BaseHoverHandler
     Q_OBJECT
 public:
     CppHoverHandler(QObject *parent = 0);
+    virtual ~CppHoverHandler();
 
 private:
     virtual bool acceptEditor(Core::IEditor *editor);
     virtual void identifyMatch(TextEditor::ITextEditor *editor, int pos);
-    virtual void resetExtras();
     virtual void evaluateHelpCandidates();
     virtual void decorateToolTip(TextEditor::ITextEditor *editor);
-
-    bool matchDiagnosticMessage(const CPlusPlus::Document::Ptr &document, unsigned line);
-    bool matchIncludeFile(const CPlusPlus::Document::Ptr &document, unsigned line);
-    bool matchMacroInUse(const CPlusPlus::Document::Ptr &document, unsigned pos);
-    void handleLookupItemMatch(const CPlusPlus::LookupItem &lookupItem,
-                               const CPlusPlus::LookupContext &lookupContext,
-                               const bool assignTooltip);
-
-    void generateDiagramTooltip(const bool extendTooltips);
-    void generateNormalTooltip(const bool extendTooltips);
-
-    CppTools::CppModelManagerInterface *m_modelManager;
-    QList<QStringList> m_classHierarchy;
 };
 
 } // namespace Internal
diff --git a/src/plugins/cppeditor/cppplugin.cpp b/src/plugins/cppeditor/cppplugin.cpp
index b43bdd980bbd7d4d947e1131a492631bfbdc4568..858d2b7606dd17d0c4c1cea6599af7eda6d2ba89 100644
--- a/src/plugins/cppeditor/cppplugin.cpp
+++ b/src/plugins/cppeditor/cppplugin.cpp
@@ -36,6 +36,7 @@
 #include "cpphoverhandler.h"
 #include "cppquickfix.h"
 #include "cppoutline.h"
+#include "cpptypehierarchy.h"
 
 #include <coreplugin/icore.h>
 #include <coreplugin/coreconstants.h>
@@ -46,6 +47,7 @@
 #include <coreplugin/actionmanager/command.h>
 #include <coreplugin/editormanager/editormanager.h>
 #include <coreplugin/progressmanager/progressmanager.h>
+#include <coreplugin/navigationwidget.h>
 #include <texteditor/completionsupport.h>
 #include <texteditor/fontsettings.h>
 #include <texteditor/storagesettings.h>
@@ -60,6 +62,7 @@
 #include <QtCore/QSettings>
 #include <QtCore/QTimer>
 #include <QtCore/QCoreApplication>
+#include <QtCore/QStringList>
 
 #include <QtGui/QMenu>
 
@@ -139,8 +142,8 @@ CppPlugin::CppPlugin() :
     m_sortedOutline(false),
     m_renameSymbolUnderCursorAction(0),
     m_findUsagesAction(0),
-    m_updateCodeModelAction(0)
-
+    m_updateCodeModelAction(0),
+    m_openTypeHierarchyAction(0)
 {
     m_instance = this;
 
@@ -205,7 +208,7 @@ bool CppPlugin::initialize(const QStringList & /*arguments*/, QString *errorMess
     addAutoReleasedObject(new CppEditorFactory(this));
     addAutoReleasedObject(new CppHoverHandler);
     addAutoReleasedObject(new CppOutlineWidgetFactory);
-
+    addAutoReleasedObject(new CppTypeHierarchyFactory);
 
     m_quickFixCollector = new CppQuickFixCollector;
     addAutoReleasedObject(m_quickFixCollector);
@@ -274,6 +277,13 @@ bool CppPlugin::initialize(const QStringList & /*arguments*/, QString *errorMess
     contextMenu->addAction(cmd);
     cppToolsMenu->addAction(cmd);
 
+    m_openTypeHierarchyAction = new QAction(tr("Open Type Hierarchy"), this);
+    cmd = am->registerAction(m_openTypeHierarchyAction, Constants::OPEN_TYPE_HIERARCHY, context);
+    cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+T")));
+    connect(m_openTypeHierarchyAction, SIGNAL(triggered()), this, SLOT(openTypeHierarchy()));
+    contextMenu->addAction(cmd);
+    cppToolsMenu->addAction(cmd);
+
     // Update context in global context
     Core::Context globalContext(Core::Constants::C_GLOBAL);
     cppToolsMenu->addAction(createSeparator(am, this, globalContext, CppEditor::Constants::SEPARATOR2));
@@ -391,6 +401,7 @@ void CppPlugin::onTaskStarted(const QString &type)
         m_renameSymbolUnderCursorAction->setEnabled(false);
         m_findUsagesAction->setEnabled(false);
         m_updateCodeModelAction->setEnabled(false);
+        m_openTypeHierarchyAction->setEnabled(false);
     }
 }
 
@@ -400,6 +411,7 @@ void CppPlugin::onAllTasksFinished(const QString &type)
         m_renameSymbolUnderCursorAction->setEnabled(true);
         m_findUsagesAction->setEnabled(true);
         m_updateCodeModelAction->setEnabled(true);
+        m_openTypeHierarchyAction->setEnabled(true);
     }
 }
 
@@ -413,4 +425,15 @@ void CppPlugin::currentEditorChanged(Core::IEditor *editor)
     }
 }
 
+void CppPlugin::openTypeHierarchy()
+{
+    Core::EditorManager *em = Core::EditorManager::instance();
+    CPPEditor *editor = qobject_cast<CPPEditor*>(em->currentEditor()->widget());
+    if (editor) {
+        Core::NavigationWidget *navigation = Core::NavigationWidget::instance();
+        navigation->activateSubWidget(QLatin1String(Constants::TYPE_HIERARCHY_ID));
+        emit typeHierarchyRequested();
+    }
+}
+
 Q_EXPORT_PLUGIN(CppPlugin)
diff --git a/src/plugins/cppeditor/cppplugin.h b/src/plugins/cppeditor/cppplugin.h
index b72a8a8df0ab324a03fc2e2c02f520e83d495d47..36550b560fc7b89141099dcf46c523d41f51b961 100644
--- a/src/plugins/cppeditor/cppplugin.h
+++ b/src/plugins/cppeditor/cppplugin.h
@@ -71,6 +71,7 @@ public:
 
 signals:
     void outlineSortingChanged(bool sort);
+    void typeHierarchyRequested();
 
 public slots:
     void setSortedOutline(bool sorted);
@@ -85,6 +86,7 @@ private slots:
     void quickFix(TextEditor::ITextEditable *editable);
     void quickFixNow();
     void currentEditorChanged(Core::IEditor *editor);
+    void openTypeHierarchy();
 
 private:
     Core::IEditor *createEditor(QWidget *parent);
@@ -98,6 +100,7 @@ private:
     QAction *m_renameSymbolUnderCursorAction;
     QAction *m_findUsagesAction;
     QAction *m_updateCodeModelAction;
+    QAction *m_openTypeHierarchyAction;
 
     CppQuickFixCollector *m_quickFixCollector;
 
diff --git a/src/plugins/cppeditor/cpptypehierarchy.cpp b/src/plugins/cppeditor/cpptypehierarchy.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a13265415228aca0fd25afd357758d81c6f70776
--- /dev/null
+++ b/src/plugins/cppeditor/cpptypehierarchy.cpp
@@ -0,0 +1,267 @@
+/**************************************************************************
+**
+** 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 "cpptypehierarchy.h"
+#include "cppeditorconstants.h"
+#include "cppeditor.h"
+#include "cppelementevaluator.h"
+#include "cppplugin.h"
+
+#include <coreplugin/editormanager/ieditor.h>
+#include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/coreconstants.h>
+#include <utils/navigationtreeview.h>
+
+#include <QtCore/QLatin1Char>
+#include <QtCore/QLatin1String>
+#include <QtCore/QModelIndex>
+#include <QtCore/QSettings>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QStandardItemModel>
+#include <QtGui/QFontMetrics>
+#include <QtGui/QApplication>
+#include <QtGui/QPainter>
+#include <QtGui/QLabel>
+
+using namespace CppEditor;
+using namespace Internal;
+
+// CppTypeHierarchyItem
+CppTypeHierarchyItem::CppTypeHierarchyItem(const CppClass &cppClass) :
+    QStandardItem(), m_cppClass(cppClass)
+{}
+
+CppTypeHierarchyItem::~CppTypeHierarchyItem()
+{}
+
+int CppTypeHierarchyItem::type() const
+{ return UserType; }
+
+const CppClass &CppTypeHierarchyItem::cppClass() const
+{ return m_cppClass; }
+
+// CppTypeHierarchyDelegate
+CppTypeHierarchyDelegate::CppTypeHierarchyDelegate(QObject *parent) : QStyledItemDelegate(parent)
+{}
+
+CppTypeHierarchyDelegate::~CppTypeHierarchyDelegate()
+{}
+
+void CppTypeHierarchyDelegate::paint(QPainter *painter,
+                                     const QStyleOptionViewItem &option,
+                                     const QModelIndex &index) const
+{
+    if (const QStyleOptionViewItemV3 *v3 =
+            qstyleoption_cast<const QStyleOptionViewItemV3 *>(&option)) {
+        QApplication::style()->drawPrimitive(QStyle::PE_PanelItemViewItem, v3, painter, v3->widget);
+
+        QStyleOptionViewItemV4 opt = option;
+        initStyleOption(&opt, index);
+
+        const QStandardItemModel *model = static_cast<const QStandardItemModel *>(index.model());
+        CppTypeHierarchyItem *item =
+            static_cast<CppTypeHierarchyItem *>(model->itemFromIndex(index));
+
+        painter->save();
+        const QIcon &icon = item->cppClass().icon();
+        const QSize &iconSize = icon.actualSize(opt.decorationSize);
+        QRect workingRect(opt.rect);
+        QRect decorationRect(workingRect.topLeft(), iconSize);
+        icon.paint(painter, decorationRect, opt.decorationAlignment);
+        workingRect.setX(workingRect.x() + iconSize.width() + 4);
+
+        QRect boundingRect;
+        const QString &name = item->cppClass().name() + QLatin1Char(' ');
+        painter->drawText(workingRect, Qt::AlignLeft, name, &boundingRect);
+        if (item->cppClass().name() != item->cppClass().qualifiedName()) {
+            QFont font(painter->font());
+            if (font.pointSize() > 2)
+                font.setPointSize(font.pointSize() - 2);
+            else if (font.pointSize() > 1)
+                font.setPointSize(font.pointSize() - 1);
+            font.setItalic(true);
+            painter->setFont(font);
+
+            QFontMetrics metrics(font);
+            workingRect.setX(boundingRect.x() + boundingRect.width());
+            workingRect.setY(boundingRect.y() + boundingRect.height() - metrics.height());
+            painter->drawText(workingRect, Qt::AlignLeft, item->cppClass().qualifiedName());
+        }
+        painter->restore();
+    } else {
+        QStyledItemDelegate::paint(painter, option, index);
+    }
+}
+
+QSize CppTypeHierarchyDelegate::sizeHint(const QStyleOptionViewItem &option,
+                                        const QModelIndex &index) const
+{
+    QSize size = QStyledItemDelegate::sizeHint(option, index);
+    size.rwidth() += 5; // Extend a bit because of the font processing.
+    return size;
+}
+
+// CppTypeHierarchyWidget
+CppTypeHierarchyWidget::CppTypeHierarchyWidget(Core::IEditor *editor) :
+    QWidget(0),
+    m_cppEditor(0),
+    m_treeView(0),
+    m_model(0),
+    m_delegate(0)
+{
+    QVBoxLayout *layout = new QVBoxLayout;
+    layout->setMargin(0);
+    layout->setSpacing(0);
+
+    if (CPPEditorEditable *cppEditable = qobject_cast<CPPEditorEditable *>(editor)) {
+        m_cppEditor = static_cast<CPPEditor *>(cppEditable->widget());
+
+        m_model = new QStandardItemModel;
+        m_treeView = new Utils::NavigationTreeView;
+        m_delegate = new CppTypeHierarchyDelegate;
+        m_treeView->setModel(m_model);
+        m_treeView->setEditTriggers(QAbstractItemView::NoEditTriggers);
+        m_treeView->setItemDelegate(m_delegate);
+        layout->addWidget(m_treeView);
+
+        connect(m_treeView, SIGNAL(clicked(QModelIndex)), this, SLOT(onItemClicked(QModelIndex)));
+        connect(CppPlugin::instance(), SIGNAL(typeHierarchyRequested()), this, SLOT(perform()));
+    } else {
+        QLabel *label = new QLabel(tr("No type hierarchy available"), this);
+        label->setAlignment(Qt::AlignCenter);
+        label->setAutoFillBackground(true);
+        label->setBackgroundRole(QPalette::Base);
+        layout->addWidget(label);
+    }
+    setLayout(layout);
+}
+
+CppTypeHierarchyWidget::~CppTypeHierarchyWidget()
+{
+    delete m_model;
+    delete m_delegate;
+}
+
+void CppTypeHierarchyWidget::perform()
+{
+    if (!m_cppEditor)
+        return;
+
+    m_model->clear();
+
+    CppElementEvaluator evaluator(m_cppEditor);
+    evaluator.setLookupBaseClasses(true);
+    QSharedPointer<CppElement> cppElement = evaluator.identifyCppElement();
+    if (!cppElement.isNull()) {
+        CppElement *element = cppElement.data();
+        if (CppClass *cppClass = dynamic_cast<CppClass *>(element))
+            buildModel(*cppClass, m_model->invisibleRootItem());
+    }
+}
+
+void CppTypeHierarchyWidget::buildModel(const CppClass &cppClass, QStandardItem *parent)
+{
+    CppTypeHierarchyItem *item = new CppTypeHierarchyItem(cppClass);
+    parent->appendRow(item);
+
+    // The delegate retrieves data from the item directly. This is to help size hint.
+    const QString &display = cppClass.name() + cppClass.qualifiedName();
+    m_model->setData(m_model->indexFromItem(item), display, Qt::DisplayRole);
+    m_model->setData(m_model->indexFromItem(item), cppClass.icon(), Qt::DecorationRole);
+
+    foreach (const CppClass &cppBase, cppClass.bases())
+        buildModel(cppBase, item);
+
+    m_treeView->expand(m_model->indexFromItem(item));
+}
+
+void CppTypeHierarchyWidget::onItemClicked(const QModelIndex &index)
+{
+    if (QStandardItem *item = m_model->itemFromIndex(index)) {
+        CppTypeHierarchyItem *cppItem = static_cast<CppTypeHierarchyItem *>(item);
+        m_cppEditor->openLink(cppItem->cppClass().link());
+    }
+}
+
+// CppTypeHierarchyStackedWidget
+CppTypeHierarchyStackedWidget::CppTypeHierarchyStackedWidget(QWidget *parent) :
+    QStackedWidget(parent),
+    m_typeHiearchyWidgetInstance(
+        new CppTypeHierarchyWidget(Core::EditorManager::instance()->currentEditor()))
+{
+    addWidget(m_typeHiearchyWidgetInstance);
+
+    connect(Core::EditorManager::instance(), SIGNAL(currentEditorChanged(Core::IEditor*)),
+            this, SLOT(editorChanged(Core::IEditor*)));
+}
+
+CppTypeHierarchyStackedWidget::~CppTypeHierarchyStackedWidget()
+{
+    delete m_typeHiearchyWidgetInstance;
+}
+
+void CppTypeHierarchyStackedWidget::editorChanged(Core::IEditor *editor)
+{
+    CppTypeHierarchyWidget *replacement = new CppTypeHierarchyWidget(editor);
+    removeWidget(m_typeHiearchyWidgetInstance);
+    m_typeHiearchyWidgetInstance->deleteLater();
+    m_typeHiearchyWidgetInstance = replacement;
+    addWidget(m_typeHiearchyWidgetInstance);
+}
+
+// CppTypeHierarchyFactory
+CppTypeHierarchyFactory::CppTypeHierarchyFactory()
+{}
+
+CppTypeHierarchyFactory::~CppTypeHierarchyFactory()
+{}
+
+QString CppTypeHierarchyFactory::displayName() const
+{
+    return tr("Type Hierarchy");
+}
+
+QString CppTypeHierarchyFactory::id() const
+{
+    return QLatin1String(Constants::TYPE_HIERARCHY_ID);
+}
+
+QKeySequence CppTypeHierarchyFactory::activationSequence() const
+{
+    return QKeySequence();
+}
+
+Core::NavigationView CppTypeHierarchyFactory::createWidget()
+{
+    CppTypeHierarchyStackedWidget *w = new CppTypeHierarchyStackedWidget;
+    static_cast<CppTypeHierarchyWidget *>(w->currentWidget())->perform();
+    Core::NavigationView navigationView;
+    navigationView.widget = w;
+    return navigationView;
+}
diff --git a/src/plugins/cppeditor/cpptypehierarchy.h b/src/plugins/cppeditor/cpptypehierarchy.h
new file mode 100644
index 0000000000000000000000000000000000000000..8bc2c192a519d87e04feff7071969cd2fa273aa9
--- /dev/null
+++ b/src/plugins/cppeditor/cpptypehierarchy.h
@@ -0,0 +1,142 @@
+/**************************************************************************
+**
+** 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 CPPTYPEHIERARCHY_H
+#define CPPTYPEHIERARCHY_H
+
+#include "cppelementevaluator.h"
+
+#include <coreplugin/inavigationwidgetfactory.h>
+
+#include <QtCore/QString>
+#include <QtGui/QWidget>
+#include <QtGui/QStackedWidget>
+#include <QtGui/QStandardItem>
+#include <QtGui/QStyledItemDelegate>
+
+QT_BEGIN_NAMESPACE
+class QStandardItemModel;
+class QModelIndex;
+class QPainter;
+QT_END_NAMESPACE
+
+namespace Core {
+class IEditor;
+}
+
+namespace Utils {
+class NavigationTreeView;
+}
+
+namespace CppEditor {
+namespace Internal {
+
+class CPPEditor;
+
+class CppTypeHierarchyItem : public QStandardItem
+{
+public:
+    CppTypeHierarchyItem(const CppClass &cppClass);
+    virtual ~CppTypeHierarchyItem();
+
+    virtual int type() const;
+
+    const CppClass &cppClass() const;
+
+private:
+    CppClass m_cppClass;
+};
+
+class CppTypeHierarchyDelegate : public QStyledItemDelegate
+{
+public:
+    CppTypeHierarchyDelegate(QObject *parent = 0);
+    virtual ~CppTypeHierarchyDelegate();
+
+    virtual void paint(QPainter *painter,
+                       const QStyleOptionViewItem &option,
+                       const QModelIndex &index) const;
+    virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
+};
+
+class CppTypeHierarchyWidget : public QWidget
+{
+    Q_OBJECT
+public:
+    CppTypeHierarchyWidget(Core::IEditor *editor);
+    virtual ~CppTypeHierarchyWidget();
+
+public slots:
+    void perform();
+
+private slots:
+    void onItemClicked(const QModelIndex &index);
+
+private:
+    void buildModel(const CppClass &cppClass, QStandardItem *item);
+
+    CPPEditor *m_cppEditor;
+    Utils::NavigationTreeView *m_treeView;
+    QStandardItemModel *m_model;
+    CppTypeHierarchyDelegate *m_delegate;
+};
+
+// @todo: Pretty much the same design as the OutlineWidgetStack. Maybe we can generalize the
+// outline factory so that it works for different widgets that support the same editor.
+class CppTypeHierarchyStackedWidget : public QStackedWidget
+{
+    Q_OBJECT
+public:
+    CppTypeHierarchyStackedWidget(QWidget *parent = 0);
+    virtual ~CppTypeHierarchyStackedWidget();
+
+public slots:
+    void editorChanged(Core::IEditor* editor);
+
+private:
+    CppTypeHierarchyWidget *m_typeHiearchyWidgetInstance;
+};
+
+class CppTypeHierarchyFactory : public Core::INavigationWidgetFactory
+{
+    Q_OBJECT
+public:
+    CppTypeHierarchyFactory();
+    virtual ~CppTypeHierarchyFactory();
+
+    virtual QString displayName() const;
+    virtual QString id() const;
+    virtual QKeySequence activationSequence() const;
+    virtual Core::NavigationView createWidget();
+};
+
+} // namespace Internal
+} // namespace CppEditor
+
+#endif // CPPTYPEHIERARCHY_H
diff --git a/src/plugins/texteditor/basehoverhandler.cpp b/src/plugins/texteditor/basehoverhandler.cpp
index d993bb124664312ff7eb8667d65974bc29bda0e7..21aaa6368756c7fdf5a591f512a463cc3a5ded98 100644
--- a/src/plugins/texteditor/basehoverhandler.cpp
+++ b/src/plugins/texteditor/basehoverhandler.cpp
@@ -95,6 +95,10 @@ void BaseHoverHandler::showToolTip(TextEditor::ITextEditor *editor, const QPoint
 
 void BaseHoverHandler::updateContextHelpId(TextEditor::ITextEditor *editor, int pos)
 {
+    BaseTextEditor *baseEditor = baseTextEditor(editor);
+    if (!baseEditor)
+        return;
+
     // If the tooltip is visible and there is a help match, this match is used to update
     // the help id. Otherwise, let the identification process happen.
     if (!ToolTip::instance()->isVisible() || m_matchingHelpCandidate == -1)
diff --git a/src/plugins/texteditor/basehoverhandler.h b/src/plugins/texteditor/basehoverhandler.h
index 587f257210bd9ba5837a94a2fdc545b898dc1489..737b44660fd95cec0a99638312143e17392abdeb 100644
--- a/src/plugins/texteditor/basehoverhandler.h
+++ b/src/plugins/texteditor/basehoverhandler.h
@@ -57,19 +57,6 @@ class TEXTEDITOR_EXPORT BaseHoverHandler : public QObject
 public:
     BaseHoverHandler(QObject *parent = 0);
 
-private slots:
-    void editorOpened(Core::IEditor *editor);
-
-public slots:
-    void showToolTip(TextEditor::ITextEditor *editor, const QPoint &point, int pos);
-    void updateContextHelpId(TextEditor::ITextEditor *editor, int pos);
-
-protected:
-    void setToolTip(const QString &tooltip);
-    const QString &toolTip() const;
-    void appendToolTip(const QString &extension);
-    void addF1ToToolTip();
-
     struct HelpCandidate
     {
         enum Category {
@@ -94,6 +81,19 @@ protected:
         Category m_category;
     };
 
+private slots:
+    void editorOpened(Core::IEditor *editor);
+
+public slots:
+    void showToolTip(TextEditor::ITextEditor *editor, const QPoint &point, int pos);
+    void updateContextHelpId(TextEditor::ITextEditor *editor, int pos);
+
+protected:
+    void setToolTip(const QString &tooltip);
+    const QString &toolTip() const;
+    void appendToolTip(const QString &extension);
+    void addF1ToToolTip();
+
     void addHelpCandidate(const HelpCandidate &helpCandidate);
     void setHelpCandidate(const HelpCandidate &helpCandidate, int index);
     const QList<HelpCandidate> &helpCandidates() const;
diff --git a/src/plugins/texteditor/basetexteditor.h b/src/plugins/texteditor/basetexteditor.h
index afa439ed9fde7c8eae08a9b10cc187e015f92fc4..121ba012cde48dc6c227b2ce21c3b3d5eb6577a5 100644
--- a/src/plugins/texteditor/basetexteditor.h
+++ b/src/plugins/texteditor/basetexteditor.h
@@ -463,6 +463,7 @@ protected:
     static void countBrackets(QTextCursor cursor, int from, int end, QChar open, QChar close,
                               int *errors, int *stillopen);
 
+public:
     struct Link
     {
         Link(const QString &fileName = QString(),
@@ -489,6 +490,7 @@ protected:
         int column;        // Target column
     };
 
+protected:
     /*!
        Reimplement this function to enable code navigation.