1 /****************************************************************************
3 ** Copyright (C) Qxt Foundation. Some rights reserved.
5 ** This file is part of the QxtGui module of the Qt eXTension library
7 ** This library is free software; you can redistribute it and/or modify it
8 ** under the terms of th Common Public License, version 1.0, as published by
11 ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
12 ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
13 ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
14 ** FITNESS FOR A PARTICULAR PURPOSE.
16 ** You should have received a copy of the CPL along with this file.
17 ** See the LICENSE file and the cpl1.0.txt file included with the source
18 ** distribution for more information. If you did not receive a copy of the
19 ** license, contact the Qxt Foundation.
21 ** <http://libqxt.sourceforge.net> <foundation@libqxt.org>
23 ****************************************************************************/
24 #include "qxttooltip.h"
25 #include "qxttooltip_p.h"
26 #include <QStyleOptionFrame>
27 #include <QDesktopWidget>
28 #include <QStylePainter>
29 #include <QApplication>
30 #include <QVBoxLayout>
31 #include <QMouseEvent>
40 static const Qt::WindowFlags FLAGS = Qt::ToolTip;
42 QxtToolTipPrivate* QxtToolTipPrivate::self = 0;
44 QxtToolTipPrivate* QxtToolTipPrivate::instance()
47 self = new QxtToolTipPrivate();
51 QxtToolTipPrivate::QxtToolTipPrivate() : QWidget(qApp->desktop(), FLAGS)
53 setWindowFlags(FLAGS);
54 vbox = new QVBoxLayout(this);
55 setPalette(QToolTip::palette());
56 setWindowOpacity(style()->styleHint(QStyle::SH_ToolTipLabel_Opacity, 0, this) / 255.0);
57 layout()->setMargin(style()->pixelMetric(QStyle::PM_ToolTipLabelFrameWidth, 0, this));
58 qApp->installEventFilter(this);
61 QxtToolTipPrivate::~QxtToolTipPrivate()
63 qApp->removeEventFilter(this); // not really necessary but rather for completeness :)
67 void QxtToolTipPrivate::show(const QPoint& pos, QWidget* tooltip, QWidget* parent, const QRect& rect)
69 Q_ASSERT(tooltip && parent);
73 if (QApplication::desktop()->isVirtualDesktop())
74 scr = QApplication::desktop()->screenNumber(pos);
76 scr = QApplication::desktop()->screenNumber(this);
77 setParent(QApplication::desktop()->screen(scr));
78 setWindowFlags(FLAGS);
80 currentParent = parent;
82 move(calculatePos(scr, pos));
87 void QxtToolTipPrivate::setToolTip(QWidget* tooltip)
89 for (int i = 0; i < vbox->count(); ++i)
91 QLayoutItem* item = layout()->takeAt(i);
93 item->widget()->hide();
95 vbox->addWidget(tooltip);
99 void QxtToolTipPrivate::enterEvent(QEvent* event)
105 void QxtToolTipPrivate::paintEvent(QPaintEvent* event)
108 QStylePainter painter(this);
109 QStyleOptionFrame opt;
111 painter.drawPrimitive(QStyle::PE_PanelTipLabel, opt);
114 bool QxtToolTipPrivate::eventFilter(QObject* object, QEvent* event)
116 switch (event->type())
118 case QEvent::KeyPress:
119 case QEvent::KeyRelease:
121 // accept only modifiers
122 const QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
123 const int key = keyEvent->key();
124 const Qt::KeyboardModifiers mods = keyEvent->modifiers();
125 if ((mods & Qt::KeyboardModifierMask) ||
126 (key == Qt::Key_Shift || key == Qt::Key_Control ||
127 key == Qt::Key_Alt || key == Qt::Key_Meta))
131 case QEvent::WindowActivate:
132 case QEvent::WindowDeactivate:
133 case QEvent::MouseButtonPress:
134 case QEvent::MouseButtonRelease:
135 case QEvent::MouseButtonDblClick:
136 case QEvent::FocusIn:
137 case QEvent::FocusOut:
142 case QEvent::MouseMove:
144 const QPoint pos = static_cast<QMouseEvent*>(event)->pos();
145 if (!currentRect.isNull() && !currentRect.contains(pos))
152 case QEvent::ToolTip:
154 // eat appropriate tooltip events
155 QWidget* widget = static_cast<QWidget*>(object);
156 if (tooltips.contains(widget))
158 QHelpEvent* helpEvent = static_cast<QHelpEvent*>(event);
159 const QRect area = tooltips.value(widget).second;
160 if (area.isNull() || area.contains(helpEvent->pos()))
162 show(helpEvent->globalPos(), tooltips.value(widget).first, widget, area);
174 void QxtToolTipPrivate::hideLater()
176 currentRect = QRect();
178 QTimer::singleShot(0, this, SLOT(hide()));
181 QPoint QxtToolTipPrivate::calculatePos(int scr, const QPoint& eventPos) const
184 QRect screen = QApplication::desktop()->availableGeometry(scr);
186 QRect screen = QApplication::desktop()->screenGeometry(scr);
197 QSize s = sizeHint();
198 if (p.x() + s.width() > screen.x() + screen.width())
199 p.rx() -= 4 + s.width();
200 if (p.y() + s.height() > screen.y() + screen.height())
201 p.ry() -= 24 + s.height();
202 if (p.y() < screen.y())
204 if (p.x() + s.width() > screen.x() + screen.width())
205 p.setX(screen.x() + screen.width() - s.width());
206 if (p.x() < screen.x())
208 if (p.y() + s.height() > screen.y() + screen.height())
209 p.setY(screen.y() + screen.height() - s.height());
214 \class QxtToolTip QxtToolTip
216 \brief Show any arbitrary widget as a tooltip.
218 QxtToolTip provides means for showing any arbitrary widget as a tooltip.
220 \note The rich text support of QToolTip already makes it possible to
221 show heavily customized tooltips with lists, tables, embedded images
222 and such. However, for example dynamically created images like
223 thumbnails cause problems. Basically the only way is to dump the
224 thumbnail to a temporary file to be able to embed it into HTML. This
225 is where QxtToolTip steps in. A generated thumbnail may simply be set
226 on a QLabel which is then shown as a tooltip. Yet another use case
227 is a tooltip with dynamically changing content.
229 \image html qxttooltip.png "QxtToolTip in action."
231 \warning Added tooltip widgets remain in the memory for the lifetime
232 of the application or until they are removed/deleted. Do NOT flood your
233 application up with lots of complex tooltip widgets or it will end up
234 being a resource hog. QToolTip is sufficient for most of the cases!
238 Shows the \a tooltip at \a pos for \a parent at \a rect.
242 void QxtToolTip::show(const QPoint& pos, QWidget* tooltip, QWidget* parent, const QRect& rect)
244 QxtToolTipPrivate::instance()->show(pos, tooltip, parent, rect);
252 void QxtToolTip::hide()
254 QxtToolTipPrivate::instance()->hide();
258 Returns the tooltip for \a parent.
262 QWidget* QxtToolTip::toolTip(QWidget* parent)
265 QWidget* tooltip = 0;
266 if (!QxtToolTipPrivate::instance()->tooltips.contains(parent))
267 qWarning("QxtToolTip::toolTip: Unknown parent");
269 tooltip = QxtToolTipPrivate::instance()->tooltips.value(parent).first;
274 Sets the \a tooltip to be shown for \a parent.
275 An optional \a rect may also be passed.
279 void QxtToolTip::setToolTip(QWidget* parent, QWidget* tooltip, const QRect& rect)
286 QxtToolTipPrivate::instance()->tooltips[parent] = qMakePair(QPointer<QWidget>(tooltip), rect);
291 if (!QxtToolTipPrivate::instance()->tooltips.contains(parent))
292 qWarning("QxtToolTip::setToolTip: Unknown parent");
294 QxtToolTipPrivate::instance()->tooltips.remove(parent);
299 Returns the rect on which tooltip is shown for \a parent.
303 QRect QxtToolTip::toolTipRect(QWidget* parent)
307 if (!QxtToolTipPrivate::instance()->tooltips.contains(parent))
308 qWarning("QxtToolTip::toolTipRect: Unknown parent");
310 rect = QxtToolTipPrivate::instance()->tooltips.value(parent).second;
315 Sets the \a rect on which tooltip is shown for \a parent.
319 void QxtToolTip::setToolTipRect(QWidget* parent, const QRect& rect)
322 if (!QxtToolTipPrivate::instance()->tooltips.contains(parent))
323 qWarning("QxtToolTip::setToolTipRect: Unknown parent");
325 QxtToolTipPrivate::instance()->tooltips[parent].second = rect;
329 Returns the margin of the tooltip.
333 int QxtToolTip::margin()
335 return QxtToolTipPrivate::instance()->layout()->margin();
339 Sets the margin of the tooltip.
341 The default value is \b QStyle::PM_ToolTipLabelFrameWidth.
345 void QxtToolTip::setMargin(int margin)
347 QxtToolTipPrivate::instance()->layout()->setMargin(margin);
351 Returns the opacity level of the tooltip.
353 \sa QWidget::windowOpacity()
355 qreal QxtToolTip::opacity()
357 return QxtToolTipPrivate::instance()->windowOpacity();
361 Sets the opacity level of the tooltip.
363 The default value is \b QStyle::SH_ToolTipLabel_Opacity.
365 \sa QWidget::setWindowOpacity()
367 void QxtToolTip::setOpacity(qreal level)
369 QxtToolTipPrivate::instance()->setWindowOpacity(level);