+++ /dev/null
-/****************************************************************************
-**
-** Copyright (C) Qxt Foundation. Some rights reserved.
-**
-** This file is part of the QxtGui module of the Qt eXTension library
-**
-** This library is free software; you can redistribute it and/or modify it
-** under the terms of th Common Public License, version 1.0, as published by
-** IBM.
-**
-** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
-** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
-** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
-** FITNESS FOR A PARTICULAR PURPOSE.
-**
-** You should have received a copy of the CPL along with this file.
-** See the LICENSE file and the cpl1.0.txt file included with the source
-** distribution for more information. If you did not receive a copy of the
-** license, contact the Qxt Foundation.
-**
-** <http://libqxt.sourceforge.net> <foundation@libqxt.org>
-**
-****************************************************************************/
-#include "qxttooltip.h"
-#include "qxttooltip_p.h"
-#include <QStyleOptionFrame>
-#include <QDesktopWidget>
-#include <QStylePainter>
-#include <QApplication>
-#include <QVBoxLayout>
-#include <QMouseEvent>
-#include <QKeyEvent>
-#include <QToolTip>
-#include <QPalette>
-#include <QTimer>
-#include <QFrame>
-#include <QStyle>
-#include <QHash>
-
-static const Qt::WindowFlags FLAGS = Qt::ToolTip;
-
-QxtToolTipPrivate* QxtToolTipPrivate::self = 0;
-
-QxtToolTipPrivate* QxtToolTipPrivate::instance()
-{
- if (!self)
- self = new QxtToolTipPrivate();
- return self;
-}
-
-QxtToolTipPrivate::QxtToolTipPrivate() : QWidget(qApp->desktop(), FLAGS)
-{
- setWindowFlags(FLAGS);
- vbox = new QVBoxLayout(this);
- setPalette(QToolTip::palette());
- setWindowOpacity(style()->styleHint(QStyle::SH_ToolTipLabel_Opacity, 0, this) / 255.0);
- layout()->setMargin(style()->pixelMetric(QStyle::PM_ToolTipLabelFrameWidth, 0, this));
- qApp->installEventFilter(this);
-}
-
-QxtToolTipPrivate::~QxtToolTipPrivate()
-{
- qApp->removeEventFilter(this); // not really necessary but rather for completeness :)
- self = 0;
-}
-
-void QxtToolTipPrivate::show(const QPoint& pos, QWidget* tooltip, QWidget* parent, const QRect& rect)
-{
- Q_ASSERT(tooltip && parent);
- if (!isVisible())
- {
- int scr = 0;
- if (QApplication::desktop()->isVirtualDesktop())
- scr = QApplication::desktop()->screenNumber(pos);
- else
- scr = QApplication::desktop()->screenNumber(this);
- setParent(QApplication::desktop()->screen(scr));
- setWindowFlags(FLAGS);
- setToolTip(tooltip);
- currentParent = parent;
- currentRect = rect;
- move(calculatePos(scr, pos));
- QWidget::show();
- }
-}
-
-void QxtToolTipPrivate::setToolTip(QWidget* tooltip)
-{
- for (int i = 0; i < vbox->count(); ++i)
- {
- QLayoutItem* item = layout()->takeAt(i);
- if (item->widget())
- item->widget()->hide();
- }
- vbox->addWidget(tooltip);
- tooltip->show();
-}
-
-void QxtToolTipPrivate::enterEvent(QEvent* event)
-{
- Q_UNUSED(event);
- hideLater();
-}
-
-void QxtToolTipPrivate::paintEvent(QPaintEvent* event)
-{
- Q_UNUSED(event);
- QStylePainter painter(this);
- QStyleOptionFrame opt;
- opt.initFrom(this);
- painter.drawPrimitive(QStyle::PE_PanelTipLabel, opt);
-}
-
-bool QxtToolTipPrivate::eventFilter(QObject* object, QEvent* event)
-{
- switch (event->type())
- {
- case QEvent::KeyPress:
- case QEvent::KeyRelease:
- {
- // accept only modifiers
- const QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
- const int key = keyEvent->key();
- const Qt::KeyboardModifiers mods = keyEvent->modifiers();
- if ((mods & Qt::KeyboardModifierMask) ||
- (key == Qt::Key_Shift || key == Qt::Key_Control ||
- key == Qt::Key_Alt || key == Qt::Key_Meta))
- break;
- }
- case QEvent::Leave:
- case QEvent::WindowActivate:
- case QEvent::WindowDeactivate:
- case QEvent::MouseButtonPress:
- case QEvent::MouseButtonRelease:
- case QEvent::MouseButtonDblClick:
- case QEvent::FocusIn:
- case QEvent::FocusOut:
- case QEvent::Wheel:
- hideLater();
- break;
-
- case QEvent::MouseMove:
- {
- const QPoint pos = static_cast<QMouseEvent*>(event)->pos();
- if (!currentRect.isNull() && !currentRect.contains(pos))
- {
- hideLater();
- }
- break;
- }
-
- case QEvent::ToolTip:
- {
- // eat appropriate tooltip events
- QWidget* widget = static_cast<QWidget*>(object);
- if (tooltips.contains(widget))
- {
- QHelpEvent* helpEvent = static_cast<QHelpEvent*>(event);
- const QRect area = tooltips.value(widget).second;
- if (area.isNull() || area.contains(helpEvent->pos()))
- {
- show(helpEvent->globalPos(), tooltips.value(widget).first, widget, area);
- return true;
- }
- }
- }
-
- default:
- break;
- }
- return false;
-}
-
-void QxtToolTipPrivate::hideLater()
-{
- currentRect = QRect();
- if (isVisible())
- QTimer::singleShot(0, this, SLOT(hide()));
-}
-
-QPoint QxtToolTipPrivate::calculatePos(int scr, const QPoint& eventPos) const
-{
-#ifdef Q_WS_MAC
- QRect screen = QApplication::desktop()->availableGeometry(scr);
-#else
- QRect screen = QApplication::desktop()->screenGeometry(scr);
-#endif
-
- QPoint p = eventPos;
- p += QPoint(2,
-#ifdef Q_WS_WIN
- 24
-#else
- 16
-#endif
- );
- QSize s = sizeHint();
- if (p.x() + s.width() > screen.x() + screen.width())
- p.rx() -= 4 + s.width();
- if (p.y() + s.height() > screen.y() + screen.height())
- p.ry() -= 24 + s.height();
- if (p.y() < screen.y())
- p.setY(screen.y());
- if (p.x() + s.width() > screen.x() + screen.width())
- p.setX(screen.x() + screen.width() - s.width());
- if (p.x() < screen.x())
- p.setX(screen.x());
- if (p.y() + s.height() > screen.y() + screen.height())
- p.setY(screen.y() + screen.height() - s.height());
- return p;
-}
-
-/*!
- \class QxtToolTip QxtToolTip
- \ingroup QxtGui
- \brief Show any arbitrary widget as a tooltip.
-
- QxtToolTip provides means for showing any arbitrary widget as a tooltip.
-
- \note The rich text support of QToolTip already makes it possible to
- show heavily customized tooltips with lists, tables, embedded images
- and such. However, for example dynamically created images like
- thumbnails cause problems. Basically the only way is to dump the
- thumbnail to a temporary file to be able to embed it into HTML. This
- is where QxtToolTip steps in. A generated thumbnail may simply be set
- on a QLabel which is then shown as a tooltip. Yet another use case
- is a tooltip with dynamically changing content.
-
- \image html qxttooltip.png "QxtToolTip in action."
-
- \warning Added tooltip widgets remain in the memory for the lifetime
- of the application or until they are removed/deleted. Do NOT flood your
- application up with lots of complex tooltip widgets or it will end up
- being a resource hog. QToolTip is sufficient for most of the cases!
- */
-
-/*!
- Shows the \a tooltip at \a pos for \a parent at \a rect.
-
- \sa hide()
-*/
-void QxtToolTip::show(const QPoint& pos, QWidget* tooltip, QWidget* parent, const QRect& rect)
-{
- QxtToolTipPrivate::instance()->show(pos, tooltip, parent, rect);
-}
-
-/*!
- Hides the tooltip.
-
- \sa show()
-*/
-void QxtToolTip::hide()
-{
- QxtToolTipPrivate::instance()->hide();
-}
-
-/*!
- Returns the tooltip for \a parent.
-
- \sa setToolTip()
-*/
-QWidget* QxtToolTip::toolTip(QWidget* parent)
-{
- Q_ASSERT(parent);
- QWidget* tooltip = 0;
- if (!QxtToolTipPrivate::instance()->tooltips.contains(parent))
- qWarning("QxtToolTip::toolTip: Unknown parent");
- else
- tooltip = QxtToolTipPrivate::instance()->tooltips.value(parent).first;
- return tooltip;
-}
-
-/*!
- Sets the \a tooltip to be shown for \a parent.
- An optional \a rect may also be passed.
-
- \sa toolTip()
-*/
-void QxtToolTip::setToolTip(QWidget* parent, QWidget* tooltip, const QRect& rect)
-{
- Q_ASSERT(parent);
- if (tooltip)
- {
- // set
- tooltip->hide();
- QxtToolTipPrivate::instance()->tooltips[parent] = qMakePair(QPointer<QWidget>(tooltip), rect);
- }
- else
- {
- // remove
- if (!QxtToolTipPrivate::instance()->tooltips.contains(parent))
- qWarning("QxtToolTip::setToolTip: Unknown parent");
- else
- QxtToolTipPrivate::instance()->tooltips.remove(parent);
- }
-}
-
-/*!
- Returns the rect on which tooltip is shown for \a parent.
-
- \sa setToolTipRect()
-*/
-QRect QxtToolTip::toolTipRect(QWidget* parent)
-{
- Q_ASSERT(parent);
- QRect rect;
- if (!QxtToolTipPrivate::instance()->tooltips.contains(parent))
- qWarning("QxtToolTip::toolTipRect: Unknown parent");
- else
- rect = QxtToolTipPrivate::instance()->tooltips.value(parent).second;
- return rect;
-}
-
-/*!
- Sets the \a rect on which tooltip is shown for \a parent.
-
- \sa toolTipRect()
-*/
-void QxtToolTip::setToolTipRect(QWidget* parent, const QRect& rect)
-{
- Q_ASSERT(parent);
- if (!QxtToolTipPrivate::instance()->tooltips.contains(parent))
- qWarning("QxtToolTip::setToolTipRect: Unknown parent");
- else
- QxtToolTipPrivate::instance()->tooltips[parent].second = rect;
-}
-
-/*!
- Returns the margin of the tooltip.
-
- \sa setMargin()
-*/
-int QxtToolTip::margin()
-{
- return QxtToolTipPrivate::instance()->layout()->margin();
-}
-
-/*!
- Sets the margin of the tooltip.
-
- The default value is \b QStyle::PM_ToolTipLabelFrameWidth.
-
- \sa margin()
-*/
-void QxtToolTip::setMargin(int margin)
-{
- QxtToolTipPrivate::instance()->layout()->setMargin(margin);
-}
-
-/*!
- Returns the opacity level of the tooltip.
-
- \sa QWidget::windowOpacity()
-*/
-qreal QxtToolTip::opacity()
-{
- return QxtToolTipPrivate::instance()->windowOpacity();
-}
-
-/*!
- Sets the opacity level of the tooltip.
-
- The default value is \b QStyle::SH_ToolTipLabel_Opacity.
-
- \sa QWidget::setWindowOpacity()
-*/
-void QxtToolTip::setOpacity(qreal level)
-{
- QxtToolTipPrivate::instance()->setWindowOpacity(level);
-}