src/gui/kernel/qtooltip.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 ** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.
00004 **
00005 ** This file is part of the QtGui module of the Qt Toolkit.
00006 **
00007 ** This file may be used under the terms of the GNU General Public
00008 ** License version 2.0 as published by the Free Software Foundation
00009 ** and appearing in the file LICENSE.GPL included in the packaging of
00010 ** this file.  Please review the following information to ensure GNU
00011 ** General Public Licensing requirements will be met:
00012 ** http://www.trolltech.com/products/qt/opensource.html
00013 **
00014 ** If you are unsure which license is appropriate for your use, please
00015 ** review the following information:
00016 ** http://www.trolltech.com/products/qt/licensing.html or contact the
00017 ** sales department at sales@trolltech.com.
00018 **
00019 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00020 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00021 **
00022 ****************************************************************************/
00023 
00024 #include <qapplication.h>
00025 #include <qdesktopwidget.h>
00026 #include <qevent.h>
00027 #include <qhash.h>
00028 #include <qlabel.h>
00029 #include <qpointer.h>
00030 #include <qstyle.h>
00031 #include <qstyleoption.h>
00032 #include <qstylepainter.h>
00033 #include <qtimer.h>
00034 #include <qtooltip.h>
00035 #include <private/qeffects_p.h>
00036 #include <qtextdocument.h>
00037 
00038 #ifndef QT_NO_TOOLTIP
00039 
00080 class QTipLabel : public QLabel
00081 {
00082     Q_OBJECT
00083 public:
00084     QTipLabel(const QString& text, QWidget* parent);
00085     ~QTipLabel();
00086     static QTipLabel *instance;
00087 
00088     bool eventFilter(QObject *, QEvent *);
00089 
00090     QBasicTimer hideTimer, deleteTimer;
00091 
00092     void hideTip();
00093     void setTipRect(QWidget *w, const QRect &r);
00094 protected:
00095     void enterEvent(QEvent*){hideTip();}
00096     void timerEvent(QTimerEvent *e);
00097     void paintEvent(QPaintEvent *e);
00098 
00099 private:
00100     QWidget *widget;
00101     QRect rect;
00102 };
00103 
00104 QTipLabel *QTipLabel::instance = 0;
00105 
00106 QTipLabel::QTipLabel(const QString& text, QWidget* parent)
00107     : QLabel(parent, Qt::ToolTip), widget(0)
00108 {
00109     delete instance;
00110     instance = this;
00111     ensurePolished();
00112     setMargin(1 + style()->pixelMetric(QStyle::PM_ToolTipLabelFrameWidth, 0, this));
00113     setFrameStyle(QFrame::NoFrame);
00114     setAlignment(Qt::AlignLeft);
00115     setIndent(1);
00116     setWordWrap(Qt::mightBeRichText(text));
00117     setText(text);
00118 
00119     QFontMetrics fm(font());
00120     QSize extra(1, 0);
00121     // Make it look good with the default ToolTip font on Mac, which has a small descent.
00122     if (fm.descent() == 2 && fm.ascent() >= 11)
00123         ++extra.rheight();
00124 
00125     resize(sizeHint() + extra);
00126     qApp->installEventFilter(this);
00127 
00128     int time = 10000 + 40 * qMax(0, text.length()-100);
00129     hideTimer.start(time, this);
00130     setWindowOpacity(style()->styleHint(QStyle::SH_ToolTipLabel_Opacity, 0, this) / 255.0);
00131     setPalette(QToolTip::palette());
00132 }
00133 
00134 void QTipLabel::paintEvent(QPaintEvent *ev)
00135 {
00136     QStylePainter p(this);
00137     QStyleOptionFrame opt;
00138     opt.init(this);
00139     p.drawPrimitive(QStyle::PE_PanelTipLabel, opt);
00140     p.end();
00141 
00142     QLabel::paintEvent(ev);
00143 }
00144 
00145 QTipLabel::~QTipLabel()
00146 {
00147     instance = 0;
00148 }
00149 
00150 void QTipLabel::hideTip()
00151 {
00152     hide();
00153     // timer based deletion to prevent animation
00154     deleteTimer.start(250, this);
00155 }
00156 
00157 void QTipLabel::setTipRect(QWidget *w, const QRect &r)
00158 {
00159     if (w) {
00160         widget = w;
00161         rect = r;
00162     }
00163 }
00164 
00165 void QTipLabel::timerEvent(QTimerEvent *e)
00166 {
00167     if (e->timerId() == hideTimer.timerId())
00168         hideTip();
00169     else if (e->timerId() == deleteTimer.timerId())
00170         delete this;
00171 }
00172 
00173 bool QTipLabel::eventFilter(QObject *o, QEvent *e)
00174 {
00175     switch (e->type()) {
00176     case QEvent::KeyPress:
00177     case QEvent::KeyRelease: {
00178         int key = static_cast<QKeyEvent *>(e)->key();
00179         Qt::KeyboardModifiers mody = static_cast<QKeyEvent *>(e)->modifiers();
00180 
00181         if ((mody & Qt::KeyboardModifierMask)
00182             || (key == Qt::Key_Shift || key == Qt::Key_Control
00183                 || key == Qt::Key_Alt || key == Qt::Key_Meta))
00184             break;
00185     }
00186     case QEvent::Leave:
00187     case QEvent::WindowActivate:
00188     case QEvent::WindowDeactivate:
00189     case QEvent::MouseButtonPress:
00190     case QEvent::MouseButtonRelease:
00191     case QEvent::MouseButtonDblClick:
00192     case QEvent::FocusIn:
00193     case QEvent::FocusOut:
00194     case QEvent::Wheel:
00195         hideTip();
00196         break;
00197 
00198     case QEvent::MouseMove:
00199         if (o == widget && !rect.isNull() && !rect.contains(static_cast<QMouseEvent*>(e)->pos()))
00200             hideTip();
00201     default:
00202         break;
00203     }
00204     return false;
00205 }
00206 
00223 void QToolTip::showText(const QPoint &pos, const QString &text, QWidget *w, const QRect &rect)
00224 {
00225     if (QTipLabel::instance && QTipLabel::instance->text() == text)
00226         return; /* this is NOT a bug, if the text doesn't change, you
00227                  don't want the tool tips to move. If you divide your
00228                  widget in different parts that show the same tool
00229                  tip, you must handle that yourself. Simple hide the
00230                  tip (by showing an empty string) and show the new
00231                  one. */
00232 
00233     if (text.isEmpty()) {
00234         if (QTipLabel::instance)
00235             QTipLabel::instance->hideTip();
00236         return;
00237     }
00238 
00239 #ifndef QT_NO_EFFECTS
00240     bool preventAnimation = (QTipLabel::instance != 0);
00241 #endif
00242     int scr;
00243     if (QApplication::desktop()->isVirtualDesktop())
00244         scr = QApplication::desktop()->screenNumber(pos);
00245     else
00246         scr = QApplication::desktop()->screenNumber(w);
00247 
00248 #ifdef Q_WS_MAC
00249     QRect screen = QApplication::desktop()->availableGeometry(scr);
00250 #else
00251     QRect screen = QApplication::desktop()->screenGeometry(scr);
00252 #endif
00253 
00254     QTipLabel *label = new QTipLabel(text, QApplication::desktop()->screen(scr));
00255     if (!rect.isNull() && !w) {
00256         qWarning("QToolTip::showText: Cannot pass null widget if rect is set");
00257     } else {
00258         label->setTipRect(w, rect);
00259     }
00260 
00261     label->setObjectName(QLatin1String("qtooltip_label"));
00262 
00263     QPoint p = pos;
00264     p += QPoint(2,
00265 #ifdef Q_WS_WIN
00266                 24
00267 #else
00268                 16
00269 #endif
00270         );
00271     if (p.x() + label->width() > screen.x() + screen.width())
00272         p.rx() -= 4 + label->width();
00273     if (p.y() + label->height() > screen.y() + screen.height())
00274         p.ry() -= 24 + label->height();
00275     if (p.y() < screen.y())
00276         p.setY(screen.y());
00277     if (p.x() + label->width() > screen.x() + screen.width())
00278         p.setX(screen.x() + screen.width() - label->width());
00279     if (p.x() < screen.x())
00280         p.setX(screen.x());
00281     if (p.y() + label->height() > screen.y() + screen.height())
00282         p.setY(screen.y() + screen.height() - label->height());
00283     label->move(p);
00284 
00285 #ifndef QT_NO_EFFECTS
00286     if ( QApplication::isEffectEnabled(Qt::UI_AnimateTooltip) == false || preventAnimation)
00287         label->show();
00288     else if (QApplication::isEffectEnabled(Qt::UI_FadeTooltip)) {
00289         qFadeEffect(label);
00290     }
00291     else
00292         qScrollEffect(label);
00293 #else
00294     label->show();
00295 #endif
00296 
00297 }
00298 
00305 void QToolTip::showText(const QPoint &pos, const QString &text, QWidget *w)
00306 {
00307     QToolTip::showText(pos, text, w, QRect());
00308 }
00309 
00310 
00322 Q_GLOBAL_STATIC_WITH_ARGS(QPalette, tooltip_palette, (Qt::black, QColor(255,255,220),
00323                                                       QColor(96,96,96), Qt::black, Qt::black,
00324                                                       Qt::black, QColor(255,255,220)))
00325 
00326 
00329 QPalette QToolTip::palette()
00330 {
00331     return *tooltip_palette();
00332 }
00333 
00339 QFont QToolTip::font()
00340 {
00341     return QApplication::font("QTipLabel");
00342 }
00343 
00349 void QToolTip::setPalette(const QPalette &palette)
00350 {
00351     *tooltip_palette() = palette;
00352 }
00353 
00359 void QToolTip::setFont(const QFont &font)
00360 {
00361     QApplication::setFont(font, "QTipLabel");
00362 }
00363 
00364 
00398 #include "qtooltip.moc"
00399 #endif // QT_NO_TOOLTIP

Generated on Thu Mar 15 11:55:15 2007 for Qt 4.2 User's Guide by  doxygen 1.5.1