1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Nokia gives you certain additional
26 ** rights. These rights are described in the Nokia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
32 **************************************************************************/
36 #include "tipcontents.h"
37 #include "tipfactory.h"
41 #include <QtCore/QString>
42 #include <QtGui/QColor>
43 #include <QtGui/QApplication>
44 #include <QtGui/QKeyEvent>
45 #include <QtGui/QMouseEvent>
46 #include <QtGui/QMenu>
48 #include <QtCore/QDebug>
50 using namespace TextEditor;
51 using namespace Internal;
53 ToolTip::ToolTip() : m_tipFactory(new TipFactory), m_tip(0), m_widget(0)
55 connect(&m_showTimer, SIGNAL(timeout()), this, SLOT(hideTipImmediately()));
56 connect(&m_hideDelayTimer, SIGNAL(timeout()), this, SLOT(hideTipImmediately()));
65 ToolTip *ToolTip::instance()
67 static ToolTip tooltip;
71 void ToolTip::show(const QPoint &pos, const TipContent &content, QWidget *w, const QRect &rect)
73 if (acceptShow(content, pos, w, rect)) {
75 m_tip = m_tipFactory->createTip(content, w);
77 m_tip = m_tipFactory->createTip(
78 content, QApplication::desktop()->screen(Internal::screenNumber(pos, w)));
80 setUp(pos, content, w, rect);
81 qApp->installEventFilter(this);
86 void ToolTip::show(const QPoint &pos, const TipContent &content, QWidget *w)
88 show(pos, content, w, QRect());
91 bool ToolTip::acceptShow(const TipContent &content,
96 if (!validateContent(content))
100 if (m_tip->canHandleContentReplacement(content)) {
101 // Reuse current tip.
102 QPoint localPos = pos;
104 localPos = w->mapFromGlobal(pos);
105 if (tipChanged(localPos, content, w))
106 setUp(pos, content, w, rect);
109 hideTipImmediately();
111 #if !defined(QT_NO_EFFECTS) && !defined(Q_WS_MAC)
112 // While the effect takes places it might be that although the widget is actually on
113 // screen the isVisible method doesn't return true.
115 && (QApplication::isEffectEnabled(Qt::UI_FadeTooltip)
116 || QApplication::isEffectEnabled(Qt::UI_AnimateTooltip))) {
117 hideTipImmediately();
123 bool ToolTip::validateContent(const TipContent &content)
125 if (!content.isValid()) {
133 void ToolTip::setUp(const QPoint &pos, const TipContent &content, QWidget *w, const QRect &rect)
135 m_tip->setContent(content);
136 m_tip->configure(pos, w);
141 if (m_hideDelayTimer.isActive())
142 m_hideDelayTimer.stop();
143 m_showTimer.start(content.showTime());
146 bool ToolTip::tipChanged(const QPoint &pos, const TipContent &content, QWidget *w) const
148 if (!m_tip->content().equals(content) || m_widget != w)
150 if (!m_rect.isNull())
151 return !m_rect.contains(pos);
155 void ToolTip::setTipRect(QWidget *w, const QRect &rect)
157 if (!m_rect.isNull() && !w)
158 qWarning("ToolTip::show: Cannot pass null widget if rect is set");
165 bool ToolTip::isVisible() const
167 return m_tip && m_tip->isVisible();
170 void ToolTip::showTip()
172 #if !defined(QT_NO_EFFECTS) && !defined(Q_WS_MAC)
173 if (QApplication::isEffectEnabled(Qt::UI_FadeTooltip))
175 else if (QApplication::isEffectEnabled(Qt::UI_AnimateTooltip))
176 qScrollEffect(m_tip);
189 void ToolTip::hideTipWithDelay()
191 if (!m_hideDelayTimer.isActive())
192 m_hideDelayTimer.start(300);
195 void ToolTip::hideTipImmediately()
199 m_tip->deleteLater();
203 m_hideDelayTimer.stop();
204 qApp->removeEventFilter(this);
207 void ToolTip::placeTip(const QPoint &pos, QWidget *w)
209 QRect screen = Internal::screenGeometry(pos, w);
219 if (p.x() + m_tip->width() > screen.x() + screen.width())
220 p.rx() -= 4 + m_tip->width();
221 if (p.y() + m_tip->height() > screen.y() + screen.height())
222 p.ry() -= 24 + m_tip->height();
223 if (p.y() < screen.y())
225 if (p.x() + m_tip->width() > screen.x() + screen.width())
226 p.setX(screen.x() + screen.width() - m_tip->width());
227 if (p.x() < screen.x())
229 if (p.y() + m_tip->height() > screen.y() + screen.height())
230 p.setY(screen.y() + screen.height() - m_tip->height());
235 bool ToolTip::eventFilter(QObject *o, QEvent *event)
237 if (!o->isWidgetType())
240 switch (event->type()) {
242 case QEvent::KeyPress:
243 case QEvent::KeyRelease: {
244 int key = static_cast<QKeyEvent *>(event)->key();
245 Qt::KeyboardModifiers mody = static_cast<QKeyEvent *>(event)->modifiers();
246 if (!(mody & Qt::KeyboardModifierMask)
247 && key != Qt::Key_Shift && key != Qt::Key_Control
248 && key != Qt::Key_Alt && key != Qt::Key_Meta)
259 // User moved cursor into tip and wants to interact.
260 if (m_tip && m_tip->isInteractive() && o == m_tip) {
261 if (m_hideDelayTimer.isActive())
262 m_hideDelayTimer.stop();
265 case QEvent::WindowActivate:
266 case QEvent::WindowDeactivate:
267 case QEvent::FocusOut:
268 case QEvent::FocusIn:
269 if (m_tip && !m_tip->isInteractive()) // Windows: A sequence of those occurs when interacting
270 hideTipImmediately();
272 case QEvent::MouseButtonPress:
273 case QEvent::MouseButtonRelease:
274 case QEvent::MouseButtonDblClick:
277 if (m_tip->isInteractive()) { // Do not close on interaction with the tooltip
278 if (o != m_tip && !m_tip->isAncestorOf(static_cast<QWidget *>(o))) {
279 hideTipImmediately();
282 hideTipImmediately();
286 case QEvent::MouseMove:
289 !m_rect.contains(static_cast<QMouseEvent*>(event)->pos())) {
298 QFont ToolTip::font() const
300 return QApplication::font("QTipLabel");
303 void ToolTip::setFont(const QFont &font)
305 QApplication::setFont(font, "QTipLabel");