Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "qxttooltip.h"
00026 #include "qxttooltip_p.h"
00027 #include <QStyleOptionFrame>
00028 #include <QDesktopWidget>
00029 #include <QStylePainter>
00030 #include <QApplication>
00031 #include <QVBoxLayout>
00032 #include <QMouseEvent>
00033 #include <QKeyEvent>
00034 #include <QToolTip>
00035 #include <QPalette>
00036 #include <QTimer>
00037 #include <QFrame>
00038 #include <QStyle>
00039 #include <QHash>
00040
00041 static const Qt::WindowFlags FLAGS = Qt::ToolTip;
00042
00043 QxtToolTipPrivate* QxtToolTipPrivate::self = 0;
00044
00045 QxtToolTipPrivate* QxtToolTipPrivate::instance()
00046 {
00047 if (!self)
00048 self = new QxtToolTipPrivate();
00049 return self;
00050 }
00051
00052 QxtToolTipPrivate::QxtToolTipPrivate() : QWidget(qApp->desktop(), FLAGS)
00053 {
00054 setWindowFlags(FLAGS);
00055 vbox = new QVBoxLayout(this);
00056 setPalette(QToolTip::palette());
00057 setWindowOpacity(style()->styleHint(QStyle::SH_ToolTipLabel_Opacity, 0, this) / 255.0);
00058 layout()->setMargin(style()->pixelMetric(QStyle::PM_ToolTipLabelFrameWidth, 0, this));
00059 qApp->installEventFilter(this);
00060 }
00061
00062 QxtToolTipPrivate::~QxtToolTipPrivate()
00063 {
00064 qApp->removeEventFilter(this);
00065 self = 0;
00066 }
00067
00068 void QxtToolTipPrivate::show(const QPoint& pos, QWidget* tooltip, QWidget* parent, const QRect& rect)
00069 {
00070 Q_ASSERT(tooltip && parent);
00071 if (!isVisible())
00072 {
00073 int scr = 0;
00074 if (QApplication::desktop()->isVirtualDesktop())
00075 scr = QApplication::desktop()->screenNumber(pos);
00076 else
00077 scr = QApplication::desktop()->screenNumber(this);
00078 setParent(QApplication::desktop()->screen(scr));
00079 setWindowFlags(FLAGS);
00080 setToolTip(tooltip);
00081 currentParent = parent;
00082 currentRect = rect;
00083 move(calculatePos(scr, pos));
00084 QWidget::show();
00085 }
00086 }
00087
00088 void QxtToolTipPrivate::setToolTip(QWidget* tooltip)
00089 {
00090 for (int i = 0; i < vbox->count(); ++i)
00091 {
00092 QLayoutItem* item = layout()->takeAt(i);
00093 if (item->widget())
00094 item->widget()->hide();
00095 }
00096 vbox->addWidget(tooltip);
00097 tooltip->show();
00098 }
00099
00100 void QxtToolTipPrivate::enterEvent(QEvent* event)
00101 {
00102 Q_UNUSED(event);
00103 hideLater();
00104 }
00105
00106 void QxtToolTipPrivate::paintEvent(QPaintEvent* event)
00107 {
00108 Q_UNUSED(event);
00109 QStylePainter painter(this);
00110 QStyleOptionFrame opt;
00111 opt.initFrom(this);
00112 painter.drawPrimitive(QStyle::PE_PanelTipLabel, opt);
00113 }
00114
00115 bool QxtToolTipPrivate::eventFilter(QObject* object, QEvent* event)
00116 {
00117 switch (event->type())
00118 {
00119 case QEvent::KeyPress:
00120 case QEvent::KeyRelease:
00121 {
00122
00123 const QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
00124 const int key = keyEvent->key();
00125 const Qt::KeyboardModifiers mods = keyEvent->modifiers();
00126 if ((mods & Qt::KeyboardModifierMask) ||
00127 (key == Qt::Key_Shift || key == Qt::Key_Control ||
00128 key == Qt::Key_Alt || key == Qt::Key_Meta))
00129 break;
00130 }
00131 case QEvent::Leave:
00132 case QEvent::WindowActivate:
00133 case QEvent::WindowDeactivate:
00134 case QEvent::MouseButtonPress:
00135 case QEvent::MouseButtonRelease:
00136 case QEvent::MouseButtonDblClick:
00137 case QEvent::FocusIn:
00138 case QEvent::FocusOut:
00139 case QEvent::Wheel:
00140 hideLater();
00141 break;
00142
00143 case QEvent::MouseMove:
00144 {
00145 const QPoint pos = static_cast<QMouseEvent*>(event)->pos();
00146 if (!currentRect.isNull() && !currentRect.contains(pos))
00147 {
00148 hideLater();
00149 }
00150 break;
00151 }
00152
00153 case QEvent::ToolTip:
00154 {
00155
00156 QWidget* widget = static_cast<QWidget*>(object);
00157 if (tooltips.contains(widget))
00158 {
00159 QHelpEvent* helpEvent = static_cast<QHelpEvent*>(event);
00160 const QRect area = tooltips.value(widget).second;
00161 if (area.isNull() || area.contains(helpEvent->pos()))
00162 {
00163 show(helpEvent->globalPos(), tooltips.value(widget).first, widget, area);
00164 return true;
00165 }
00166 }
00167 }
00168
00169 default:
00170 break;
00171 }
00172 return false;
00173 }
00174
00175 void QxtToolTipPrivate::hideLater()
00176 {
00177 currentRect = QRect();
00178 if (isVisible())
00179 QTimer::singleShot(0, this, SLOT(hide()));
00180 }
00181
00182 QPoint QxtToolTipPrivate::calculatePos(int scr, const QPoint& eventPos) const
00183 {
00184 #ifdef Q_WS_MAC
00185 QRect screen = QApplication::desktop()->availableGeometry(scr);
00186 #else
00187 QRect screen = QApplication::desktop()->screenGeometry(scr);
00188 #endif
00189
00190 QPoint p = eventPos;
00191 p += QPoint(2,
00192 #ifdef Q_WS_WIN
00193 24
00194 #else
00195 16
00196 #endif
00197 );
00198 QSize s = sizeHint();
00199 if (p.x() + s.width() > screen.x() + screen.width())
00200 p.rx() -= 4 + s.width();
00201 if (p.y() + s.height() > screen.y() + screen.height())
00202 p.ry() -= 24 + s.height();
00203 if (p.y() < screen.y())
00204 p.setY(screen.y());
00205 if (p.x() + s.width() > screen.x() + screen.width())
00206 p.setX(screen.x() + screen.width() - s.width());
00207 if (p.x() < screen.x())
00208 p.setX(screen.x());
00209 if (p.y() + s.height() > screen.y() + screen.height())
00210 p.setY(screen.y() + screen.height() - s.height());
00211 return p;
00212 }
00213
00241 QxtToolTip::QxtToolTip()
00242 {
00243 }
00244
00250 void QxtToolTip::show(const QPoint& pos, QWidget* tooltip, QWidget* parent, const QRect& rect)
00251 {
00252 QxtToolTipPrivate::instance()->show(pos, tooltip, parent, rect);
00253 }
00254
00260 void QxtToolTip::hide()
00261 {
00262 QxtToolTipPrivate::instance()->hide();
00263 }
00264
00270 QWidget* QxtToolTip::toolTip(QWidget* parent)
00271 {
00272 Q_ASSERT(parent);
00273 QWidget* tooltip = 0;
00274 if (!QxtToolTipPrivate::instance()->tooltips.contains(parent))
00275 qWarning("QxtToolTip::toolTip: Unknown parent");
00276 else
00277 tooltip = QxtToolTipPrivate::instance()->tooltips.value(parent).first;
00278 return tooltip;
00279 }
00280
00287 void QxtToolTip::setToolTip(QWidget* parent, QWidget* tooltip, const QRect& rect)
00288 {
00289 Q_ASSERT(parent);
00290 if (tooltip)
00291 {
00292
00293 tooltip->hide();
00294 QxtToolTipPrivate::instance()->tooltips[parent] = qMakePair(QPointer<QWidget>(tooltip), rect);
00295 }
00296 else
00297 {
00298
00299 if (!QxtToolTipPrivate::instance()->tooltips.contains(parent))
00300 qWarning("QxtToolTip::setToolTip: Unknown parent");
00301 else
00302 QxtToolTipPrivate::instance()->tooltips.remove(parent);
00303 }
00304 }
00305
00311 QRect QxtToolTip::toolTipRect(QWidget* parent)
00312 {
00313 Q_ASSERT(parent);
00314 QRect rect;
00315 if (!QxtToolTipPrivate::instance()->tooltips.contains(parent))
00316 qWarning("QxtToolTip::toolTipRect: Unknown parent");
00317 else
00318 rect = QxtToolTipPrivate::instance()->tooltips.value(parent).second;
00319 return rect;
00320 }
00321
00327 void QxtToolTip::setToolTipRect(QWidget* parent, const QRect& rect)
00328 {
00329 Q_ASSERT(parent);
00330 if (!QxtToolTipPrivate::instance()->tooltips.contains(parent))
00331 qWarning("QxtToolTip::setToolTipRect: Unknown parent");
00332 else
00333 QxtToolTipPrivate::instance()->tooltips[parent].second = rect;
00334 }
00335
00341 int QxtToolTip::margin()
00342 {
00343 return QxtToolTipPrivate::instance()->layout()->margin();
00344 }
00345
00353 void QxtToolTip::setMargin(int margin)
00354 {
00355 QxtToolTipPrivate::instance()->layout()->setMargin(margin);
00356 }
00357
00363 qreal QxtToolTip::opacity()
00364 {
00365 return QxtToolTipPrivate::instance()->windowOpacity();
00366 }
00367
00375 void QxtToolTip::setOpacity(qreal level)
00376 {
00377 QxtToolTipPrivate::instance()->setWindowOpacity(level);
00378 }