From 9da13ea53aec6d841ba7f416531d6c52d4368df4 Mon Sep 17 00:00:00 2001
From: Yoann Lopes <yoann.lopes@nokia.com>
Date: Thu, 15 Apr 2010 10:41:18 +0200
Subject: Fixes tooltips for QGraphicsProxyWidget.

Help event was not propagated to the widget. Also fixes tooltip value
propagation when setting it on the proxy or on the widget.
Autotest included.

Task-number: QTBUG-5349
Reviewed-by: bnilsen
---
 src/gui/graphicsview/qgraphicsproxywidget.cpp      | 31 +++++++
 src/gui/graphicsview/qgraphicsproxywidget_p.h      |  2 +
 src/gui/graphicsview/qgraphicsscene.cpp            |  6 ++
 src/gui/kernel/qtooltip.cpp                        |  4 +-
 .../tst_qgraphicsproxywidget.cpp                   | 99 +++++++++++++++++-----
 5 files changed, 118 insertions(+), 24 deletions(-)

diff --git a/src/gui/graphicsview/qgraphicsproxywidget.cpp b/src/gui/graphicsview/qgraphicsproxywidget.cpp
index 2132526..bdd41cd 100644
--- a/src/gui/graphicsview/qgraphicsproxywidget.cpp
+++ b/src/gui/graphicsview/qgraphicsproxywidget.cpp
@@ -897,6 +897,29 @@ bool QGraphicsProxyWidget::event(QEvent *event)
         }
         break;
     }
+#ifndef QT_NO_TOOLTIP
+    case QEvent::GraphicsSceneHelp: {
+        // Propagate the help event (for tooltip) to the widget under mouse
+        if (d->lastWidgetUnderMouse) {
+            QGraphicsSceneHelpEvent *he = static_cast<QGraphicsSceneHelpEvent *>(event);
+            QPoint pos = d->mapToReceiver(mapFromScene(he->scenePos()), d->lastWidgetUnderMouse).toPoint();
+            QHelpEvent e(QEvent::ToolTip, pos, he->screenPos());
+            QApplication::sendEvent(d->lastWidgetUnderMouse, &e);
+            event->setAccepted(e.isAccepted());
+            return e.isAccepted();
+        }
+        break;
+    }
+    case QEvent::ToolTipChange: {
+        // Propagate tooltip change to the widget
+        if (!d->tooltipChangeMode) {
+            d->tooltipChangeMode = QGraphicsProxyWidgetPrivate::ProxyToWidgetMode;
+            d->widget->setToolTip(toolTip());
+            d->tooltipChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
+        }
+        break;
+    }
+#endif
     default:
         break;
     }
@@ -952,6 +975,14 @@ bool QGraphicsProxyWidget::eventFilter(QObject *object, QEvent *event)
                 d->styleChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
             }
             break;
+        case QEvent::ToolTipChange:
+            // Propagate tooltip change to the proxy.
+            if (!d->tooltipChangeMode) {
+                d->tooltipChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode;
+                setToolTip(d->widget->toolTip());
+                d->tooltipChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
+            }
+            break;
         default:
             break;
         }
diff --git a/src/gui/graphicsview/qgraphicsproxywidget_p.h b/src/gui/graphicsview/qgraphicsproxywidget_p.h
index 8aed363..0e29a7e 100644
--- a/src/gui/graphicsview/qgraphicsproxywidget_p.h
+++ b/src/gui/graphicsview/qgraphicsproxywidget_p.h
@@ -72,6 +72,7 @@ public:
           enabledChangeMode(NoMode),
           styleChangeMode(NoMode),
           paletteChangeMode(NoMode),
+          tooltipChangeMode(NoMode),
           focusFromWidgetToProxy(0)
     { }
     void init();
@@ -117,6 +118,7 @@ public:
     quint32 enabledChangeMode : 2;
     quint32 styleChangeMode : 2;
     quint32 paletteChangeMode : 2;
+    quint32 tooltipChangeMode : 2;
     quint32 focusFromWidgetToProxy : 1;
     quint32 proxyIsGivingFocus : 1;
 };
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index 6581727..b368a82 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -3772,6 +3772,12 @@ void QGraphicsScene::helpEvent(QGraphicsSceneHelpEvent *helpEvent)
     QGraphicsItem *toolTipItem = 0;
     for (int i = 0; i < itemsAtPos.size(); ++i) {
         QGraphicsItem *tmp = itemsAtPos.at(i);
+        if (tmp->d_func()->isProxyWidget()) {
+            // if the item is a proxy widget, the event is forwarded to it
+            sendEvent(tmp, helpEvent);
+            if (helpEvent->isAccepted())
+                return;
+        }
         if (!tmp->toolTip().isEmpty()) {
             toolTipItem = tmp;
             break;
diff --git a/src/gui/kernel/qtooltip.cpp b/src/gui/kernel/qtooltip.cpp
index 1343959..c8fcf45 100644
--- a/src/gui/kernel/qtooltip.cpp
+++ b/src/gui/kernel/qtooltip.cpp
@@ -168,9 +168,9 @@ QTipLabel *QTipLabel::instance = 0;
 
 QTipLabel::QTipLabel(const QString &text, QWidget *w)
 #ifndef QT_NO_STYLE_STYLESHEET
-    : QLabel(w, Qt::ToolTip), styleSheetParent(0), widget(0)
+    : QLabel(w, Qt::ToolTip | Qt::BypassGraphicsProxyWidget), styleSheetParent(0), widget(0)
 #else
-    : QLabel(w, Qt::ToolTip), widget(0)
+    : QLabel(w, Qt::ToolTip | Qt::BypassGraphicsProxyWidget), widget(0)
 #endif
 {
     delete instance;
diff --git a/tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp b/tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp
index e46709b..a5a039a 100644
--- a/tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp
+++ b/tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp
@@ -43,6 +43,7 @@
 #include <QtTest/QtTest>
 #include <QtGui>
 #include "../../shared/util.h"
+#include <private/qgraphicsproxywidget_p.h>
 #include <private/qlayoutengine_p.h>    // qSmartMin functions...
 #if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC)
 #include <QMacStyle>
@@ -2582,33 +2583,87 @@ void tst_QGraphicsProxyWidget::changingCursor_basic()
 
 void tst_QGraphicsProxyWidget::tooltip_basic()
 {
-    // Confirm that mouse events are working properly by checking that
-    // when moving the mouse over a label with a tooptip the tooltip appears
+    QString toolTip = "Qt rocks!";
+    QString toolTip2 = "Qt rocks even more!";
+
+    QPushButton *button = new QPushButton("button");
+    QGraphicsProxyWidget *proxy = new QGraphicsProxyWidget;
+    QGraphicsProxyWidgetPrivate *proxyd = static_cast<QGraphicsProxyWidgetPrivate *>(QGraphicsItemPrivate::get(proxy));
+    proxy->setWidget(button);
+    proxyd->lastWidgetUnderMouse = button; // force widget under mouse
+
+    QVERIFY(button->toolTip().isEmpty());
+    QVERIFY(proxy->toolTip().isEmpty());
+    // Check that setting the tooltip on the proxy also set it on the widget
+    proxy->setToolTip(toolTip);
+    QCOMPARE(proxy->toolTip(), toolTip);
+    QCOMPARE(button->toolTip(), toolTip);
+    // Check that setting the tooltip on the widget also set it on the proxy
+    button->setToolTip(toolTip2);
+    QCOMPARE(proxy->toolTip(), toolTip2);
+    QCOMPARE(button->toolTip(), toolTip2);
+
     QGraphicsScene scene;
+    scene.addItem(proxy);
+
     QGraphicsView view(&scene);
+    view.setFixedSize(200, 200);
     view.show();
+    QTest::qWaitForWindowShown(&view);
+    {
+        QHelpEvent helpEvent(QEvent::ToolTip, view.viewport()->rect().topLeft(),
+                             view.viewport()->mapToGlobal(view.viewport()->rect().topLeft()));
+        QApplication::sendEvent(view.viewport(), &helpEvent);
+        QTest::qWait(350);
+
+        bool foundView = false;
+        bool foundTipLabel = false;
+        foreach (QWidget *widget, QApplication::topLevelWidgets()) {
+            if (widget == &view)
+                foundView = true;
+            if (widget->inherits("QTipLabel"))
+                foundTipLabel = true;
+        }
+        QVERIFY(foundView);
+        QVERIFY(!foundTipLabel);
+    }
 
-    QSKIP("Tooltips don't work yet", SkipAll);
-
-    SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
-    QLabel *widget = new QLabel;
-    widget->setText("If it ain't tested it's broken");
-    widget->setToolTip("When in doubt, test");
-    proxy->setWidget(widget);
-    widget->show();
-    scene.addItem(proxy);
-    QTest::qWait(125);
-
-    // in
-    QTest::mouseMove(view.viewport(), view.mapFromScene(proxy->mapToScene(proxy->boundingRect().center())));
+    {
+        QHelpEvent helpEvent(QEvent::ToolTip, view.mapFromScene(proxy->boundingRect().center()),
+                             view.viewport()->mapToGlobal(view.mapFromScene(proxy->boundingRect().center())));
+        QApplication::sendEvent(view.viewport(), &helpEvent);
+        QTest::qWait(350);
+
+        bool foundView = false;
+        bool foundTipLabel = false;
+        foreach (QWidget *widget, QApplication::topLevelWidgets()) {
+            if (widget == &view)
+                foundView = true;
+            if (widget->inherits("QTipLabel"))
+                foundTipLabel = true;
+        }
+        QVERIFY(foundView);
+        QVERIFY(foundTipLabel);
+    }
 
-    QTRY_COMPARE(proxy->childItems().count(), 1);
-    QGraphicsProxyWidget *child = (QGraphicsProxyWidget*)(proxy->childItems())[0];
-    QVERIFY(child->isWidget());
-    QVERIFY(child->widget());
-    QCOMPARE(child->widget()->parent(), static_cast<QObject*>(widget));
-    QCOMPARE(child->widget()->x(), widget->x()); // ### ???
-    QCOMPARE(child->widget()->y(), widget->y() + widget->height()); // ### ???
+    {
+        QHelpEvent helpEvent(QEvent::ToolTip, view.viewport()->rect().topLeft(),
+                             view.viewport()->mapToGlobal(view.viewport()->rect().topLeft()));
+        QApplication::sendEvent(view.viewport(), &helpEvent);
+        // Wait 350ms because the tooltip only hides after 300ms...
+        QTest::qWait(350);
+
+        bool foundView = false;
+        bool foundTipLabel = false;
+        foreach (QWidget *widget, QApplication::topLevelWidgets()) {
+            if (widget == &view)
+                foundView = true;
+            if (widget->inherits("QTipLabel") && widget->isVisible())
+                foundTipLabel = true;
+        }
+        QVERIFY(foundView);
+        QVERIFY(!foundTipLabel);
+    }
 }
 
 void tst_QGraphicsProxyWidget::childPos_data()
-- 
cgit v0.12