xref: /glogg/src/menuactiontooltipbehavior.cpp (revision bb02e0acf44ddb4e4f83d6127a1e488789162922)
1*bb02e0acSNicolas Bonnefon /*
2*bb02e0acSNicolas Bonnefon  * Copyright (C) 2009, 2010 Nicolas Bonnefon and other contributors
3*bb02e0acSNicolas Bonnefon  *
4*bb02e0acSNicolas Bonnefon  * This file is part of glogg.
5*bb02e0acSNicolas Bonnefon  *
6*bb02e0acSNicolas Bonnefon  * glogg is free software: you can redistribute it and/or modify
7*bb02e0acSNicolas Bonnefon  * it under the terms of the GNU General Public License as published by
8*bb02e0acSNicolas Bonnefon  * the Free Software Foundation, either version 3 of the License, or
9*bb02e0acSNicolas Bonnefon  * (at your option) any later version.
10*bb02e0acSNicolas Bonnefon  *
11*bb02e0acSNicolas Bonnefon  * glogg is distributed in the hope that it will be useful,
12*bb02e0acSNicolas Bonnefon  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13*bb02e0acSNicolas Bonnefon  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*bb02e0acSNicolas Bonnefon  * GNU General Public License for more details.
15*bb02e0acSNicolas Bonnefon  *
16*bb02e0acSNicolas Bonnefon  * You should have received a copy of the GNU General Public License
17*bb02e0acSNicolas Bonnefon  * along with glogg.  If not, see <http://www.gnu.org/licenses/>.
18*bb02e0acSNicolas Bonnefon  */
19*bb02e0acSNicolas Bonnefon 
20*bb02e0acSNicolas Bonnefon #include <QAction>
21*bb02e0acSNicolas Bonnefon #include <QMenu>
22*bb02e0acSNicolas Bonnefon #include <QTimerEvent>
23*bb02e0acSNicolas Bonnefon #include <QToolTip>
24*bb02e0acSNicolas Bonnefon 
25*bb02e0acSNicolas Bonnefon #include "menuactiontooltipbehavior.h"
26*bb02e0acSNicolas Bonnefon 
27*bb02e0acSNicolas Bonnefon // It would be nice to only need action, and have action be the parent,
28*bb02e0acSNicolas Bonnefon // however implementation needs the parent menu (see showToolTip), and
29*bb02e0acSNicolas Bonnefon // since neither action nor parent is guaranteed to die before the other,
30*bb02e0acSNicolas Bonnefon // for memory-management purposes the parent will have to be specified
31*bb02e0acSNicolas Bonnefon // explicity (probably, the window owning the action and the menu).
MenuActionToolTipBehavior(QAction * action,QMenu * parentMenu,QObject * parent=0)32*bb02e0acSNicolas Bonnefon MenuActionToolTipBehavior::MenuActionToolTipBehavior(QAction *action,
33*bb02e0acSNicolas Bonnefon                                                      QMenu *parentMenu,
34*bb02e0acSNicolas Bonnefon                                                      QObject *parent = 0)
35*bb02e0acSNicolas Bonnefon     : QObject(parent),
36*bb02e0acSNicolas Bonnefon       action(action),
37*bb02e0acSNicolas Bonnefon       parentMenu(parentMenu),
38*bb02e0acSNicolas Bonnefon       toolTipDelayMs(1000),
39*bb02e0acSNicolas Bonnefon       timerId(0),
40*bb02e0acSNicolas Bonnefon       hoverPoint()
41*bb02e0acSNicolas Bonnefon {
42*bb02e0acSNicolas Bonnefon     connect(action, SIGNAL(hovered()), this, SLOT(onActionHovered()));
43*bb02e0acSNicolas Bonnefon }
44*bb02e0acSNicolas Bonnefon 
toolTipDelay()45*bb02e0acSNicolas Bonnefon int MenuActionToolTipBehavior::toolTipDelay()
46*bb02e0acSNicolas Bonnefon {
47*bb02e0acSNicolas Bonnefon     return toolTipDelayMs;
48*bb02e0acSNicolas Bonnefon }
49*bb02e0acSNicolas Bonnefon 
setToolTipDelay(int delayMs)50*bb02e0acSNicolas Bonnefon void MenuActionToolTipBehavior::setToolTipDelay(int delayMs)
51*bb02e0acSNicolas Bonnefon {
52*bb02e0acSNicolas Bonnefon     toolTipDelayMs = delayMs;
53*bb02e0acSNicolas Bonnefon }
54*bb02e0acSNicolas Bonnefon 
timerEvent(QTimerEvent * event)55*bb02e0acSNicolas Bonnefon void MenuActionToolTipBehavior::timerEvent(QTimerEvent *event)
56*bb02e0acSNicolas Bonnefon {
57*bb02e0acSNicolas Bonnefon     // Not ours, don't touch
58*bb02e0acSNicolas Bonnefon     if (event->timerId() != timerId) {
59*bb02e0acSNicolas Bonnefon         QObject::timerEvent(event);
60*bb02e0acSNicolas Bonnefon         return;
61*bb02e0acSNicolas Bonnefon     }
62*bb02e0acSNicolas Bonnefon 
63*bb02e0acSNicolas Bonnefon     killTimer(timerId); // interested in a single shot
64*bb02e0acSNicolas Bonnefon     timerId = 0;
65*bb02e0acSNicolas Bonnefon 
66*bb02e0acSNicolas Bonnefon     // Has the mouse waited unmoved in one location for 'delay' ms?
67*bb02e0acSNicolas Bonnefon     const QPoint &mousePos = QCursor::pos();
68*bb02e0acSNicolas Bonnefon     if (hoverPoint == mousePos)
69*bb02e0acSNicolas Bonnefon         showToolTip(hoverPoint);
70*bb02e0acSNicolas Bonnefon }
71*bb02e0acSNicolas Bonnefon 
onActionHovered()72*bb02e0acSNicolas Bonnefon void MenuActionToolTipBehavior::onActionHovered()
73*bb02e0acSNicolas Bonnefon {
74*bb02e0acSNicolas Bonnefon     const QPoint &mousePos = QCursor::pos();
75*bb02e0acSNicolas Bonnefon 
76*bb02e0acSNicolas Bonnefon     // Hover is fired on keyboard focus over action in menu, ignore it
77*bb02e0acSNicolas Bonnefon     const QPoint &relativeMousePos = parentMenu->mapFromGlobal(mousePos);
78*bb02e0acSNicolas Bonnefon     if (!parentMenu->actionGeometry(action).contains(relativeMousePos)) {
79*bb02e0acSNicolas Bonnefon         if (timerId != 0) { // once timer expires its check will fail anyway
80*bb02e0acSNicolas Bonnefon             killTimer(timerId);
81*bb02e0acSNicolas Bonnefon             timerId = 0;
82*bb02e0acSNicolas Bonnefon         }
83*bb02e0acSNicolas Bonnefon         QToolTip::hideText(); // there might be one currently shown
84*bb02e0acSNicolas Bonnefon         return;
85*bb02e0acSNicolas Bonnefon     }
86*bb02e0acSNicolas Bonnefon 
87*bb02e0acSNicolas Bonnefon     // Record location
88*bb02e0acSNicolas Bonnefon     hoverPoint = mousePos;
89*bb02e0acSNicolas Bonnefon 
90*bb02e0acSNicolas Bonnefon     // Restart timer
91*bb02e0acSNicolas Bonnefon     if (timerId != 0)
92*bb02e0acSNicolas Bonnefon         killTimer(timerId);
93*bb02e0acSNicolas Bonnefon     timerId = startTimer(toolTipDelayMs);
94*bb02e0acSNicolas Bonnefon }
95*bb02e0acSNicolas Bonnefon 
showToolTip(const QPoint & position)96*bb02e0acSNicolas Bonnefon void MenuActionToolTipBehavior::showToolTip(const QPoint &position)
97*bb02e0acSNicolas Bonnefon {
98*bb02e0acSNicolas Bonnefon     const QString &toolTip = action->toolTip();
99*bb02e0acSNicolas Bonnefon     // Show tooltip until mouse moves at all
100*bb02e0acSNicolas Bonnefon     // NOTE: using action->parentWidget() which is the MainWindow,
101*bb02e0acSNicolas Bonnefon     // does not work (tooltip is not cleared when upon leaving the
102*bb02e0acSNicolas Bonnefon     // region). This is the only reason we need parentMenu here. Just
103*bb02e0acSNicolas Bonnefon     // a wild guess: maybe it isn't cleared because it would be
104*bb02e0acSNicolas Bonnefon     // cleared on a mouse move over the designated widget, but mouse
105*bb02e0acSNicolas Bonnefon     // move doesn't happen over MainWindow, since the mouse is over
106*bb02e0acSNicolas Bonnefon     // the menu even when out of the activeRegion.
107*bb02e0acSNicolas Bonnefon     QPoint relativePos = parentMenu->mapFromGlobal(position);
108*bb02e0acSNicolas Bonnefon     QRect activeRegion(relativePos.x(), relativePos.y(), 1, 1);
109*bb02e0acSNicolas Bonnefon     QToolTip::showText(position, toolTip, parentMenu, activeRegion);
110*bb02e0acSNicolas Bonnefon }
111