From ba12a3390eb0ec1a54c226ed137764a5efc2b6b0 Mon Sep 17 00:00:00 2001
From: Leandro Melo <leandro.melo@nokia.com>
Date: Fri, 27 Aug 2010 12:11:55 +0200
Subject: [PATCH] Refactor how base hover handler manipulates the help items
 (qt docs interaction).

---
 src/plugins/cppeditor/cppelementevaluator.cpp |  22 +--
 src/plugins/cppeditor/cppelementevaluator.h   |   9 +-
 src/plugins/cppeditor/cpphoverhandler.cpp     |  51 +++----
 src/plugins/cppeditor/cpphoverhandler.h       |   1 -
 src/plugins/qmljseditor/qmljshoverhandler.cpp |  85 +++++------
 src/plugins/qmljseditor/qmljshoverhandler.h   |  17 ++-
 src/plugins/texteditor/basehoverhandler.cpp   | 140 ++++--------------
 src/plugins/texteditor/basehoverhandler.h     |  54 +------
 src/plugins/texteditor/helpitem.cpp           | 123 +++++++++++++++
 src/plugins/texteditor/helpitem.h             |  79 ++++++++++
 src/plugins/texteditor/texteditor.pro         |   6 +-
 11 files changed, 333 insertions(+), 254 deletions(-)
 create mode 100644 src/plugins/texteditor/helpitem.cpp
 create mode 100644 src/plugins/texteditor/helpitem.h

diff --git a/src/plugins/cppeditor/cppelementevaluator.cpp b/src/plugins/cppeditor/cppelementevaluator.cpp
index 8086b89e0b5..09018ffe7ee 100644
--- a/src/plugins/cppeditor/cppelementevaluator.cpp
+++ b/src/plugins/cppeditor/cppelementevaluator.cpp
@@ -199,16 +199,16 @@ void CppElementEvaluator::handleLookupItemMatch(const Snapshot &snapshot,
 }
 
 // CppElement
-CppElement::CppElement() : m_helpCategory(CppHoverHandler::HelpCandidate::Unknown)
+CppElement::CppElement() : m_helpCategory(TextEditor::HelpItem::Unknown)
 {}
 
 CppElement::~CppElement()
 {}
 
-void CppElement::setHelpCategory(const CppHoverHandler::HelpCandidate::Category &cat)
+void CppElement::setHelpCategory(const TextEditor::HelpItem::Category &cat)
 { m_helpCategory = cat; }
 
-const CppHoverHandler::HelpCandidate::Category &CppElement::helpCategory() const
+const TextEditor::HelpItem::Category &CppElement::helpCategory() const
 { return m_helpCategory; }
 
 void CppElement::setHelpIdCandidates(const QStringList &candidates)
@@ -273,7 +273,7 @@ CppInclude::CppInclude(const Document::Include &includeFile) :
     m_path(QDir::toNativeSeparators(includeFile.fileName())),
     m_fileName(QFileInfo(includeFile.fileName()).fileName())
 {
-    setHelpCategory(CppHoverHandler::HelpCandidate::Brief);
+    setHelpCategory(TextEditor::HelpItem::Brief);
     setHelpIdCandidates(QStringList(m_fileName));
     setHelpMark(m_fileName);
     setLink(CPPEditor::Link(m_path));
@@ -289,7 +289,7 @@ const QString &CppInclude::fileName() const
 // CppMacro
 CppMacro::CppMacro(const Macro &macro) : CppElement()
 {
-    setHelpCategory(CppHoverHandler::HelpCandidate::Macro);
+    setHelpCategory(TextEditor::HelpItem::Macro);
     setHelpIdCandidates(QStringList(macro.name()));
     setHelpMark(macro.name());
     setLink(CPPEditor::Link(macro.fileName(), macro.line()));
@@ -366,7 +366,7 @@ const QIcon &CppDeclarableElement::icon() const
 // CppNamespace
 CppNamespace::CppNamespace(Symbol *declaration) : CppDeclarableElement(declaration)
 {
-    setHelpCategory(CppHoverHandler::HelpCandidate::ClassOrNamespace);
+    setHelpCategory(TextEditor::HelpItem::ClassOrNamespace);
 }
 
 CppNamespace::~CppNamespace()
@@ -375,7 +375,7 @@ CppNamespace::~CppNamespace()
 // CppClass
 CppClass::CppClass(Symbol *declaration) : CppDeclarableElement(declaration)
 {
-    setHelpCategory(CppHoverHandler::HelpCandidate::ClassOrNamespace);
+    setHelpCategory(TextEditor::HelpItem::ClassOrNamespace);
 }
 
 CppClass::~CppClass()
@@ -418,7 +418,7 @@ const QList<CppClass> &CppClass::bases() const
 // CppFunction
 CppFunction::CppFunction(Symbol *declaration) : CppDeclarableElement(declaration)
 {
-    setHelpCategory(CppHoverHandler::HelpCandidate::Function);
+    setHelpCategory(TextEditor::HelpItem::Function);
 
     const FullySpecifiedType &type = declaration->type();
 
@@ -438,7 +438,7 @@ CppFunction::~CppFunction()
 // CppEnum
 CppEnum::CppEnum(Symbol *declaration) : CppDeclarableElement(declaration)
 {
-    setHelpCategory(CppHoverHandler::HelpCandidate::Enum);
+    setHelpCategory(TextEditor::HelpItem::Enum);
 
     if (declaration->enclosingScope()->isEnum()) {
         Symbol *enumSymbol = declaration->enclosingScope()->asEnum();
@@ -455,7 +455,7 @@ CppEnum::~CppEnum()
 CppTypedef::CppTypedef(Symbol *declaration) :
     CppDeclarableElement(declaration)
 {
-    setHelpCategory(CppHoverHandler::HelpCandidate::Typedef);
+    setHelpCategory(TextEditor::HelpItem::Typedef);
 }
 
 CppTypedef::~CppTypedef()
@@ -488,7 +488,7 @@ CppVariable::CppVariable(Symbol *declaration, const LookupContext &context, Scop
                 const QString &name =
                     overview.prettyName(LookupContext::fullyQualifiedName(symbol));
                 setTooltip(name);
-                setHelpCategory(CppHoverHandler::HelpCandidate::ClassOrNamespace);
+                setHelpCategory(TextEditor::HelpItem::ClassOrNamespace);
                 setHelpMark(name);
                 setHelpIdCandidates(QStringList(name));
             }
diff --git a/src/plugins/cppeditor/cppelementevaluator.h b/src/plugins/cppeditor/cppelementevaluator.h
index 92a454877b2..6a34f4666d4 100644
--- a/src/plugins/cppeditor/cppelementevaluator.h
+++ b/src/plugins/cppeditor/cppelementevaluator.h
@@ -31,7 +31,8 @@
 #define CPPHIGHLEVELMODEL_H
 
 #include "cppeditor.h"
-#include "cpphoverhandler.h"
+
+#include <texteditor/helpitem.h>
 
 #include <cplusplus/CppDocument.h>
 #include <cplusplus/Overview.h>
@@ -88,7 +89,7 @@ class CppElement
 public:
     virtual ~CppElement();
 
-    const CppHoverHandler::HelpCandidate::Category &helpCategory() const;
+    const TextEditor::HelpItem::Category &helpCategory() const;
     const QStringList &helpIdCandidates() const;
     const QString &helpMark() const;
     const CPPEditor::Link &link() const;
@@ -97,7 +98,7 @@ public:
 protected:
     CppElement();
 
-    void setHelpCategory(const CppHoverHandler::HelpCandidate::Category &category);
+    void setHelpCategory(const TextEditor::HelpItem::Category &category);
     void setLink(const CPPEditor::Link &link);
     void setTooltip(const QString &tooltip);
     void setHelpIdCandidates(const QStringList &candidates);
@@ -105,7 +106,7 @@ protected:
     void setHelpMark(const QString &mark);
 
 private:
-    CppHoverHandler::HelpCandidate::Category m_helpCategory;
+    TextEditor::HelpItem::Category m_helpCategory;
     QStringList m_helpIdCandidates;
     QString m_helpMark;
     CPPEditor::Link m_link;
diff --git a/src/plugins/cppeditor/cpphoverhandler.cpp b/src/plugins/cppeditor/cpphoverhandler.cpp
index 15922d906ed..47c7ee97fb2 100644
--- a/src/plugins/cppeditor/cpphoverhandler.cpp
+++ b/src/plugins/cppeditor/cpphoverhandler.cpp
@@ -33,10 +33,12 @@
 
 #include <coreplugin/editormanager/ieditor.h>
 #include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/helpmanager.h>
 #include <cpptools/cppmodelmanagerinterface.h>
 #include <extensionsystem/pluginmanager.h>
 #include <texteditor/itexteditor.h>
 #include <texteditor/basetexteditor.h>
+#include <texteditor/helpitem.h>
 
 #include <QtGui/QTextCursor>
 
@@ -84,27 +86,21 @@ void CppHoverHandler::identifyMatch(TextEditor::ITextEditor *editor, int pos)
         QSharedPointer<CppElement> cppElement = evaluator.identifyCppElement();
         if (!cppElement.isNull()) {
             setToolTip(cppElement->tooltip());
-            foreach (const QString &helpId, cppElement->helpIdCandidates())
-                addHelpCandidate(HelpCandidate(helpId,
-                                               cppElement->helpMark(),
-                                               cppElement->helpCategory()));
-        }
-    }
-}
-
-void CppHoverHandler::evaluateHelpCandidates()
-{
-    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 = helpCandidates().at(i);
-            const QString &helpId = removeClassNameQualification(candidate.m_helpId);
-            if (helpIdExists(helpId)) {
-                candidate.m_helpId = helpId;
-                setHelpCandidate(candidate, i);
-                setMatchingHelpCandidate(i);
+            foreach (QString helpId, cppElement->helpIdCandidates()) {
+                bool found = false;
+                if (!Core::HelpManager::instance()->linksForIdentifier(helpId).isEmpty()) {
+                    found = true;
+                } else {
+                    helpId = removeClassNameQualification(helpId);
+                    if (!Core::HelpManager::instance()->linksForIdentifier(helpId).isEmpty())
+                        found = true;
+                }
+                if (found) {
+                    setLastHelpItemIdentified(TextEditor::HelpItem(helpId,
+                                                                   cppElement->helpMark(),
+                                                                   cppElement->helpCategory()));
+                    break;
+                }
             }
         }
     }
@@ -112,11 +108,15 @@ void CppHoverHandler::evaluateHelpCandidates()
 
 void CppHoverHandler::decorateToolTip(TextEditor::ITextEditor *editor)
 {
-    if (matchingHelpCandidate() != -1) {
-        const QString &contents = getDocContents(extendToolTips(editor));
+    CPPEditor *cppEditor = qobject_cast<CPPEditor *>(editor->widget());
+    if (!cppEditor)
+        return;
+
+    const TextEditor::HelpItem &help = lastHelpItemIdentified();
+    if (help.isValid()) {
+        const QString &contents = help.extractContent(extendToolTips(editor));
         if (!contents.isEmpty()) {
-            HelpCandidate::Category cat = helpCandidate(matchingHelpCandidate()).m_category;
-            if (cat == HelpCandidate::ClassOrNamespace)
+            if (help.category() == TextEditor::HelpItem::ClassOrNamespace)
                 appendToolTip(contents);
             else
                 setToolTip(contents);
@@ -126,5 +126,6 @@ void CppHoverHandler::decorateToolTip(TextEditor::ITextEditor *editor)
             tip.append(QLatin1String("</nobr>"));
             setToolTip(tip);
         }
+        addF1ToToolTip();
     }
 }
diff --git a/src/plugins/cppeditor/cpphoverhandler.h b/src/plugins/cppeditor/cpphoverhandler.h
index 6c7de5cd1fb..5cce9980583 100644
--- a/src/plugins/cppeditor/cpphoverhandler.h
+++ b/src/plugins/cppeditor/cpphoverhandler.h
@@ -55,7 +55,6 @@ public:
 private:
     virtual bool acceptEditor(Core::IEditor *editor);
     virtual void identifyMatch(TextEditor::ITextEditor *editor, int pos);
-    virtual void evaluateHelpCandidates();
     virtual void decorateToolTip(TextEditor::ITextEditor *editor);
 };
 
diff --git a/src/plugins/qmljseditor/qmljshoverhandler.cpp b/src/plugins/qmljseditor/qmljshoverhandler.cpp
index 2e95585b92f..100d8fb34fa 100644
--- a/src/plugins/qmljseditor/qmljshoverhandler.cpp
+++ b/src/plugins/qmljseditor/qmljshoverhandler.cpp
@@ -33,6 +33,7 @@
 
 #include <coreplugin/editormanager/ieditor.h>
 #include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/helpmanager.h>
 #include <extensionsystem/pluginmanager.h>
 #include <qmljs/qmljsinterpreter.h>
 #include <qmljs/parser/qmljsast_p.h>
@@ -40,9 +41,12 @@
 #include <qmljs/qmljscheck.h>
 #include <texteditor/itexteditor.h>
 #include <texteditor/basetexteditor.h>
+#include <texteditor/helpitem.h>
 #include <texteditor/tooltip/tooltip.h>
 #include <texteditor/tooltip/tipcontents.h>
 
+#include <QtCore/QList>
+
 using namespace Core;
 using namespace QmlJS;
 using namespace QmlJSEditor;
@@ -95,6 +99,8 @@ bool HoverHandler::acceptEditor(IEditor *editor)
 
 void HoverHandler::identifyMatch(TextEditor::ITextEditor *editor, int pos)
 {
+    reset();
+
     if (!m_modelManager)
         return;
 
@@ -114,8 +120,12 @@ void HoverHandler::identifyMatch(TextEditor::ITextEditor *editor, int pos)
         const Document::Ptr qmlDocument = semanticInfo.document;
         LookupContext::Ptr lookupContext = semanticInfo.lookupContext(astPath);
 
-        if (!matchColorItem(lookupContext, qmlDocument, astPath, pos))
+        if (!matchColorItem(lookupContext, qmlDocument, astPath, pos)) {
             handleOrdinaryMatch(lookupContext, semanticInfo.nodeUnderCursor(pos));
+            const QString &helpId = qmlHelpId(toolTip());
+            if (!helpId.isEmpty())
+                setLastHelpItemIdentified(TextEditor::HelpItem(helpId, TextEditor::HelpItem::QML));
+        }
     }
 }
 
@@ -192,43 +202,15 @@ 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);
-        setToolTip(prettyPrint(value, lookupContext->context()));
+        prettyPrintTooltip(value, lookupContext->context());
     }
 }
 
-void HoverHandler::resetExtras()
+void HoverHandler::reset()
 {
     m_colorTip = QColor();
 }
 
-void HoverHandler::evaluateHelpCandidates()
-{
-    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())
@@ -239,9 +221,6 @@ void HoverHandler::operateTooltip(TextEditor::ITextEditor *editor, const QPoint
                                                   TextEditor::ColorContent(m_colorTip),
                                                   editor->widget());
         } else {
-            if (matchingHelpCandidate() != -1)
-                addF1ToToolTip();
-
             TextEditor::ToolTip::instance()->show(point,
                                                   TextEditor::TextContent(toolTip()),
                                                   editor->widget());
@@ -249,33 +228,41 @@ void HoverHandler::operateTooltip(TextEditor::ITextEditor *editor, const QPoint
     }
 }
 
-QString HoverHandler::prettyPrint(const QmlJS::Interpreter::Value *value,
-                                  const QmlJS::Interpreter::Context *context)
+void HoverHandler::prettyPrintTooltip(const QmlJS::Interpreter::Value *value,
+                                      const QmlJS::Interpreter::Context *context)
 {
     if (! value)
-        return QString();
+        return;
 
     if (const Interpreter::ObjectValue *objectValue = value->asObjectValue()) {
+        bool found = false;
         do {
             const QString className = objectValue->className();
 
-            if (! className.isEmpty())
-                addHelpCandidate(HelpCandidate(className, HelpCandidate::QML));
+            if (! className.isEmpty()) {
+                found = !qmlHelpId(className).isEmpty();
+                if (toolTip().isEmpty() || found)
+                    setToolTip(className);
+            }
 
             objectValue = objectValue->prototype(context);
-        } while (objectValue);
-
-        if (! helpCandidates().isEmpty())
-            return helpCandidates().first().m_helpId;
+        } while (objectValue && !found);
     } else if (const Interpreter::QmlEnumValue *enumValue =
                dynamic_cast<const Interpreter::QmlEnumValue *>(value)) {
-        return enumValue->name();
+        setToolTip(enumValue->name());
     }
 
-    QString typeId = context->engine()->typeId(value);
-
-    if (typeId == QLatin1String("undefined"))
-        typeId.clear();
+    if (toolTip().isEmpty()) {
+        QString typeId = context->engine()->typeId(value);
+        if (typeId != QLatin1String("undefined"))
+            setToolTip(typeId);
+    }
+}
 
-    return typeId;
+QString HoverHandler::qmlHelpId(const QString &itemName) const
+{
+    QString helpId(QLatin1String("QML.") + itemName);
+    if (!Core::HelpManager::instance()->linksForIdentifier(helpId).isEmpty())
+        return helpId;
+    return QString();
 }
diff --git a/src/plugins/qmljseditor/qmljshoverhandler.h b/src/plugins/qmljseditor/qmljshoverhandler.h
index e8b3290268c..77e967e39df 100644
--- a/src/plugins/qmljseditor/qmljshoverhandler.h
+++ b/src/plugins/qmljseditor/qmljshoverhandler.h
@@ -34,10 +34,12 @@
 #include <qmljs/qmljslookupcontext.h>
 #include <texteditor/basehoverhandler.h>
 
-#include <QtCore/QObject>
-#include <QtCore/QStringList>
 #include <QtGui/QColor>
 
+QT_BEGIN_NAMESPACE
+template <class> class QList;
+QT_END_NAMESPACE
+
 namespace Core {
 class IEditor;
 }
@@ -59,11 +61,10 @@ public:
     HoverHandler(QObject *parent = 0);
 
 private:
+    void reset();
+
     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);
@@ -74,8 +75,10 @@ private:
     void handleOrdinaryMatch(const QmlJS::LookupContext::Ptr &lookupContext,
                              QmlJS::AST::Node *node);
 
-    QString prettyPrint(const QmlJS::Interpreter::Value *value,
-                        const QmlJS::Interpreter::Context *context);
+    void prettyPrintTooltip(const QmlJS::Interpreter::Value *value,
+                            const QmlJS::Interpreter::Context *context);
+
+    QString qmlHelpId(const QString &itemName) const;
 
     QmlJS::ModelManagerInterface *m_modelManager;
     QColor m_colorTip;
diff --git a/src/plugins/texteditor/basehoverhandler.cpp b/src/plugins/texteditor/basehoverhandler.cpp
index 1a0ec60f450..8bb60941d73 100644
--- a/src/plugins/texteditor/basehoverhandler.cpp
+++ b/src/plugins/texteditor/basehoverhandler.cpp
@@ -45,8 +45,7 @@
 using namespace TextEditor;
 using namespace Core;
 
-BaseHoverHandler::BaseHoverHandler(QObject *parent) :
-    QObject(parent), m_matchingHelpCandidate(-1)
+BaseHoverHandler::BaseHoverHandler(QObject *parent) : QObject(parent)
 {
     // Listen for editor opened events in order to connect to tooltip/helpid requests
     connect(ICore::instance()->editorManager(), SIGNAL(editorOpened(Core::IEditor *)),
@@ -102,13 +101,13 @@ void BaseHoverHandler::updateContextHelpId(TextEditor::ITextEditor *editor, int
 
     // 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)
+    if (!ToolTip::instance()->isVisible() || !lastHelpItemIdentified().isValid())
         process(editor, pos);
 
-    if (m_matchingHelpCandidate != -1)
-        editor->setContextHelpId(m_helpCandidates.at(m_matchingHelpCandidate).m_helpId);
+    if (lastHelpItemIdentified().isValid())
+        editor->setContextHelpId(lastHelpItemIdentified().helpId());
     else
-        editor->setContextHelpId(QString());
+        editor->setContextHelpId(QString()); // Make sure it's an empty string.
 }
 
 void BaseHoverHandler::setToolTip(const QString &tooltip)
@@ -127,126 +126,51 @@ void BaseHoverHandler::addF1ToToolTip()
                                       "</tr></table>")).arg(m_toolTip);
 }
 
-void BaseHoverHandler::reset()
+void BaseHoverHandler::setLastHelpItemIdentified(const HelpItem &help)
+{ m_lastHelpItemIdentified = help; }
+
+const HelpItem &BaseHoverHandler::lastHelpItemIdentified() const
+{ return m_lastHelpItemIdentified; }
+
+void BaseHoverHandler::clear()
 {
-    m_matchingHelpCandidate = -1;
-    m_helpCandidates.clear();
     m_toolTip.clear();
-
-    resetExtras();
+    m_lastHelpItemIdentified = HelpItem();
 }
 
 void BaseHoverHandler::process(ITextEditor *editor, int pos)
 {
-    reset();
+    clear();
     identifyMatch(editor, pos);
-    evaluateHelpCandidates();
     decorateToolTip(editor);
 }
 
-void BaseHoverHandler::resetExtras()
-{}
-
-void BaseHoverHandler::evaluateHelpCandidates()
+void BaseHoverHandler::decorateToolTip(ITextEditor *editor)
 {
-    for (int i = 0; i < m_helpCandidates.size(); ++i) {
-        if (helpIdExists(m_helpCandidates.at(i).m_helpId)) {
-            m_matchingHelpCandidate = i;
-            return;
+    BaseTextEditor *baseEditor = baseTextEditor(editor);
+    if (!baseEditor)
+        return;
+
+    if (lastHelpItemIdentified().isValid()) {
+        const QString &contents = lastHelpItemIdentified().extractContent(extendToolTips(editor));
+        if (!contents.isEmpty()) {
+            appendToolTip(contents);
+        } else {
+            QString tip = Qt::escape(toolTip());
+            tip.prepend(QLatin1String("<nobr>"));
+            tip.append(QLatin1String("</nobr>"));
+            setToolTip(tip);
         }
+        addF1ToToolTip();
     }
 }
 
-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();
-
-        ToolTip::instance()->show(point, TextContent(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);
+    if (m_toolTip.isEmpty())
+        ToolTip::instance()->hide();
     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;
+        ToolTip::instance()->show(point, TextContent(m_toolTip), editor->widget());
 }
 
 BaseTextEditor *BaseHoverHandler::baseTextEditor(ITextEditor *editor)
diff --git a/src/plugins/texteditor/basehoverhandler.h b/src/plugins/texteditor/basehoverhandler.h
index 737b44660fd..429155ea9bf 100644
--- a/src/plugins/texteditor/basehoverhandler.h
+++ b/src/plugins/texteditor/basehoverhandler.h
@@ -31,12 +31,10 @@
 #define BASEHOVERHANDLER_H
 
 #include "texteditor_global.h"
-
-#include <utils/htmldocextractor.h>
+#include "helpitem.h"
 
 #include <QtCore/QObject>
 #include <QtCore/QString>
-#include <QtCore/QList>
 
 QT_BEGIN_NAMESPACE
 class QPoint;
@@ -57,30 +55,6 @@ class TEXTEDITOR_EXPORT BaseHoverHandler : public QObject
 public:
     BaseHoverHandler(QObject *parent = 0);
 
-    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;
-    };
-
 private slots:
     void editorOpened(Core::IEditor *editor);
 
@@ -90,42 +64,28 @@ public slots:
 
 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;
-    const HelpCandidate &helpCandidate(int index) const;
-
-    void setMatchingHelpCandidate(int index);
-    int matchingHelpCandidate() const;
+    const QString &toolTip() const;
 
-    bool helpIdExists(const QString &helpId) const;
+    void addF1ToToolTip();
 
-    QString getDocContents(const bool extended);
-    QString getDocContents(const HelpCandidate &help, const bool extended);
+    void setLastHelpItemIdentified(const HelpItem &help);
+    const HelpItem &lastHelpItemIdentified() const;
 
     static BaseTextEditor *baseTextEditor(ITextEditor *editor);
     static bool extendToolTips(ITextEditor *editor);
 
 private:
-    void reset();
+    void clear();
     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;
+    HelpItem m_lastHelpItemIdentified;
 };
 
 } // namespace TextEditor
diff --git a/src/plugins/texteditor/helpitem.cpp b/src/plugins/texteditor/helpitem.cpp
new file mode 100644
index 00000000000..b4b766e52fc
--- /dev/null
+++ b/src/plugins/texteditor/helpitem.cpp
@@ -0,0 +1,123 @@
+/**************************************************************************
+**
+** 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 "helpitem.h"
+
+#include <coreplugin/helpmanager.h>
+#include <utils/htmldocextractor.h>
+
+#include <QtCore/QUrl>
+#include <QtCore/QByteArray>
+#include <QtCore/QMap>
+
+using namespace TextEditor;
+
+HelpItem::HelpItem()
+{}
+
+HelpItem::HelpItem(const QString &helpId, Category category) :
+    m_helpId(helpId), m_docMark(helpId), m_category(category)
+{}
+
+HelpItem::HelpItem(const QString &helpId, const QString &docMark, Category category) :
+    m_helpId(helpId), m_docMark(docMark), m_category(category)
+{}
+
+HelpItem::~HelpItem()
+{}
+
+void HelpItem::setHelpId(const QString &id)
+{ m_helpId = id; }
+
+const QString &HelpItem::helpId() const
+{ return m_helpId; }
+
+void HelpItem::setDocMark(const QString &mark)
+{ m_docMark = mark; }
+
+const QString &HelpItem::docMark() const
+{ return m_docMark; }
+
+void HelpItem::setCategory(Category cat)
+{ m_category = cat; }
+
+HelpItem::Category HelpItem::category() const
+{ return m_category; }
+
+bool HelpItem::isValid() const
+{
+    if (!Core::HelpManager::instance()->linksForIdentifier(m_helpId).isEmpty())
+        return true;
+    return false;
+}
+
+QString HelpItem::extractContent(bool extended) const
+{
+    Utils::HtmlDocExtractor htmlExtractor;
+    if (extended)
+        htmlExtractor.extractExtendedContents(1500, true);
+    else
+        htmlExtractor.extractFirstParagraphOnly();
+
+    QString contents;
+    QMap<QString, QUrl> helpLinks = Core::HelpManager::instance()->linksForIdentifier(m_helpId);
+    foreach (const QUrl &url, helpLinks) {
+        const QByteArray &html = Core::HelpManager::instance()->fileData(url);
+        switch (m_category) {
+        case Brief:
+            contents = htmlExtractor.getClassOrNamespaceBrief(html, m_docMark);
+            break;
+        case ClassOrNamespace:
+            contents = htmlExtractor.getClassOrNamespaceDescription(html, m_docMark);
+            break;
+        case Function:
+            contents = htmlExtractor.getFunctionDescription(html, m_docMark);
+            break;
+        case Enum:
+            contents = htmlExtractor.getEnumDescription(html, m_docMark);
+            break;
+        case Typedef:
+            contents = htmlExtractor.getTypedefDescription(html, m_docMark);
+            break;
+        case Macro:
+            contents = htmlExtractor.getMacroDescription(html, m_docMark);
+            break;
+        case QML:
+            contents = htmlExtractor.getQMLItemDescription(html, m_docMark);
+            break;
+
+        default:
+            break;
+        }
+
+        if (!contents.isEmpty())
+            break;
+    }
+    return contents;
+}
diff --git a/src/plugins/texteditor/helpitem.h b/src/plugins/texteditor/helpitem.h
new file mode 100644
index 00000000000..89f8aa7be37
--- /dev/null
+++ b/src/plugins/texteditor/helpitem.h
@@ -0,0 +1,79 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef TEXTEDITORHELPITEM_H
+#define TEXTEDITORHELPITEM_H
+
+#include "texteditor_global.h"
+
+#include <QtCore/QString>
+
+namespace TextEditor {
+
+class TEXTEDITOR_EXPORT HelpItem
+{
+public:
+    enum Category {
+        ClassOrNamespace,
+        Enum,
+        Typedef,
+        Macro,
+        Brief,
+        Function,
+        QML,
+        Unknown
+    };
+
+    HelpItem();
+    HelpItem(const QString &helpId, Category category);
+    HelpItem(const QString &helpId, const QString &docMark, Category category);
+    ~HelpItem();
+
+    void setHelpId(const QString &id);
+    const QString &helpId() const;
+
+    void setDocMark(const QString &mark);
+    const QString &docMark() const;
+
+    void setCategory(Category cat);
+    Category category() const;
+
+    bool isValid() const;
+
+    QString extractContent(bool extended) const;
+
+private:
+    QString m_helpId;
+    QString m_docMark;
+    Category m_category;
+};
+
+} // namespace TextEditor
+
+#endif // TEXTEDITORHELPITEM_H
diff --git a/src/plugins/texteditor/texteditor.pro b/src/plugins/texteditor/texteditor.pro
index e9e1ba4c946..b513c7de8c2 100644
--- a/src/plugins/texteditor/texteditor.pro
+++ b/src/plugins/texteditor/texteditor.pro
@@ -68,7 +68,8 @@ SOURCES += texteditorplugin.cpp \
     tooltip/tips.cpp \
     tooltip/tipcontents.cpp \
     basehoverhandler.cpp \
-    tooltip/tipfactory.cpp
+    tooltip/tipfactory.cpp \
+    helpitem.cpp
 
 HEADERS += texteditorplugin.h \
     textfilewizard.h \
@@ -139,7 +140,8 @@ HEADERS += texteditorplugin.h \
     tooltip/tipcontents.h \
     basehoverhandler.h \
     tooltip/effects.h \
-    tooltip/tipfactory.h
+    tooltip/tipfactory.h \
+    helpitem.h
 
 FORMS += behaviorsettingspage.ui \
     displaysettingspage.ui \
-- 
GitLab