From 6ed775f56a17a6fc3bb48323bd43373d8589b7b0 Mon Sep 17 00:00:00 2001
From: Eike Ziller <eike.ziller@theqtcompany.com>
Date: Fri, 7 Aug 2015 17:21:38 +0200
Subject: [PATCH] Fix wrong context help if tool tip was not shown for focus
 widget

The tool tip never has focus, so it cannot become the IContext that is
checked for context help. So, integrate the help id into Utils::ToolTip
and check the tool tip first when checking for context help.
As a side effect the [F1] button and help id for the tool tip is now also
available for use outside of the text editors.

Task-number: QTCREATORBUG-5345
Change-Id: Id975703caf161d1183c247e8ad8bb693b90fd306
Reviewed-by: Nikolai Kosjar <nikolai.kosjar@theqtcompany.com>
Reviewed-by: David Schulz <david.schulz@theqtcompany.com>
---
 .../utils/tooltip}/images/f1.png              | Bin
 .../utils/tooltip}/images/f1.svg              |   0
 src/libs/utils/tooltip/tips.cpp               |  31 +++++--
 src/libs/utils/tooltip/tips.h                 |  13 ++-
 src/libs/utils/tooltip/tooltip.cpp            |  34 +++++---
 src/libs/utils/tooltip/tooltip.h              |  25 ++++--
 src/libs/utils/utils.qrc                      |   1 +
 src/plugins/coreplugin/icore.cpp              |  11 +--
 src/plugins/coreplugin/icore.h                |  11 ++-
 src/plugins/coreplugin/mainwindow.cpp         |  24 +++---
 src/plugins/coreplugin/mainwindow.h           |   6 +-
 src/plugins/cppeditor/cpphoverhandler.cpp     |   1 -
 src/plugins/help/helpplugin.cpp               |  77 ++++++++++--------
 src/plugins/texteditor/basehoverhandler.cpp   |  12 +--
 src/plugins/texteditor/basehoverhandler.h     |   2 -
 src/plugins/texteditor/texteditor.cpp         |   2 +-
 src/plugins/texteditor/texteditor.qrc         |   1 -
 17 files changed, 157 insertions(+), 94 deletions(-)
 rename src/{plugins/texteditor => libs/utils/tooltip}/images/f1.png (100%)
 rename src/{plugins/texteditor => libs/utils/tooltip}/images/f1.svg (100%)

diff --git a/src/plugins/texteditor/images/f1.png b/src/libs/utils/tooltip/images/f1.png
similarity index 100%
rename from src/plugins/texteditor/images/f1.png
rename to src/libs/utils/tooltip/images/f1.png
diff --git a/src/plugins/texteditor/images/f1.svg b/src/libs/utils/tooltip/images/f1.svg
similarity index 100%
rename from src/plugins/texteditor/images/f1.svg
rename to src/libs/utils/tooltip/images/f1.svg
diff --git a/src/libs/utils/tooltip/tips.cpp b/src/libs/utils/tooltip/tips.cpp
index 9fd0121a682..89000a30dae 100644
--- a/src/libs/utils/tooltip/tips.cpp
+++ b/src/libs/utils/tooltip/tips.cpp
@@ -55,6 +55,17 @@ QTipLabel::QTipLabel(QWidget *parent) :
     QLabel(parent, Qt::ToolTip | Qt::BypassGraphicsProxyWidget)
 {}
 
+void QTipLabel::setHelpId(const QString &id)
+{
+    m_helpId = id;
+    update();
+}
+
+QString QTipLabel::helpId() const
+{
+    return m_helpId;
+}
+
 
 ColorTip::ColorTip(QWidget *parent)
     : QTipLabel(parent)
@@ -88,9 +99,9 @@ bool ColorTip::canHandleContentReplacement(int typeId) const
     return typeId == ToolTip::ColorContent;
 }
 
-bool ColorTip::equals(int typeId, const QVariant &other) const
+bool ColorTip::equals(int typeId, const QVariant &other, const QString &otherHelpId) const
 {
-    return typeId == ToolTip::ColorContent && other == m_color;
+    return typeId == ToolTip::ColorContent && otherHelpId == helpId() && other == m_color;
 }
 
 void ColorTip::paintEvent(QPaintEvent *event)
@@ -131,7 +142,12 @@ void TextTip::setContent(const QVariant &content)
 
 void TextTip::configure(const QPoint &pos, QWidget *w)
 {
-    setText(m_text);
+    if (helpId().isEmpty())
+        setText(m_text);
+    else
+        setText(QString::fromLatin1("<table><tr><td valign=middle>%1</td><td>&nbsp;&nbsp;"
+                                    "<img src=\":/utils/tooltip/images/f1.png\"></td>"
+                                    "</tr></table>").arg(m_text));
 
     // Make it look good with the default ToolTip font on Mac, which has a small descent.
     QFontMetrics fm(font());
@@ -166,9 +182,9 @@ int TextTip::showTime() const
     return 10000 + 40 * qMax(0, m_text.size() - 100);
 }
 
-bool TextTip::equals(int typeId, const QVariant &other) const
+bool TextTip::equals(int typeId, const QVariant &other, const QString &otherHelpId) const
 {
-    return typeId == ToolTip::TextContent && other.toString() == m_text;
+    return typeId == ToolTip::TextContent && otherHelpId == helpId() && other.toString() == m_text;
 }
 
 void TextTip::paintEvent(QPaintEvent *event)
@@ -245,9 +261,10 @@ bool WidgetTip::canHandleContentReplacement(int typeId) const
     return false;
 }
 
-bool WidgetTip::equals(int typeId, const QVariant &other) const
+bool WidgetTip::equals(int typeId, const QVariant &other, const QString &otherHelpId) const
 {
-    return typeId == ToolTip::WidgetContent && other.value<QWidget *>() == m_widget;
+    return typeId == ToolTip::WidgetContent && otherHelpId == helpId()
+            && other.value<QWidget *>() == m_widget;
 }
 
 // need to include it here to force it to be inside the namespaces
diff --git a/src/libs/utils/tooltip/tips.h b/src/libs/utils/tooltip/tips.h
index 86a9633e5da..748de44e2bc 100644
--- a/src/libs/utils/tooltip/tips.h
+++ b/src/libs/utils/tooltip/tips.h
@@ -56,7 +56,12 @@ public:
     virtual int showTime() const = 0;
     virtual void configure(const QPoint &pos, QWidget *w) = 0;
     virtual bool canHandleContentReplacement(int typeId) const = 0;
-    virtual bool equals(int typeId, const QVariant &other) const = 0;
+    virtual bool equals(int typeId, const QVariant &other, const QString &helpId) const = 0;
+    virtual void setHelpId(const QString &id);
+    virtual QString helpId() const;
+
+private:
+    QString m_helpId;
 };
 
 class TextTip : public QTipLabel
@@ -68,7 +73,7 @@ public:
     virtual void configure(const QPoint &pos, QWidget *w);
     virtual bool canHandleContentReplacement(int typeId) const;
     virtual int showTime() const;
-    virtual bool equals(int typeId, const QVariant &other) const;
+    virtual bool equals(int typeId, const QVariant &other, const QString &otherHelpId) const;
     virtual void paintEvent(QPaintEvent *event);
     virtual void resizeEvent(QResizeEvent *event);
 
@@ -85,7 +90,7 @@ public:
     virtual void configure(const QPoint &pos, QWidget *w);
     virtual bool canHandleContentReplacement(int typeId) const;
     virtual int showTime() const { return 4000; }
-    virtual bool equals(int typeId, const QVariant &other) const;
+    virtual bool equals(int typeId, const QVariant &other, const QString &otherHelpId) const;
     virtual void paintEvent(QPaintEvent *event);
 
 private:
@@ -105,7 +110,7 @@ public:
     virtual void configure(const QPoint &pos, QWidget *w);
     virtual bool canHandleContentReplacement(int typeId) const;
     virtual int showTime() const { return 30000; }
-    virtual bool equals(int typeId, const QVariant &other) const;
+    virtual bool equals(int typeId, const QVariant &other, const QString &otherHelpId) const;
     virtual bool isInteractive() const { return true; }
 
 private:
diff --git a/src/libs/utils/tooltip/tooltip.cpp b/src/libs/utils/tooltip/tooltip.cpp
index b15ba4c5191..38b280c5619 100644
--- a/src/libs/utils/tooltip/tooltip.cpp
+++ b/src/libs/utils/tooltip/tooltip.cpp
@@ -66,28 +66,28 @@ ToolTip *ToolTip::instance()
     return &tooltip;
 }
 
-void ToolTip::show(const QPoint &pos, const QString &content, QWidget *w, const QRect &rect)
+void ToolTip::show(const QPoint &pos, const QString &content, QWidget *w, const QString &helpId, const QRect &rect)
 {
     if (content.isEmpty())
         instance()->hideTipWithDelay();
     else
-        instance()->showInternal(pos, QVariant(content), TextContent, w, rect);
+        instance()->showInternal(pos, QVariant(content), TextContent, w, helpId, rect);
 }
 
-void ToolTip::show(const QPoint &pos, const QColor &color, QWidget *w, const QRect &rect)
+void ToolTip::show(const QPoint &pos, const QColor &color, QWidget *w, const QString &helpId, const QRect &rect)
 {
     if (!color.isValid())
         instance()->hideTipWithDelay();
     else
-        instance()->showInternal(pos, QVariant(color), ColorContent, w, rect);
+        instance()->showInternal(pos, QVariant(color), ColorContent, w, helpId, rect);
 }
 
-void ToolTip::show(const QPoint &pos, QWidget *content, QWidget *w, const QRect &rect)
+void ToolTip::show(const QPoint &pos, QWidget *content, QWidget *w, const QString &helpId, const QRect &rect)
 {
     if (!content)
         instance()->hideTipWithDelay();
     else
-        instance()->showInternal(pos, QVariant::fromValue(content), WidgetContent, w, rect);
+        instance()->showInternal(pos, QVariant::fromValue(content), WidgetContent, w, helpId, rect);
 }
 
 void ToolTip::move(const QPoint &pos, QWidget *w)
@@ -111,10 +111,15 @@ bool ToolTip::pinToolTip(QWidget *w, QWidget *parent)
     return false;
 }
 
+QString ToolTip::contextHelpId()
+{
+    return instance()->m_tip ? instance()->m_tip->helpId() : QString();
+}
+
 bool ToolTip::acceptShow(const QVariant &content,
                          int typeId,
                          const QPoint &pos,
-                         QWidget *w,
+                         QWidget *w, const QString &helpId,
                          const QRect &rect)
 {
     if (isVisible()) {
@@ -123,8 +128,9 @@ bool ToolTip::acceptShow(const QVariant &content,
             QPoint localPos = pos;
             if (w)
                 localPos = w->mapFromGlobal(pos);
-            if (tipChanged(localPos, content, typeId, w)) {
+            if (tipChanged(localPos, content, typeId, w, helpId)) {
                 m_tip->setContent(content);
+                m_tip->setHelpId(helpId);
                 setUp(pos, w, rect);
             }
             return false;
@@ -155,9 +161,10 @@ void ToolTip::setUp(const QPoint &pos, QWidget *w, const QRect &rect)
     m_showTimer.start(m_tip->showTime());
 }
 
-bool ToolTip::tipChanged(const QPoint &pos, const QVariant &content, int typeId, QWidget *w) const
+bool ToolTip::tipChanged(const QPoint &pos, const QVariant &content, int typeId, QWidget *w,
+                         const QString &helpId) const
 {
-    if (!m_tip->equals(typeId, content) || m_widget != w)
+    if (!m_tip->equals(typeId, content, helpId) || m_widget != w)
         return true;
     if (!m_rect.isNull())
         return !m_rect.contains(pos);
@@ -220,12 +227,13 @@ void ToolTip::hideTipImmediately()
     m_showTimer.stop();
     m_hideDelayTimer.stop();
     qApp->removeEventFilter(this);
+    emit hidden();
 }
 
 void ToolTip::showInternal(const QPoint &pos, const QVariant &content,
-                           int typeId, QWidget *w, const QRect &rect)
+                           int typeId, QWidget *w, const QString &helpId, const QRect &rect)
 {
-    if (acceptShow(content, typeId, pos, w, rect)) {
+    if (acceptShow(content, typeId, pos, w, helpId, rect)) {
         QWidget *target = 0;
         if (HostOsInfo::isWindowsHost())
             target = QApplication::desktop()->screen(Internal::screenNumber(pos, w));
@@ -244,10 +252,12 @@ void ToolTip::showInternal(const QPoint &pos, const QVariant &content,
                 break;
         }
         m_tip->setContent(content);
+        m_tip->setHelpId(helpId);
         setUp(pos, w, rect);
         qApp->installEventFilter(this);
         showTip();
     }
+    emit shown();
 }
 
 void ToolTip::placeTip(const QPoint &pos, QWidget *w)
diff --git a/src/libs/utils/tooltip/tooltip.h b/src/libs/utils/tooltip/tooltip.h
index f7c4be31dd5..7356d3b2071 100644
--- a/src/libs/utils/tooltip/tooltip.h
+++ b/src/libs/utils/tooltip/tooltip.h
@@ -75,9 +75,12 @@ public:
 
     static ToolTip *instance();
 
-    static void show(const QPoint &pos, const QString &content, QWidget *w = 0, const QRect &rect = QRect());
-    static void show(const QPoint &pos, const QColor &color, QWidget *w = 0, const QRect &rect = QRect());
-    static void show(const QPoint &pos, QWidget *content, QWidget *w = 0, const QRect &rect = QRect());
+    static void show(const QPoint &pos, const QString &content, QWidget *w = 0,
+                     const QString &helpId = QString(), const QRect &rect = QRect());
+    static void show(const QPoint &pos, const QColor &color, QWidget *w = 0,
+                     const QString &helpId = QString(), const QRect &rect = QRect());
+    static void show(const QPoint &pos, QWidget *content, QWidget *w = 0,
+                     const QString &helpId = QString(), const QRect &rect = QRect());
     static void move(const QPoint &pos, QWidget *w);
     static void hide();
     static bool isVisible();
@@ -88,12 +91,21 @@ public:
     // using WidgetContent
     static bool pinToolTip(QWidget *w, QWidget *parent);
 
+    static QString contextHelpId();
+
+signals:
+    void shown();
+    void hidden();
+
 private:
-    void showInternal(const QPoint &pos, const QVariant &content, int typeId, QWidget *w, const QRect &rect);
+    void showInternal(const QPoint &pos, const QVariant &content, int typeId, QWidget *w,
+                      const QString &helpId, const QRect &rect);
     void hideTipImmediately();
-    bool acceptShow(const QVariant &content, int typeId, const QPoint &pos, QWidget *w, const QRect &rect);
+    bool acceptShow(const QVariant &content, int typeId, const QPoint &pos, QWidget *w,
+                    const QString &helpId, const QRect &rect);
     void setUp(const QPoint &pos, QWidget *w, const QRect &rect);
-    bool tipChanged(const QPoint &pos, const QVariant &content, int typeId, QWidget *w) const;
+    bool tipChanged(const QPoint &pos, const QVariant &content, int typeId, QWidget *w,
+                    const QString &helpId) const;
     void setTipRect(QWidget *w, const QRect &rect);
     void placeTip(const QPoint &pos, QWidget *w);
     void showTip();
@@ -104,6 +116,7 @@ private:
     QRect m_rect;
     QTimer m_showTimer;
     QTimer m_hideDelayTimer;
+    QString m_helpId;
 };
 
 } // namespace Utils
diff --git a/src/libs/utils/utils.qrc b/src/libs/utils/utils.qrc
index c7be7e8de8e..4bbc0be8b3a 100644
--- a/src/libs/utils/utils.qrc
+++ b/src/libs/utils/utils.qrc
@@ -14,5 +14,6 @@
         <file>images/progressindicator_small.png</file>
         <file>images/progressindicator_small@2x.png</file>
         <file>images/triangle_vert.png</file>
+        <file>tooltip/images/f1.png</file>
     </qresource>
 </RCC>
diff --git a/src/plugins/coreplugin/icore.cpp b/src/plugins/coreplugin/icore.cpp
index 6bb5ca9190e..1efea803ecd 100644
--- a/src/plugins/coreplugin/icore.cpp
+++ b/src/plugins/coreplugin/icore.cpp
@@ -528,19 +528,20 @@ void ICore::raiseWindow(QWidget *widget)
     }
 }
 
-void ICore::updateAdditionalContexts(const Context &remove, const Context &add)
+void ICore::updateAdditionalContexts(const Context &remove, const Context &add,
+                                     ContextPriority priority)
 {
-    m_mainwindow->updateAdditionalContexts(remove, add);
+    m_mainwindow->updateAdditionalContexts(remove, add, priority);
 }
 
-void ICore::addAdditionalContext(const Context &context)
+void ICore::addAdditionalContext(const Context &context, ContextPriority priority)
 {
-    m_mainwindow->updateAdditionalContexts(Context(), context);
+    m_mainwindow->updateAdditionalContexts(Context(), context, priority);
 }
 
 void ICore::removeAdditionalContext(const Context &context)
 {
-    m_mainwindow->updateAdditionalContexts(context, Context());
+    m_mainwindow->updateAdditionalContexts(context, Context(), ContextPriority::Low);
 }
 
 void ICore::addContextObject(IContext *context)
diff --git a/src/plugins/coreplugin/icore.h b/src/plugins/coreplugin/icore.h
index 783753ebb78..6f5e98ddd8a 100644
--- a/src/plugins/coreplugin/icore.h
+++ b/src/plugins/coreplugin/icore.h
@@ -65,6 +65,11 @@ class CORE_EXPORT ICore : public QObject
     ~ICore();
 
 public:
+    enum class ContextPriority {
+        High,
+        Low
+    };
+
     // This should only be used to acccess the signals, so it could
     // theoretically return an QObject *. For source compatibility
     // it returns a ICore.
@@ -107,8 +112,10 @@ public:
     static IContext *currentContextObject();
     // Adds and removes additional active contexts, these contexts are appended
     // to the currently active contexts.
-    static void updateAdditionalContexts(const Context &remove, const Context &add);
-    static void addAdditionalContext(const Context &context);
+    static void updateAdditionalContexts(const Context &remove, const Context &add,
+                                         ContextPriority priority = ContextPriority::Low);
+    static void addAdditionalContext(const Context &context,
+                                     ContextPriority priority = ContextPriority::Low);
     static void removeAdditionalContext(const Context &context);
     static void addContextObject(IContext *context);
     static void removeContextObject(IContext *context);
diff --git a/src/plugins/coreplugin/mainwindow.cpp b/src/plugins/coreplugin/mainwindow.cpp
index ddb32436e3b..1c6ab395487 100644
--- a/src/plugins/coreplugin/mainwindow.cpp
+++ b/src/plugins/coreplugin/mainwindow.cpp
@@ -112,7 +112,7 @@ enum { debugMainWindow = 0 };
 MainWindow::MainWindow() :
     AppMainWindow(),
     m_coreImpl(new ICore(this)),
-    m_additionalContexts(Constants::C_GLOBAL),
+    m_lowPrioAdditionalContexts(Constants::C_GLOBAL),
     m_settingsDatabase(new SettingsDatabase(QFileInfo(PluginManager::settings()->fileName()).path(),
                                             QLatin1String("QtCreator"),
                                             this)),
@@ -985,23 +985,27 @@ void MainWindow::writeSettings()
     m_navigationWidget->saveSettings(settings);
 }
 
-void MainWindow::updateAdditionalContexts(const Context &remove, const Context &add)
+void MainWindow::updateAdditionalContexts(const Context &remove, const Context &add,
+                                          ICore::ContextPriority priority)
 {
     foreach (const Id id, remove) {
         if (!id.isValid())
             continue;
-
-        int index = m_additionalContexts.indexOf(id);
+        int index = m_lowPrioAdditionalContexts.indexOf(id);
+        if (index != -1)
+            m_lowPrioAdditionalContexts.removeAt(index);
+        index = m_highPrioAdditionalContexts.indexOf(id);
         if (index != -1)
-            m_additionalContexts.removeAt(index);
+            m_highPrioAdditionalContexts.removeAt(index);
     }
 
     foreach (const Id id, add) {
         if (!id.isValid())
             continue;
-
-        if (!m_additionalContexts.contains(id))
-            m_additionalContexts.prepend(id);
+        Context &cref = (priority == ICore::ContextPriority::High ? m_highPrioAdditionalContexts
+                                                                  : m_lowPrioAdditionalContexts);
+        if (!cref.contains(id))
+            cref.prepend(id);
     }
 
     updateContext();
@@ -1009,12 +1013,12 @@ void MainWindow::updateAdditionalContexts(const Context &remove, const Context &
 
 void MainWindow::updateContext()
 {
-    Context contexts;
+    Context contexts = m_highPrioAdditionalContexts;
 
     foreach (IContext *context, m_activeContext)
         contexts.add(context->context());
 
-    contexts.add(m_additionalContexts);
+    contexts.add(m_lowPrioAdditionalContexts);
 
     Context uniquecontexts;
     for (int i = 0; i < contexts.size(); ++i) {
diff --git a/src/plugins/coreplugin/mainwindow.h b/src/plugins/coreplugin/mainwindow.h
index b931f2652c1..dff6096f814 100644
--- a/src/plugins/coreplugin/mainwindow.h
+++ b/src/plugins/coreplugin/mainwindow.h
@@ -103,7 +103,8 @@ public:
     IContext * currentContextObject() const;
     QStatusBar *statusBar() const;
 
-    void updateAdditionalContexts(const Context &remove, const Context &add);
+    void updateAdditionalContexts(const Context &remove, const Context &add,
+                                  ICore::ContextPriority priority);
 
     void setSuppressNavigationWidget(bool suppress);
 
@@ -151,7 +152,8 @@ private:
     void writeSettings();
 
     ICore *m_coreImpl;
-    Context m_additionalContexts;
+    Context m_highPrioAdditionalContexts;
+    Context m_lowPrioAdditionalContexts;
     SettingsDatabase *m_settingsDatabase;
     mutable QPrinter *m_printer;
     WindowSupport *m_windowSupport;
diff --git a/src/plugins/cppeditor/cpphoverhandler.cpp b/src/plugins/cppeditor/cpphoverhandler.cpp
index f5e5e5214de..94ed9efa9c6 100644
--- a/src/plugins/cppeditor/cpphoverhandler.cpp
+++ b/src/plugins/cppeditor/cpphoverhandler.cpp
@@ -119,7 +119,6 @@ void CppHoverHandler::decorateToolTip()
                 prefix = QLatin1String("enum ");
             setToolTip(prefix + help.helpId());
         }
-        addF1ToToolTip();
     }
 }
 
diff --git a/src/plugins/help/helpplugin.cpp b/src/plugins/help/helpplugin.cpp
index b8a83150c26..c51d5aa7216 100644
--- a/src/plugins/help/helpplugin.cpp
+++ b/src/plugins/help/helpplugin.cpp
@@ -78,6 +78,7 @@
 #include <utils/qtcassert.h>
 #include <utils/styledbar.h>
 #include <utils/theme/theme.h>
+#include <utils/tooltip/tooltip.h>
 
 #include <QDir>
 #include <QFileInfo>
@@ -101,6 +102,7 @@
 using namespace Help::Internal;
 
 static const char kExternalWindowStateKey[] = "Help/ExternalWindowState";
+static const char kToolTipHelpContext[] = "Help.ToolTip";
 
 using namespace Core;
 using namespace Utils;
@@ -169,6 +171,13 @@ bool HelpPlugin::initialize(const QStringList &arguments, QString *error)
     connect(HelpManager::instance(), SIGNAL(collectionFileChanged()), this,
         SLOT(setupHelpEngineIfNeeded()));
 
+    connect(ToolTip::instance(), &ToolTip::shown, ICore::instance(), []() {
+        ICore::addAdditionalContext(Context(kToolTipHelpContext), ICore::ContextPriority::High);
+    });
+    connect(ToolTip::instance(), &ToolTip::hidden,ICore::instance(), []() {
+        ICore::removeAdditionalContext(Context(kToolTipHelpContext));
+    });
+
     Command *cmd;
     QAction *action;
 
@@ -185,7 +194,8 @@ bool HelpPlugin::initialize(const QStringList &arguments, QString *error)
     connect(action, SIGNAL(triggered()), this, SLOT(activateIndex()));
 
     action = new QAction(tr("Context Help"), this);
-    cmd = ActionManager::registerAction(action, Help::Constants::CONTEXT_HELP);
+    cmd = ActionManager::registerAction(action, Help::Constants::CONTEXT_HELP,
+                                        Context(kToolTipHelpContext, Core::Constants::C_GLOBAL));
     ActionManager::actionContainer(Core::Constants::M_HELP)->addAction(cmd, Core::Constants::G_HELP_HELP);
     cmd->setDefaultKeySequence(QKeySequence(Qt::Key_F1));
     connect(action, SIGNAL(triggered()), this, SLOT(showContextHelp()));
@@ -560,40 +570,43 @@ static QUrl findBestLink(const QMap<QString, QUrl> &links, QString *highlightId)
 void HelpPlugin::showContextHelp()
 {
     // Find out what to show
-    QMap<QString, QUrl> links;
-    QString idFromContext;
-    if (IContext *context = ICore::currentContextObject()) {
-        idFromContext = context->contextHelpId();
-        links = HelpManager::linksForIdentifier(idFromContext);
-        // Maybe the id is already an URL
-        if (links.isEmpty() && LocalHelpManager::isValidUrl(idFromContext))
-            links.insert(idFromContext, idFromContext);
-    }
+    QString contextHelpId = Utils::ToolTip::contextHelpId();
+    IContext *context = ICore::currentContextObject();
+    if (contextHelpId.isEmpty() && context)
+        contextHelpId = context->contextHelpId();
+
+    // get the viewer after getting the help id,
+    // because a new window might be opened and therefore focus be moved
+    HelpViewer *viewer = viewerForContextHelp();
+    QTC_ASSERT(viewer, return);
 
-    if (HelpViewer *viewer = viewerForContextHelp()) {
-        QUrl source = findBestLink(links, &m_contextHelpHighlightId);
-        if (!source.isValid()) {
-            // No link found or no context object
-            viewer->setSource(QUrl(Help::Constants::AboutBlank));
-            viewer->setHtml(tr("<html><head><title>No Documentation</title>"
-                "</head><body><br/><center>"
-                "<font color=\"%1\"><b>%2</b></font><br/>"
-                "<font color=\"%3\">No documentation available.</font>"
-                "</center></body></html>")
-                .arg(creatorTheme()->color(Theme::TextColorNormal).name())
-                .arg(idFromContext)
-                .arg(creatorTheme()->color(Theme::TextColorNormal).name()));
+    QMap<QString, QUrl> links = HelpManager::linksForIdentifier(contextHelpId);
+    // Maybe the id is already an URL
+    if (links.isEmpty() && LocalHelpManager::isValidUrl(contextHelpId))
+        links.insert(contextHelpId, contextHelpId);
+
+    QUrl source = findBestLink(links, &m_contextHelpHighlightId);
+    if (!source.isValid()) {
+        // No link found or no context object
+        viewer->setSource(QUrl(Help::Constants::AboutBlank));
+        viewer->setHtml(tr("<html><head><title>No Documentation</title>"
+            "</head><body><br/><center>"
+            "<font color=\"%1\"><b>%2</b></font><br/>"
+            "<font color=\"%3\">No documentation available.</font>"
+            "</center></body></html>")
+            .arg(creatorTheme()->color(Theme::TextColorNormal).name())
+            .arg(contextHelpId)
+            .arg(creatorTheme()->color(Theme::TextColorNormal).name()));
+    } else {
+        const QUrl &oldSource = viewer->source();
+        if (source != oldSource) {
+            viewer->stop();
+            viewer->setSource(source); // triggers loadFinished which triggers id highlighting
         } else {
-            const QUrl &oldSource = viewer->source();
-            if (source != oldSource) {
-                viewer->stop();
-                viewer->setSource(source); // triggers loadFinished which triggers id highlighting
-            } else {
-                viewer->scrollToAnchor(source.fragment());
-            }
-            viewer->setFocus();
-            ICore::raiseWindow(viewer);
+            viewer->scrollToAnchor(source.fragment());
         }
+        viewer->setFocus();
+        ICore::raiseWindow(viewer);
     }
 }
 
diff --git a/src/plugins/texteditor/basehoverhandler.cpp b/src/plugins/texteditor/basehoverhandler.cpp
index 08e1bbcdb31..b76250a4223 100644
--- a/src/plugins/texteditor/basehoverhandler.cpp
+++ b/src/plugins/texteditor/basehoverhandler.cpp
@@ -82,13 +82,6 @@ void BaseHoverHandler::appendToolTip(const QString &extension)
     m_toolTip.append(extension);
 }
 
-void BaseHoverHandler::addF1ToToolTip()
-{
-    m_toolTip = QString::fromLatin1("<table><tr><td valign=middle>%1</td><td>&nbsp;&nbsp;"
-                                    "<img src=\":/texteditor/images/f1.png\"></td>"
-                                    "</tr></table>").arg(m_toolTip);
-}
-
 void BaseHoverHandler::setIsDiagnosticTooltip(bool isDiagnosticTooltip)
 {
     m_diagnosticTooltip = isDiagnosticTooltip;
@@ -133,7 +126,6 @@ void BaseHoverHandler::decorateToolTip()
         if (!contents.isEmpty()) {
             setToolTip(toolTip().toHtmlEscaped());
             appendToolTip(contents);
-            addF1ToToolTip();
         }
     }
 }
@@ -143,7 +135,9 @@ void BaseHoverHandler::operateTooltip(TextEditorWidget *editorWidget, const QPoi
     if (m_toolTip.isEmpty())
         Utils::ToolTip::hide();
     else
-        Utils::ToolTip::show(point, m_toolTip, editorWidget);
+        Utils::ToolTip::show(point, m_toolTip, editorWidget, m_lastHelpItemIdentified.isValid()
+                             ? m_lastHelpItemIdentified.helpId()
+                             : QString());
 }
 
 } // namespace TextEditor
diff --git a/src/plugins/texteditor/basehoverhandler.h b/src/plugins/texteditor/basehoverhandler.h
index 00accf05b7e..eff2b75a06f 100644
--- a/src/plugins/texteditor/basehoverhandler.h
+++ b/src/plugins/texteditor/basehoverhandler.h
@@ -59,8 +59,6 @@ protected:
     void appendToolTip(const QString &extension);
     const QString &toolTip() const;
 
-    void addF1ToToolTip();
-
     void setIsDiagnosticTooltip(bool isDiagnosticTooltip);
     bool isDiagnosticTooltip() const;
 
diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp
index 582b52fdcbc..ea968f8e6a6 100644
--- a/src/plugins/texteditor/texteditor.cpp
+++ b/src/plugins/texteditor/texteditor.cpp
@@ -3127,7 +3127,7 @@ bool TextEditorWidget::viewportEvent(QEvent *event)
         RefactorMarker refactorMarker = d->m_refactorOverlay->markerAt(pos);
         if (refactorMarker.isValid() && !refactorMarker.tooltip.isEmpty()) {
             ToolTip::show(he->globalPos(), refactorMarker.tooltip,
-                          viewport(), refactorMarker.rect);
+                          viewport(), QString(), refactorMarker.rect);
             return true;
         }
 
diff --git a/src/plugins/texteditor/texteditor.qrc b/src/plugins/texteditor/texteditor.qrc
index c58205cd2c1..7f829e91594 100644
--- a/src/plugins/texteditor/texteditor.qrc
+++ b/src/plugins/texteditor/texteditor.qrc
@@ -4,6 +4,5 @@
         <file>images/finddirectory.png</file>
         <file>images/refactormarker.png</file>
         <file>images/snippet.png</file>
-        <file>images/f1.png</file>
     </qresource>
 </RCC>
-- 
GitLab