diff --git a/src/libs/utils/htmldocextractor.cpp b/src/libs/utils/htmldocextractor.cpp
index 478795f90457397ef0abe9bcb601a4b884bfa905..2f6481379b50c96cc892ccadf5c671b6aa429ef2 100644
--- a/src/libs/utils/htmldocextractor.cpp
+++ b/src/libs/utils/htmldocextractor.cpp
@@ -149,6 +149,11 @@ QString HtmlDocExtractor::getFunctionDescription(const QString &html,
     return contents;
 }
 
+QString HtmlDocExtractor::getQMLItemDescription(const QString &html, const QString &mark) const
+{
+    return getClassOrNamespaceDescription(html, mark);
+}
+
 QString HtmlDocExtractor::getClassOrNamespaceMemberDescription(const QString &html,
                                                                const QString &startMark,
                                                                const QString &endMark) const
diff --git a/src/libs/utils/htmldocextractor.h b/src/libs/utils/htmldocextractor.h
index a752c1ef80ca9f039bc6f3af4a86b299967b2add..a9acf79a5fd7e4a2bfd291ac92f2001d1ad6e03d 100644
--- a/src/libs/utils/htmldocextractor.h
+++ b/src/libs/utils/htmldocextractor.h
@@ -54,6 +54,7 @@ public:
     QString getFunctionDescription(const QString &html,
                                    const QString &mark,
                                    const bool mainOverload = true) const;
+    QString getQMLItemDescription(const QString &html, const QString &mark) const;
 
 private:
     QString getClassOrNamespaceMemberDescription(const QString &html,
diff --git a/src/plugins/cppeditor/cpphoverhandler.cpp b/src/plugins/cppeditor/cpphoverhandler.cpp
index baf9d68854037f79fe2c3f4b48ec4953bf1280a5..6efc3ae1b17ad1b4f4de36db5ec89cdbc0db9d7a 100644
--- a/src/plugins/cppeditor/cpphoverhandler.cpp
+++ b/src/plugins/cppeditor/cpphoverhandler.cpp
@@ -30,17 +30,12 @@
 #include "cpphoverhandler.h"
 #include "cppeditor.h"
 
-#include <coreplugin/icore.h>
-#include <coreplugin/helpmanager.h>
-#include <coreplugin/uniqueidmanager.h>
+#include <coreplugin/editormanager/ieditor.h>
 #include <coreplugin/editormanager/editormanager.h>
 #include <cpptools/cppmodelmanagerinterface.h>
 #include <extensionsystem/pluginmanager.h>
 #include <texteditor/itexteditor.h>
 #include <texteditor/basetexteditor.h>
-#include <texteditor/displaysettings.h>
-#include <texteditor/tooltip/tooltip.h>
-#include <debugger/debuggerconstants.h>
 
 #include <FullySpecifiedType.h>
 #include <Names.h>
@@ -128,89 +123,22 @@ namespace {
     };
 }
 
-CppHoverHandler::CppHoverHandler(QObject *parent)
-    : QObject(parent), m_modelManager(0), m_matchingHelpCandidate(-1)
+CppHoverHandler::CppHoverHandler(QObject *parent) : BaseHoverHandler(parent), m_modelManager(0)
 {
     m_modelManager =
         ExtensionSystem::PluginManager::instance()->getObject<CppTools::CppModelManagerInterface>();
-
-    // Listen for editor opened events in order to connect to tooltip/helpid requests
-    connect(ICore::instance()->editorManager(), SIGNAL(editorOpened(Core::IEditor *)),
-            this, SLOT(editorOpened(Core::IEditor *)));
 }
 
-void CppHoverHandler::editorOpened(IEditor *editor)
+bool CppHoverHandler::acceptEditor(IEditor *editor)
 {
     CPPEditorEditable *cppEditor = qobject_cast<CPPEditorEditable *>(editor);
-    if (!cppEditor)
-        return;
-
-    connect(cppEditor, SIGNAL(tooltipRequested(TextEditor::ITextEditor*, QPoint, int)),
-            this, SLOT(showToolTip(TextEditor::ITextEditor*, QPoint, int)));
-
-    connect(cppEditor, SIGNAL(contextHelpIdRequested(TextEditor::ITextEditor*, int)),
-            this, SLOT(updateContextHelpId(TextEditor::ITextEditor*, int)));
-}
-
-void CppHoverHandler::updateContextHelpId(TextEditor::ITextEditor *editor, int pos)
-{
-    if (!editor)
-        return;
-
-    // If the tooltip is visible and there is a help match, this match is used to update the help
-    // id. Otherwise, the identification process happens.
-    if (!TextEditor::ToolTip::instance()->isVisible() || m_matchingHelpCandidate == -1)
-        identifyMatch(editor, pos);
-
-    if (m_matchingHelpCandidate != -1)
-        editor->setContextHelpId(m_helpCandidates.at(m_matchingHelpCandidate).m_helpId);
-    else
-        editor->setContextHelpId(QString());
-}
-
-void CppHoverHandler::showToolTip(TextEditor::ITextEditor *editor, const QPoint &point, int pos)
-{
-    TextEditor::BaseTextEditor *baseEditor = baseTextEditor(editor);
-    if (!baseEditor)
-        return;
-
-    editor->setContextHelpId(QString());
-
-    ICore *core = ICore::instance();
-    const int dbgContext =
-        core->uniqueIDManager()->uniqueIdentifier(Debugger::Constants::C_DEBUGMODE);
-    if (core->hasContext(dbgContext))
-        return;
-
-    identifyMatch(editor, pos);
-
-    if (m_toolTip.isEmpty()) {
-        TextEditor::ToolTip::instance()->hide();
-    } else {
-        if (!m_classHierarchy.isEmpty())
-            generateDiagramTooltip(baseEditor->displaySettings().m_extendTooltips);
-        else
-            generateNormalTooltip(baseEditor->displaySettings().m_extendTooltips);
-
-        if (m_matchingHelpCandidate != -1)
-            addF1ToTooltip();
-
-        const QPoint pnt = point - QPoint(0,
-#ifdef Q_WS_WIN
-        24
-#else
-        16
-#endif
-        );
-
-        TextEditor::ToolTip::instance()->showText(pnt, m_toolTip, editor->widget());
-    }
+    if (cppEditor)
+        return true;
+    return false;
 }
 
 void CppHoverHandler::identifyMatch(TextEditor::ITextEditor *editor, int pos)
 {
-    resetMatchings();
-
     if (!m_modelManager)
         return;
 
@@ -231,7 +159,7 @@ void CppHoverHandler::identifyMatch(TextEditor::ITextEditor *editor, int pos)
 
             bool extraSelectionTooltip = false;
             if (!baseEditor->extraSelectionTooltip(pos).isEmpty()) {
-                m_toolTip = baseEditor->extraSelectionTooltip(pos);
+                setToolTip(baseEditor->extraSelectionTooltip(pos));
                 extraSelectionTooltip = true;
             }
 
@@ -253,8 +181,6 @@ void CppHoverHandler::identifyMatch(TextEditor::ITextEditor *editor, int pos)
             const LookupItem &lookupItem = lookupItems.first(); // ### TODO: select best candidate.
             handleLookupItemMatch(lookupItem, typeOfExpression.context(), !extraSelectionTooltip);
         }
-
-        evaluateHelpCandidates();
     }
 }
 
@@ -263,7 +189,7 @@ bool CppHoverHandler::matchDiagnosticMessage(const CPlusPlus::Document::Ptr &doc
 {
     foreach (const Document::DiagnosticMessage &m, document->diagnosticMessages()) {
         if (m.line() == line) {
-            m_toolTip = m.text();
+            setToolTip(m.text());
             return true;
         }
     }
@@ -274,9 +200,9 @@ bool CppHoverHandler::matchIncludeFile(const CPlusPlus::Document::Ptr &document,
 {
     foreach (const Document::Include &includeFile, document->includes()) {
         if (includeFile.line() == line) {
-            m_toolTip = QDir::toNativeSeparators(includeFile.fileName());
+            setToolTip(QDir::toNativeSeparators(includeFile.fileName()));
             const QString &fileName = QFileInfo(includeFile.fileName()).fileName();
-            m_helpCandidates.append(HelpCandidate(fileName, fileName, HelpCandidate::Brief));
+            addHelpCandidate(HelpCandidate(fileName, fileName, HelpCandidate::Brief));
             return true;
         }
     }
@@ -290,8 +216,8 @@ bool CppHoverHandler::matchMacroInUse(const CPlusPlus::Document::Ptr &document,
             const unsigned begin = use.begin();
             const QString &name = use.macro().name();
             if (pos < begin + name.length()) {
-                m_toolTip = use.macro().toString();
-                m_helpCandidates.append(HelpCandidate(name, name, HelpCandidate::Macro));
+                setToolTip(use.macro().toString());
+                addHelpCandidate(HelpCandidate(name, name, HelpCandidate::Macro));
                 return true;
             }
         }
@@ -311,7 +237,7 @@ void CppHoverHandler::handleLookupItemMatch(const LookupItem &lookupItem,
     overview.setShowReturnTypes(true);
 
     if (!matchingDeclaration && assignTooltip) {
-        m_toolTip = overview.prettyType(matchingType, QString());
+        setToolTip(overview.prettyType(matchingType, QString()));
     } else {
         QString name;
         if (matchingDeclaration->enclosingSymbol()->isClass() ||
@@ -333,9 +259,9 @@ void CppHoverHandler::handleLookupItemMatch(const LookupItem &lookupItem,
                 matchingDeclaration->isNamespace() ||
                 matchingDeclaration->isForwardClassDeclaration() ||
                 matchingDeclaration->isEnum()) {
-                m_toolTip = name;
+                setToolTip(name);
             } else {
-                m_toolTip = overview.prettyType(matchingType, name);
+                setToolTip(overview.prettyType(matchingType, name));
             }
         }
 
@@ -372,7 +298,7 @@ void CppHoverHandler::handleLookupItemMatch(const LookupItem &lookupItem,
                         Symbol *symbol = clazz->symbols().at(0);
                         matchingDeclaration = symbol;
                         name = overview.prettyName(LookupContext::fullyQualifiedName(symbol));
-                        m_toolTip = name;
+                        setToolTip(name);
                         buildClassHierarchy(symbol, context, overview, &m_classHierarchy);
                         helpCategory = HelpCandidate::ClassOrNamespace;
                     }
@@ -391,93 +317,46 @@ void CppHoverHandler::handleLookupItemMatch(const LookupItem &lookupItem,
                 docMark = overview.prettyType(matchingType, docMark);
                 overview.setShowFunctionSignatures(false);
                 const QString &functionName = overview.prettyName(matchingDeclaration->name());
-                m_helpCandidates.append(HelpCandidate(functionName, docMark, helpCategory));
+                addHelpCandidate(HelpCandidate(functionName, docMark, helpCategory));
             } else if (matchingDeclaration->enclosingSymbol()->isEnum()) {
                 Symbol *enumSymbol = matchingDeclaration->enclosingSymbol()->asEnum();
                 docMark = overview.prettyName(enumSymbol->name());
             }
 
-            m_helpCandidates.append(HelpCandidate(name, docMark, helpCategory));
+            addHelpCandidate(HelpCandidate(name, docMark, helpCategory));
         }
     }
 }
 
 void CppHoverHandler::evaluateHelpCandidates()
 {
-    for (int i = 0; i < m_helpCandidates.size() && m_matchingHelpCandidate == -1; ++i) {
-        if (helpIdExists(m_helpCandidates.at(i).m_helpId)) {
-            m_matchingHelpCandidate = i;
+    for (int i = 0; i < helpCandidates().size() && matchingHelpCandidate() == -1; ++i) {
+        if (helpIdExists(helpCandidates().at(i).m_helpId)) {
+            setMatchingHelpCandidate(i);
         } else {
             // There are class help ids with and without qualification.
-            HelpCandidate &candidate = m_helpCandidates[i];
+            HelpCandidate candidate = helpCandidates().at(i);
             const QString &helpId = removeClassNameQualification(candidate.m_helpId);
             if (helpIdExists(helpId)) {
                 candidate.m_helpId = helpId;
-                m_matchingHelpCandidate = i;
+                setHelpCandidate(candidate, i);
+                setMatchingHelpCandidate(i);
             }
         }
     }
 }
 
-bool CppHoverHandler::helpIdExists(const QString &helpId) const
+void CppHoverHandler::decorateToolTip(TextEditor::ITextEditor *editor)
 {
-    QMap<QString, QUrl> helpLinks = Core::HelpManager::instance()->linksForIdentifier(helpId);
-    if (!helpLinks.isEmpty())
-        return true;
-    return false;
-}
-
-QString CppHoverHandler::getDocContents(const bool extended)
-{
-    Q_ASSERT(m_matchingHelpCandidate >= 0);
-
-    return getDocContents(m_helpCandidates.at(m_matchingHelpCandidate), extended);
-}
-
-QString CppHoverHandler::getDocContents(const HelpCandidate &help, const bool extended)
-{
-    if (extended)
-        m_htmlDocExtractor.extractExtendedContents(1500, true);
+    if (!m_classHierarchy.isEmpty())
+        generateDiagramTooltip(extendToolTips(editor));
     else
-        m_htmlDocExtractor.extractFirstParagraphOnly();
-
-    QString contents;
-    QMap<QString, QUrl> helpLinks =
-        Core::HelpManager::instance()->linksForIdentifier(help.m_helpId);
-    foreach (const QUrl &url, helpLinks) {
-        const QByteArray &html = Core::HelpManager::instance()->fileData(url);
-        switch (help.m_category) {
-        case HelpCandidate::Brief:
-            contents = m_htmlDocExtractor.getClassOrNamespaceBrief(html, help.m_docMark);
-            break;
-        case HelpCandidate::ClassOrNamespace:
-            contents = m_htmlDocExtractor.getClassOrNamespaceDescription(html, help.m_docMark);
-            break;
-        case HelpCandidate::Function:
-            contents = m_htmlDocExtractor.getFunctionDescription(html, help.m_docMark);
-            break;
-        case HelpCandidate::Enum:
-            contents = m_htmlDocExtractor.getEnumDescription(html, help.m_docMark);
-            break;
-        case HelpCandidate::Typedef:
-            contents = m_htmlDocExtractor.getTypedefDescription(html, help.m_docMark);
-            break;
-        case HelpCandidate::Macro:
-            contents = m_htmlDocExtractor.getMacroDescription(html, help.m_docMark);
-            break;
-        default:
-            break;
-        }
-
-        if (!contents.isEmpty())
-            break;
-    }
-    return contents;
+        generateNormalTooltip(extendToolTips(editor));
 }
 
 void CppHoverHandler::generateDiagramTooltip(const bool extendTooltips)
 {
-    QString clazz = m_toolTip;
+    QString clazz = toolTip();
 
     qSort(m_classHierarchy.begin(), m_classHierarchy.end(), ClassHierarchyComp());
 
@@ -498,7 +377,7 @@ void CppHoverHandler::generateDiagramTooltip(const bool extendTooltips)
             diagram.append(QString(
                 "<tr><td>%1</td><td>"
                 "<img src=\":/cppeditor/images/rightarrow.png\"></td>"
-                "<td>%2</td></tr>").arg(m_toolTip).arg(directBaseClasses.at(i)));
+                "<td>%2</td></tr>").arg(toolTip()).arg(directBaseClasses.at(i)));
         } else {
             diagram.append(QString(
                 "<tr><td></td><td>"
@@ -507,10 +386,10 @@ void CppHoverHandler::generateDiagramTooltip(const bool extendTooltips)
         }
     }
     diagram.append(QLatin1String("</table>"));
-    m_toolTip = diagram;
+    setToolTip(diagram);
 
-    if (m_matchingHelpCandidate != -1) {
-        m_toolTip.append(getDocContents(extendTooltips));
+    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).
@@ -521,8 +400,18 @@ void CppHoverHandler::generateDiagramTooltip(const bool extendTooltips)
             if (helpLevel != 0 && hierarchy.size() != helpLevel)
                 break;
 
-            const QString &name = hierarchy.last();
+            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();
@@ -533,14 +422,14 @@ void CppHoverHandler::generateDiagramTooltip(const bool extendTooltips)
             // Choose the first one as the help match.
             QString base = m_classHierarchy.at(baseClassesWithHelp.at(0)).last();
             HelpCandidate help(base, base, HelpCandidate::ClassOrNamespace);
-            m_helpCandidates.append(help);
-            m_matchingHelpCandidate = m_helpCandidates.size() - 1;
+            addHelpCandidate(help);
+            setMatchingHelpCandidate(helpCandidates().size() - 1);
 
             if (baseClassesWithHelp.size() == 1 && helpLevel == 1) {
-                m_toolTip.append(getDocContents(help, extendTooltips));
+                appendToolTip(getDocContents(help, extendTooltips));
             } else {
                 foreach (int hierarchyIndex, baseClassesWithHelp) {
-                    m_toolTip.append(QLatin1String("<p>"));
+                    appendToolTip(QLatin1String("<p>"));
                     const QStringList &hierarchy = m_classHierarchy.at(hierarchyIndex);
                     Q_ASSERT(helpLevel <= hierarchy.size());
 
@@ -557,13 +446,13 @@ void CppHoverHandler::generateDiagramTooltip(const bool extendTooltips)
                     diagram.append(QLatin1String("</tr></table>"));
 
                     base = hierarchy.at(helpLevel - 1);
-                    QString contents =
+                    const QString &contents =
                         getDocContents(HelpCandidate(base, base, HelpCandidate::Brief), false);
                     if (!contents.isEmpty()) {
-                        m_toolTip.append(diagram % QLatin1String("<table><tr><td>") %
-                                         contents % QLatin1String("</td></tr></table>"));
+                        appendToolTip(diagram % QLatin1String("<table><tr><td>") %
+                                      contents % QLatin1String("</td></tr></table>"));
                     }
-                    m_toolTip.append(QLatin1String("</p>"));
+                    appendToolTip(QLatin1String("</p>"));
                 }
             }
         }
@@ -572,40 +461,24 @@ void CppHoverHandler::generateDiagramTooltip(const bool extendTooltips)
 
 void CppHoverHandler::generateNormalTooltip(const bool extendTooltips)
 {
-    if (m_matchingHelpCandidate != -1) {
+    if (matchingHelpCandidate() != -1) {
         const QString &contents = getDocContents(extendTooltips);
         if (!contents.isEmpty()) {
-            HelpCandidate::Category cat = m_helpCandidates.at(m_matchingHelpCandidate).m_category;
+            HelpCandidate::Category cat = helpCandidate(matchingHelpCandidate()).m_category;
             if (cat == HelpCandidate::ClassOrNamespace)
-                m_toolTip.append(contents);
+                appendToolTip(contents);
             else
-                m_toolTip = contents;
+                setToolTip(contents);
         } else {
-            m_toolTip = Qt::escape(m_toolTip);
-            m_toolTip.prepend(QLatin1String("<nobr>"));
-            m_toolTip.append(QLatin1String("</nobr>"));
+            QString tip = Qt::escape(toolTip());
+            tip.prepend(QLatin1String("<nobr>"));
+            tip.append(QLatin1String("</nobr>"));
+            setToolTip(tip);
         }
     }
 }
 
-void CppHoverHandler::addF1ToTooltip()
-{
-    m_toolTip = QString(QLatin1String("<table><tr><td valign=middle>%1</td><td>&nbsp;&nbsp;"
-                                      "<img src=\":/cppeditor/images/f1.png\"></td>"
-                                      "</tr></table>")).arg(m_toolTip);
-}
-
-void CppHoverHandler::resetMatchings()
+void CppHoverHandler::resetExtras()
 {
-    m_matchingHelpCandidate = -1;
-    m_helpCandidates.clear();
-    m_toolTip.clear();
     m_classHierarchy.clear();
 }
-
-TextEditor::BaseTextEditor *CppHoverHandler::baseTextEditor(TextEditor::ITextEditor *editor)
-{
-    if (!editor)
-        return 0;
-    return qobject_cast<TextEditor::BaseTextEditor *>(editor->widget());
-}
diff --git a/src/plugins/cppeditor/cpphoverhandler.h b/src/plugins/cppeditor/cpphoverhandler.h
index 094bf68b4b2d52f2a00e65121d1d2ebdd73f8e23..1fab49b1d2e06658b23a81f3435745e97f02c394 100644
--- a/src/plugins/cppeditor/cpphoverhandler.h
+++ b/src/plugins/cppeditor/cpphoverhandler.h
@@ -31,16 +31,12 @@
 #define CPPHOVERHANDLER_H
 
 #include <cplusplus/CppDocument.h>
-#include <utils/htmldocextractor.h>
+#include <texteditor/basehoverhandler.h>
 
 #include <QtCore/QObject>
 #include <QtCore/QList>
 #include <QtCore/QStringList>
 
-QT_BEGIN_NAMESPACE
-class QPoint;
-QT_END_NAMESPACE
-
 namespace CPlusPlus {
 class LookupItem;
 class LookupContext;
@@ -56,48 +52,24 @@ class CppModelManagerInterface;
 
 namespace TextEditor {
 class ITextEditor;
-class BaseTextEditor;
 }
 
 namespace CppEditor {
 namespace Internal {
 
-class CppHoverHandler : public QObject
+class CppHoverHandler : public TextEditor::BaseHoverHandler
 {
     Q_OBJECT
 public:
     CppHoverHandler(QObject *parent = 0);
 
-public slots:
-    void showToolTip(TextEditor::ITextEditor *editor, const QPoint &point, int pos);
-    void updateContextHelpId(TextEditor::ITextEditor *editor, int pos);
-
-private slots:
-    void editorOpened(Core::IEditor *editor);
-
 private:
-    struct HelpCandidate
-    {
-        enum Category {
-            ClassOrNamespace,
-            Enum,
-            Typedef,
-            Macro,
-            Brief,
-            Function,
-            Unknown
-        };
+    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);
 
-        HelpCandidate(const QString &helpId, const QString &docMark, Category category) :
-            m_helpId(helpId), m_docMark(docMark), m_category(category)
-        {}
-        QString m_helpId;
-        QString m_docMark;
-        Category m_category;
-    };
-
-    void resetMatchings();
-    void identifyMatch(TextEditor::ITextEditor *editor, int pos);
     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);
@@ -105,23 +77,11 @@ private:
                                const CPlusPlus::LookupContext &lookupContext,
                                const bool assignTooltip);
 
-    void evaluateHelpCandidates();
-    bool helpIdExists(const QString &helpId) const;
-    QString getDocContents(const bool extended);
-    QString getDocContents(const HelpCandidate &helpCandidate, const bool extended);
-
     void generateDiagramTooltip(const bool extendTooltips);
     void generateNormalTooltip(const bool extendTooltips);
-    void addF1ToTooltip();
-
-    static TextEditor::BaseTextEditor *baseTextEditor(TextEditor::ITextEditor *editor);
 
     CppTools::CppModelManagerInterface *m_modelManager;
-    int m_matchingHelpCandidate;
-    QList<HelpCandidate> m_helpCandidates;
-    QString m_toolTip;
     QList<QStringList> m_classHierarchy;
-    Utils::HtmlDocExtractor m_htmlDocExtractor;
 };
 
 } // namespace Internal
diff --git a/src/plugins/qmljseditor/qmljshoverhandler.cpp b/src/plugins/qmljseditor/qmljshoverhandler.cpp
index aa7e22d60fe136438fb97e48e1ec3fafe2c8915b..b12377d751905122a4863684fc30bc48d2aca382 100644
--- a/src/plugins/qmljseditor/qmljshoverhandler.cpp
+++ b/src/plugins/qmljseditor/qmljshoverhandler.cpp
@@ -31,11 +31,8 @@
 #include "qmlexpressionundercursor.h"
 #include "qmljshoverhandler.h"
 
-#include <coreplugin/icore.h>
-#include <coreplugin/helpmanager.h>
-#include <coreplugin/uniqueidmanager.h>
+#include <coreplugin/editormanager/ieditor.h>
 #include <coreplugin/editormanager/editormanager.h>
-#include <debugger/debuggerconstants.h>
 #include <extensionsystem/pluginmanager.h>
 #include <qmljs/qmljsinterpreter.h>
 #include <qmljs/parser/qmljsast_p.h>
@@ -81,97 +78,22 @@ namespace {
     }
 }
 
-HoverHandler::HoverHandler(QObject *parent) :
-    QObject(parent), m_modelManager(0), m_matchingHelpCandidate(-1)
+HoverHandler::HoverHandler(QObject *parent) : BaseHoverHandler(parent), m_modelManager(0)
 {
     m_modelManager =
         ExtensionSystem::PluginManager::instance()->getObject<QmlJS::ModelManagerInterface>();
-
-    // Listen for editor opened events in order to connect to tooltip/helpid requests
-    connect(ICore::instance()->editorManager(), SIGNAL(editorOpened(Core::IEditor *)),
-            this, SLOT(editorOpened(Core::IEditor *)));
 }
 
-void HoverHandler::editorOpened(IEditor *editor)
+bool HoverHandler::acceptEditor(IEditor *editor)
 {
     QmlJSEditorEditable *qmlEditor = qobject_cast<QmlJSEditorEditable *>(editor);
-    if (!qmlEditor)
-        return;
-
-    connect(qmlEditor, SIGNAL(tooltipRequested(TextEditor::ITextEditor*, QPoint, int)),
-            this, SLOT(showToolTip(TextEditor::ITextEditor*, QPoint, int)));
-
-    connect(qmlEditor, SIGNAL(contextHelpIdRequested(TextEditor::ITextEditor*, int)),
-            this, SLOT(updateContextHelpId(TextEditor::ITextEditor*, int)));
-}
-
-void HoverHandler::showToolTip(TextEditor::ITextEditor *editor, const QPoint &point, int pos)
-{
-    if (!editor)
-        return;
-
-    ICore *core = ICore::instance();
-    const int dbgcontext =
-        core->uniqueIDManager()->uniqueIdentifier(Debugger::Constants::C_DEBUGMODE);
-    if (core->hasContext(dbgcontext))
-        return;
-
-    editor->setContextHelpId(QString());
-
-    identifyMatch(editor, pos);
-
-    if (m_toolTip.isEmpty())
-        TextEditor::ToolTip::instance()->hide();
-    else {
-        const QPoint &pnt = point - QPoint(0,
-#ifdef Q_WS_WIN
-        24
-#else
-        16
-#endif
-        );
-
-        if (m_colorTip.isValid()) {
-            TextEditor::ToolTip::instance()->showColor(pnt, m_colorTip, editor->widget());
-        } else {
-            m_toolTip = Qt::escape(m_toolTip);
-            if (m_matchingHelpCandidate != -1) {
-                m_toolTip = QString::fromUtf8(
-                    "<table><tr><td valign=middle><nobr>%1</td><td>"
-                    "<img src=\":/cppeditor/images/f1.png\"></td></tr></table>").arg(m_toolTip);
-            } else {
-                m_toolTip = QString::fromUtf8("<nobr>%1</nobr>").arg(m_toolTip);
-            }
-            TextEditor::ToolTip::instance()->showText(pnt, m_toolTip, editor->widget());
-        }
-    }
-}
-
-void HoverHandler::updateContextHelpId(TextEditor::ITextEditor *editor, int pos)
-{
-    // If the tooltip is visible and there is a help match, use it to update the help id.
-    // Otherwise, identify the match.
-    if (!TextEditor::ToolTip::instance()->isVisible() || m_matchingHelpCandidate == -1)
-        identifyMatch(editor, pos);
-
-    if (m_matchingHelpCandidate != -1)
-        editor->setContextHelpId(m_helpCandidates.at(m_matchingHelpCandidate));
-    else
-        editor->setContextHelpId(QString());
-}
-
-void HoverHandler::resetMatchings()
-{
-    m_matchingHelpCandidate = -1;
-    m_helpCandidates.clear();
-    m_toolTip.clear();
-    m_colorTip = QColor();
+    if (qmlEditor)
+        return true;
+    return false;
 }
 
 void HoverHandler::identifyMatch(TextEditor::ITextEditor *editor, int pos)
 {
-    resetMatchings();
-
     if (!m_modelManager)
         return;
 
@@ -195,8 +117,6 @@ void HoverHandler::identifyMatch(TextEditor::ITextEditor *editor, int pos)
         if (!matchColorItem(lookupContext, qmlDocument, astPath, pos))
             handleOrdinaryMatch(lookupContext, semanticInfo.nodeUnderCursor(pos));
     }
-
-    evaluateHelpCandidates();
 }
 
 bool HoverHandler::matchDiagnosticMessage(QmlJSTextEditor *qmlEditor, int pos)
@@ -204,7 +124,7 @@ bool HoverHandler::matchDiagnosticMessage(QmlJSTextEditor *qmlEditor, int pos)
     foreach (const QTextEdit::ExtraSelection &sel,
              qmlEditor->extraSelections(TextEditor::BaseTextEditor::CodeWarningsSelection)) {
         if (pos >= sel.cursor.selectionStart() && pos <= sel.cursor.selectionEnd()) {
-            m_toolTip = sel.format.toolTip();
+            setToolTip(sel.format.toolTip());
             return true;
         }
     }
@@ -260,7 +180,7 @@ bool HoverHandler::matchColorItem(const LookupContext::Ptr &lookupContext,
 
         m_colorTip = QmlJS::toQColor(color);
         if (m_colorTip.isValid()) {
-            m_toolTip = color;
+            setToolTip(color);
             return true;
         }
     }
@@ -272,23 +192,59 @@ void HoverHandler::handleOrdinaryMatch(const LookupContext::Ptr &lookupContext,
     if (node && !(AST::cast<AST::StringLiteral *>(node) != 0 ||
                   AST::cast<AST::NumericLiteral *>(node) != 0)) {
         const Interpreter::Value *value = lookupContext->evaluate(node);
-        m_toolTip = prettyPrint(value, lookupContext->context());
+        setToolTip(prettyPrint(value, lookupContext->context()));
     }
 }
 
+void HoverHandler::resetExtras()
+{
+    m_colorTip = QColor();
+}
+
 void HoverHandler::evaluateHelpCandidates()
 {
-    for (int i = 0; i < m_helpCandidates.size(); ++i) {
-        QString helpId = m_helpCandidates.at(i);
-        helpId.prepend(QLatin1String("QML."));
-        if (!Core::HelpManager::instance()->linksForIdentifier(helpId).isEmpty()) {
-            m_matchingHelpCandidate = i;
-            m_helpCandidates[i] = helpId;
+    for (int i = 0; i < helpCandidates().size(); ++i) {
+        HelpCandidate helpCandidate = helpCandidates().at(i);
+        helpCandidate.m_helpId.prepend(QLatin1String("QML."));
+        if (helpIdExists(helpCandidate.m_helpId)) {
+            setMatchingHelpCandidate(i);
+            setHelpCandidate(helpCandidate, i);
             break;
         }
     }
 }
 
+void HoverHandler::decorateToolTip(TextEditor::ITextEditor *editor)
+{
+    if (matchingHelpCandidate() != -1) {
+        const QString &contents = getDocContents(extendToolTips(editor));
+        if (!contents.isEmpty()) {
+            appendToolTip(contents);
+        } else {
+            QString tip = Qt::escape(toolTip());
+            tip.prepend(QLatin1String("<nobr>"));
+            tip.append(QLatin1String("</nobr>"));
+            setToolTip(tip);
+        }
+    }
+}
+
+void HoverHandler::operateTooltip(TextEditor::ITextEditor *editor, const QPoint &point)
+{
+    if (toolTip().isEmpty())
+        TextEditor::ToolTip::instance()->hide();
+    else {
+        if (m_colorTip.isValid()) {
+            TextEditor::ToolTip::instance()->showColor(point, m_colorTip, editor->widget());
+        } else {
+            if (matchingHelpCandidate() != -1)
+                addF1ToToolTip();
+
+            TextEditor::ToolTip::instance()->showText(point, toolTip(), editor->widget());
+        }
+    }
+}
+
 QString HoverHandler::prettyPrint(const QmlJS::Interpreter::Value *value,
                                   QmlJS::Interpreter::Context *context)
 {
@@ -300,13 +256,13 @@ QString HoverHandler::prettyPrint(const QmlJS::Interpreter::Value *value,
             const QString className = objectValue->className();
 
             if (! className.isEmpty())
-                m_helpCandidates.append(className);
+                addHelpCandidate(HelpCandidate(className, HelpCandidate::QML));
 
             objectValue = objectValue->prototype(context);
         } while (objectValue);
 
-        if (! m_helpCandidates.isEmpty())
-            return m_helpCandidates.first();
+        if (! helpCandidates().isEmpty())
+            return helpCandidates().first().m_helpId;
     } else if (const Interpreter::QmlEnumValue *enumValue =
                dynamic_cast<const Interpreter::QmlEnumValue *>(value)) {
         return enumValue->name();
diff --git a/src/plugins/qmljseditor/qmljshoverhandler.h b/src/plugins/qmljseditor/qmljshoverhandler.h
index 49f763deef236a8c9ebdaf0d4dac54b656d597b7..13d0cb2db57f2a509ae53838e33a928a673e381a 100644
--- a/src/plugins/qmljseditor/qmljshoverhandler.h
+++ b/src/plugins/qmljseditor/qmljshoverhandler.h
@@ -32,15 +32,12 @@
 
 #include <qmljs/qmljsmodelmanagerinterface.h>
 #include <qmljs/qmljslookupcontext.h>
+#include <texteditor/basehoverhandler.h>
 
 #include <QtCore/QObject>
 #include <QtCore/QStringList>
 #include <QtGui/QColor>
 
-QT_BEGIN_NAMESPACE
-class QPoint;
-QT_END_NAMESPACE
-
 namespace Core {
 class IEditor;
 }
@@ -55,23 +52,20 @@ namespace Internal {
 class SemanticInfo;
 class QmlJSTextEditor;
 
-class HoverHandler : public QObject
+class HoverHandler : public TextEditor::BaseHoverHandler
 {
     Q_OBJECT
-
 public:
     HoverHandler(QObject *parent = 0);
 
-public slots:
-    void showToolTip(TextEditor::ITextEditor *editor, const QPoint &point, int pos);
-    void updateContextHelpId(TextEditor::ITextEditor *editor, int pos);
-
-private slots:
-    void editorOpened(Core::IEditor *editor);
-
 private:
-    void resetMatchings();
-    void identifyMatch(TextEditor::ITextEditor *editor, int pos);
+    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);
+    virtual void operateTooltip(TextEditor::ITextEditor *editor, const QPoint &point);
+
     bool matchDiagnosticMessage(QmlJSTextEditor *qmlEditor, int pos);
     bool matchColorItem(const QmlJS::LookupContext::Ptr &lookupContext,
                         const QmlJS::Document::Ptr &qmlDocument,
@@ -80,15 +74,10 @@ private:
     void handleOrdinaryMatch(const QmlJS::LookupContext::Ptr &lookupContext,
                              QmlJS::AST::Node *node);
 
-    void evaluateHelpCandidates();
-
     QString prettyPrint(const QmlJS::Interpreter::Value *value,
                         QmlJS::Interpreter::Context *context);
 
     QmlJS::ModelManagerInterface *m_modelManager;
-    int m_matchingHelpCandidate;
-    QStringList m_helpCandidates;
-    QString m_toolTip;
     QColor m_colorTip;
 };
 
diff --git a/src/plugins/texteditor/basehoverhandler.cpp b/src/plugins/texteditor/basehoverhandler.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d993bb124664312ff7eb8667d65974bc29bda0e7
--- /dev/null
+++ b/src/plugins/texteditor/basehoverhandler.cpp
@@ -0,0 +1,260 @@
+/**************************************************************************
+**
+** 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 "basehoverhandler.h"
+#include "itexteditor.h"
+#include "basetexteditor.h"
+#include "displaysettings.h"
+#include "tooltip.h"
+
+#include <coreplugin/icore.h>
+#include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/helpmanager.h>
+#include <coreplugin/uniqueidmanager.h>
+#include <debugger/debuggerconstants.h>
+
+#include <QtCore/QPoint>
+
+using namespace TextEditor;
+using namespace Core;
+
+BaseHoverHandler::BaseHoverHandler(QObject *parent) :
+    QObject(parent), m_matchingHelpCandidate(-1)
+{
+    // Listen for editor opened events in order to connect to tooltip/helpid requests
+    connect(ICore::instance()->editorManager(), SIGNAL(editorOpened(Core::IEditor *)),
+            this, SLOT(editorOpened(Core::IEditor *)));
+}
+
+void BaseHoverHandler::editorOpened(Core::IEditor *editor)
+{
+    if (acceptEditor(editor)) {
+        BaseTextEditorEditable *textEditor = qobject_cast<BaseTextEditorEditable *>(editor);
+        if (textEditor) {
+            connect(textEditor, SIGNAL(tooltipRequested(TextEditor::ITextEditor*, QPoint, int)),
+                    this, SLOT(showToolTip(TextEditor::ITextEditor*, QPoint, int)));
+
+            connect(textEditor, SIGNAL(contextHelpIdRequested(TextEditor::ITextEditor*, int)),
+                    this, SLOT(updateContextHelpId(TextEditor::ITextEditor*, int)));
+        }
+    }
+}
+
+void BaseHoverHandler::showToolTip(TextEditor::ITextEditor *editor, const QPoint &point, int pos)
+{
+    BaseTextEditor *baseEditor = baseTextEditor(editor);
+    if (!baseEditor)
+        return;
+
+    editor->setContextHelpId(QString());
+
+    ICore *core = ICore::instance();
+    const int dbgContext =
+        core->uniqueIDManager()->uniqueIdentifier(Debugger::Constants::C_DEBUGMODE);
+    if (core->hasContext(dbgContext))
+        return;
+
+    process(editor, pos);
+
+    const QPoint &actualPoint = point - QPoint(0,
+#ifdef Q_WS_WIN
+    24
+#else
+    16
+#endif
+    );
+
+    operateTooltip(editor, actualPoint);
+}
+
+void BaseHoverHandler::updateContextHelpId(TextEditor::ITextEditor *editor, int pos)
+{
+    // 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)
+        process(editor, pos);
+
+    if (m_matchingHelpCandidate != -1)
+        editor->setContextHelpId(m_helpCandidates.at(m_matchingHelpCandidate).m_helpId);
+    else
+        editor->setContextHelpId(QString());
+}
+
+void BaseHoverHandler::setToolTip(const QString &tooltip)
+{ m_toolTip = tooltip; }
+
+const QString &BaseHoverHandler::toolTip() const
+{ return m_toolTip; }
+
+void BaseHoverHandler::appendToolTip(const QString &extension)
+{ m_toolTip.append(extension); }
+
+void BaseHoverHandler::addF1ToToolTip()
+{
+    m_toolTip = QString(QLatin1String("<table><tr><td valign=middle>%1</td><td>&nbsp;&nbsp;"
+                                      "<img src=\":/cppeditor/images/f1.png\"></td>"
+                                      "</tr></table>")).arg(m_toolTip);
+}
+
+void BaseHoverHandler::reset()
+{
+    m_matchingHelpCandidate = -1;
+    m_helpCandidates.clear();
+    m_toolTip.clear();
+
+    resetExtras();
+}
+
+void BaseHoverHandler::process(ITextEditor *editor, int pos)
+{
+    reset();
+    identifyMatch(editor, pos);
+    evaluateHelpCandidates();
+    decorateToolTip(editor);
+}
+
+void BaseHoverHandler::resetExtras()
+{}
+
+void BaseHoverHandler::evaluateHelpCandidates()
+{
+    for (int i = 0; i < m_helpCandidates.size(); ++i) {
+        if (helpIdExists(m_helpCandidates.at(i).m_helpId)) {
+            m_matchingHelpCandidate = i;
+            return;
+        }
+    }
+}
+
+void BaseHoverHandler::decorateToolTip(ITextEditor *)
+{}
+
+void BaseHoverHandler::operateTooltip(ITextEditor *editor, const QPoint &point)
+{
+    if (m_toolTip.isEmpty()) {
+        TextEditor::ToolTip::instance()->hide();
+    } else {
+        if (m_matchingHelpCandidate != -1)
+            addF1ToToolTip();
+
+        TextEditor::ToolTip::instance()->showText(point, m_toolTip, editor->widget());
+    }
+}
+
+bool BaseHoverHandler::helpIdExists(const QString &helpId) const
+{
+    if (!Core::HelpManager::instance()->linksForIdentifier(helpId).isEmpty())
+        return true;
+    return false;
+}
+
+void BaseHoverHandler::addHelpCandidate(const HelpCandidate &helpCandidate)
+{ m_helpCandidates.append(helpCandidate); }
+
+void BaseHoverHandler::setHelpCandidate(const HelpCandidate &helpCandidate, int index)
+{ m_helpCandidates[index] = helpCandidate; }
+
+const QList<BaseHoverHandler::HelpCandidate> &BaseHoverHandler::helpCandidates() const
+{ return m_helpCandidates; }
+
+const BaseHoverHandler::HelpCandidate &BaseHoverHandler::helpCandidate(int index) const
+{ return m_helpCandidates.at(index); }
+
+void BaseHoverHandler::setMatchingHelpCandidate(int index)
+{ m_matchingHelpCandidate = index; }
+
+int BaseHoverHandler::matchingHelpCandidate() const
+{ return m_matchingHelpCandidate; }
+
+QString BaseHoverHandler::getDocContents(const bool extended)
+{
+    Q_ASSERT(m_matchingHelpCandidate >= 0);
+
+    return getDocContents(m_helpCandidates.at(m_matchingHelpCandidate), extended);
+}
+
+QString BaseHoverHandler::getDocContents(const HelpCandidate &help, const bool extended)
+{
+    if (extended)
+        m_htmlDocExtractor.extractExtendedContents(1500, true);
+    else
+        m_htmlDocExtractor.extractFirstParagraphOnly();
+
+    QString contents;
+    QMap<QString, QUrl> helpLinks =
+        Core::HelpManager::instance()->linksForIdentifier(help.m_helpId);
+    foreach (const QUrl &url, helpLinks) {
+        const QByteArray &html = Core::HelpManager::instance()->fileData(url);
+        switch (help.m_category) {
+        case HelpCandidate::Brief:
+            contents = m_htmlDocExtractor.getClassOrNamespaceBrief(html, help.m_docMark);
+            break;
+        case HelpCandidate::ClassOrNamespace:
+            contents = m_htmlDocExtractor.getClassOrNamespaceDescription(html, help.m_docMark);
+            break;
+        case HelpCandidate::Function:
+            contents = m_htmlDocExtractor.getFunctionDescription(html, help.m_docMark);
+            break;
+        case HelpCandidate::Enum:
+            contents = m_htmlDocExtractor.getEnumDescription(html, help.m_docMark);
+            break;
+        case HelpCandidate::Typedef:
+            contents = m_htmlDocExtractor.getTypedefDescription(html, help.m_docMark);
+            break;
+        case HelpCandidate::Macro:
+            contents = m_htmlDocExtractor.getMacroDescription(html, help.m_docMark);
+            break;
+        case HelpCandidate::QML:
+            contents = m_htmlDocExtractor.getQMLItemDescription(html, help.m_docMark);
+            break;
+
+        default:
+            break;
+        }
+
+        if (!contents.isEmpty())
+            break;
+    }
+    return contents;
+}
+
+BaseTextEditor *BaseHoverHandler::baseTextEditor(ITextEditor *editor)
+{
+    if (!editor)
+        return 0;
+    return qobject_cast<BaseTextEditor *>(editor->widget());
+}
+
+bool BaseHoverHandler::extendToolTips(ITextEditor *editor)
+{
+    BaseTextEditor *baseEditor = baseTextEditor(editor);
+    if (baseEditor && baseEditor->displaySettings().m_extendTooltips)
+        return true;
+    return false;
+}
diff --git a/src/plugins/texteditor/basehoverhandler.h b/src/plugins/texteditor/basehoverhandler.h
new file mode 100644
index 0000000000000000000000000000000000000000..587f257210bd9ba5837a94a2fdc545b898dc1489
--- /dev/null
+++ b/src/plugins/texteditor/basehoverhandler.h
@@ -0,0 +1,133 @@
+/**************************************************************************
+**
+** 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 BASEHOVERHANDLER_H
+#define BASEHOVERHANDLER_H
+
+#include "texteditor_global.h"
+
+#include <utils/htmldocextractor.h>
+
+#include <QtCore/QObject>
+#include <QtCore/QString>
+#include <QtCore/QList>
+
+QT_BEGIN_NAMESPACE
+class QPoint;
+QT_END_NAMESPACE
+
+namespace Core {
+class IEditor;
+}
+
+namespace TextEditor {
+
+class ITextEditor;
+class BaseTextEditor;
+
+class TEXTEDITOR_EXPORT BaseHoverHandler : public QObject
+{
+    Q_OBJECT
+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 {
+            ClassOrNamespace,
+            Enum,
+            Typedef,
+            Macro,
+            Brief,
+            Function,
+            QML,
+            Unknown
+        };
+
+        HelpCandidate(const QString &helpId, Category category) :
+            m_helpId(helpId), m_docMark(helpId), m_category(category)
+        {}
+        HelpCandidate(const QString &helpId, const QString &docMark, Category category) :
+            m_helpId(helpId), m_docMark(docMark), m_category(category)
+        {}
+        QString m_helpId;
+        QString m_docMark;
+        Category m_category;
+    };
+
+    void addHelpCandidate(const HelpCandidate &helpCandidate);
+    void setHelpCandidate(const HelpCandidate &helpCandidate, int index);
+    const QList<HelpCandidate> &helpCandidates() const;
+    const HelpCandidate &helpCandidate(int index) const;
+
+    void setMatchingHelpCandidate(int index);
+    int matchingHelpCandidate() const;
+
+    bool helpIdExists(const QString &helpId) const;
+
+    QString getDocContents(const bool extended);
+    QString getDocContents(const HelpCandidate &help, const bool extended);
+
+    static BaseTextEditor *baseTextEditor(ITextEditor *editor);
+    static bool extendToolTips(ITextEditor *editor);
+
+private:
+    void reset();
+    void process(ITextEditor *editor, int pos);
+
+    virtual bool acceptEditor(Core::IEditor *editor) = 0;
+    virtual void identifyMatch(ITextEditor *editor, int pos) = 0;
+
+    virtual void resetExtras();
+    virtual void evaluateHelpCandidates();
+    virtual void decorateToolTip(ITextEditor *editor);
+    virtual void operateTooltip(ITextEditor *editor, const QPoint &point);
+
+    int m_matchingHelpCandidate;
+    QList<HelpCandidate> m_helpCandidates;
+    QString m_toolTip;
+    Utils::HtmlDocExtractor m_htmlDocExtractor;
+};
+
+} // namespace TextEditor
+
+#endif // BASEHOVERHANDLER_H
diff --git a/src/plugins/texteditor/texteditor.pro b/src/plugins/texteditor/texteditor.pro
index 14314433f46bd2d2a206a0115dbc2285f3fd7a8f..df3e8f380de7c39ee719c7fd9c5bed3877ff9a89 100644
--- a/src/plugins/texteditor/texteditor.pro
+++ b/src/plugins/texteditor/texteditor.pro
@@ -67,7 +67,8 @@ SOURCES += texteditorplugin.cpp \
     outlinefactory.cpp \
     tooltip/tooltip.cpp \
     tooltip/tips.cpp \
-    tooltip/tipcontents.cpp
+    tooltip/tipcontents.cpp \
+    basehoverhandler.cpp
 
 HEADERS += texteditorplugin.h \
     textfilewizard.h \
@@ -136,7 +137,8 @@ HEADERS += texteditorplugin.h \
     ioutlinewidget.h \
     tooltip/tooltip.h \
     tooltip/tips.h \
-    tooltip/tipcontents.h
+    tooltip/tipcontents.h \
+    basehoverhandler.h
 
 FORMS += behaviorsettingspage.ui \
     displaysettingspage.ui \