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