changeset 2463:820481e9bdbd draft

Merge pull request #1090 from laanwj/2012_04_wraptooltips Allow Qt to wrap long tooltips (fixes #1063)
author Wladimir J. van der Laan <laanwj@gmail.com>
date Thu, 10 May 2012 23:54:53 -0700
parents 816464140ae4 (current diff) 360a7331f181 (diff)
children 619245c5666e
files src/qt/bitcoin.cpp src/qt/bitcoingui.cpp
diffstat 5 files changed, 57 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -6,6 +6,7 @@
 #include "walletmodel.h"
 #include "optionsmodel.h"
 #include "guiutil.h"
+#include "guiconstants.h"
 
 #include "init.h"
 #include "ui_interface.h"
@@ -164,6 +165,9 @@
     Q_INIT_RESOURCE(bitcoin);
     QApplication app(argc, argv);
 
+    // Install global event filter that makes sure that long tooltips can be word-wrapped
+    app.installEventFilter(new GUIUtil::ToolTipToRichTextFilter(TOOLTIP_WRAP_THRESHOLD, &app));
+
     // Command-line options take precedence:
     ParseParameters(argc, argv);
 
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -563,22 +563,25 @@
     // Set icon state: spinning if catching up, tick otherwise
     if(secs < 90*60 && count >= nTotalBlocks)
     {
-        tooltip = tr("Up to date") + QString(".\n") + tooltip;
+        tooltip = tr("Up to date") + QString(".<br>") + tooltip;
         labelBlocksIcon->setPixmap(QIcon(":/icons/synced").pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE));
     }
     else
     {
-        tooltip = tr("Catching up...") + QString("\n") + tooltip;
+        tooltip = tr("Catching up...") + QString("<br>") + tooltip;
         labelBlocksIcon->setMovie(syncIconMovie);
         syncIconMovie->start();
     }
 
     if(!text.isEmpty())
     {
-        tooltip += QString("\n");
+        tooltip += QString("<br>");
         tooltip += tr("Last received block was generated %1.").arg(text);
     }
 
+    // Don't word-wrap this (fixed-width) tooltip
+    tooltip = QString("<nobr>") + tooltip + QString("</nobr>");
+
     labelBlocksIcon->setToolTip(tooltip);
     progressBarLabel->setToolTip(tooltip);
     progressBar->setToolTip(tooltip);
--- a/src/qt/guiconstants.h
+++ b/src/qt/guiconstants.h
@@ -20,4 +20,9 @@
 /* Transaction list -- bare address (without label) */
 #define COLOR_BAREADDRESS QColor(140, 140, 140)
 
+/* Tooltips longer than this (in characters) are converted into rich text,
+   so that they can be word-wrapped.
+ */
+static const int TOOLTIP_WRAP_THRESHOLD = 80;
+
 #endif // GUICONSTANTS_H
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -214,5 +214,29 @@
            && checkPoint(QPoint(w->width()/2, w->height()/2), w));
 }
 
+ToolTipToRichTextFilter::ToolTipToRichTextFilter(int size_threshold, QObject *parent):
+    size_threshold(size_threshold), QObject(parent)
+{
+
+}
+
+bool ToolTipToRichTextFilter::eventFilter(QObject *obj, QEvent *evt)
+{
+    if(evt->type() == QEvent::ToolTipChange)
+    {
+        QWidget *widget = static_cast<QWidget*>(obj);
+        QString tooltip = widget->toolTip();
+        if(!Qt::mightBeRichText(tooltip) && tooltip.size() > size_threshold)
+        {
+            // Prefix <qt/> to make sure Qt detects this as rich text
+            // Escape the current message as HTML and replace \n by <br>
+            tooltip = "<qt/>" + HtmlEscape(tooltip, true);
+            widget->setToolTip(tooltip);
+            return true;
+        }
+    }
+    return QObject::eventFilter(obj, evt);
+}
+
 } // namespace GUIUtil
 
--- a/src/qt/guiutil.h
+++ b/src/qt/guiutil.h
@@ -2,6 +2,7 @@
 #define GUIUTIL_H
 
 #include <QString>
+#include <QObject>
 
 QT_BEGIN_NAMESPACE
 class QFont;
@@ -69,6 +70,23 @@
     // Determine whether a widget is hidden behind other windows
     bool isObscured(QWidget *w);
 
+    /** Qt event filter that intercepts ToolTipChange events, and replaces the tooltip with a rich text
+      representation if needed. This assures that Qt can word-wrap long tooltip messages.
+      Tooltips longer than the provided size threshold (in characters) are wrapped.
+     */
+    class ToolTipToRichTextFilter: public QObject
+    {
+        Q_OBJECT
+    public:
+        ToolTipToRichTextFilter(int size_threshold, QObject *parent);
+
+    protected:
+        bool eventFilter(QObject *obj, QEvent *evt);
+
+    private:
+        int size_threshold;
+    };
+
 } // namespace GUIUtil
 
 #endif // GUIUTIL_H