?? qtooltip.cpp
字號:
/****************************************************************************** $Id: qt/src/widgets/qtooltip.cpp 2.3.12 edited 2005-10-27 $**** Tool Tips (or Balloon Help) for any widget or rectangle**** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.**** This file is part of the widgets module of the Qt GUI Toolkit.**** This file may be distributed under the terms of the Q Public License** as defined by Trolltech AS of Norway and appearing in the file** LICENSE.QPL included in the packaging of this file.**** This file may be distributed and/or modified under the terms of the** GNU General Public License version 2 as published by the Free Software** Foundation and appearing in the file LICENSE.GPL included in the** packaging of this file.**** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition** licenses may use this file in accordance with the Qt Commercial License** Agreement provided with the Software.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.**** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for** information about Qt Commercial License Agreements.** See http://www.trolltech.com/qpl/ for QPL licensing information.** See http://www.trolltech.com/gpl/ for GPL licensing information.**** Contact info@trolltech.com if any conditions of this licensing are** not clear to you.************************************************************************/#include "qtooltip.h"#ifndef QT_NO_TOOLTIP#include "qlabel.h"#include "qptrdict.h"#include "qapplication.h"#include "qguardedptr.h"#include "qtimer.h"#include "qeffects_p.h"static bool globally_enabled = TRUE;// Magic value meaning an entire widget - if someone tries to insert a// tool tip on this part of a widget it will be interpreted as the// entire widget.static inline QRect entireWidget(){ return QRect( -QWIDGETSIZE_MAX, -QWIDGETSIZE_MAX, 2*QWIDGETSIZE_MAX, 2*QWIDGETSIZE_MAX );}// Internal class - don't touchclass QTipLabel : public QLabel{ Q_OBJECTpublic: QTipLabel(const QString& text) : QLabel( 0, "toolTipTip", WStyle_StaysOnTop + WStyle_Customize + WStyle_NoBorder + WStyle_Tool ) { setMargin(1); setIndent(0); setAutoMask( FALSE ); setFrameStyle( QFrame::Plain | QFrame::Box ); setLineWidth( 1 ); setAlignment( AlignLeft | AlignTop ); polish(); setText(text); adjustSize(); }};// Internal class - don't touchclass QTipManager : public QObject{ Q_OBJECTpublic: QTipManager(); ~QTipManager(); struct Tip { QRect rect; QString text; QString groupText; QToolTipGroup *group; QToolTip *tip; bool autoDelete; QRect geometry; Tip *next; }; bool eventFilter( QObject * o, QEvent * e ); void add( const QRect &gm, QWidget *, const QRect &, const QString& , QToolTipGroup *, const QString& , QToolTip *, bool ); void add( QWidget *, const QRect &, const QString& , QToolTipGroup *, const QString& , QToolTip *, bool ); void remove( QWidget *, const QRect & ); void remove( QWidget * ); void removeFromGroup( QToolTipGroup * ); void hideTipAndSleep();public slots: void hideTip();private slots: void labelDestroyed(); void clientWidgetDestroyed(); void showTip(); void allowAnimation();private: QTimer wakeUp; QTimer fallAsleep; QPtrDict<Tip> *tips; QLabel *label; QPoint pos; QGuardedPtr<QWidget> widget; Tip *currentTip; Tip *previousTip; bool preventAnimation; bool isApplicationFilter; QTimer *removeTimer;};// We have a global, internal QTipManager objectstatic QTipManager *tipManager = 0;static bool initializedTM = FALSE;static void cleanupTipManager(){ delete tipManager; tipManager = 0; initializedTM = FALSE;}static void initTipManager(){ if ( !tipManager ) { tipManager = new QTipManager; CHECK_PTR( tipManager ); } if ( !initializedTM ) { initializedTM = TRUE; qAddPostRoutine( cleanupTipManager ); }}QTipManager::QTipManager() : QObject( 0, "toolTipManager" ){ tips = new QPtrDict<QTipManager::Tip>( 313 ); currentTip = 0; previousTip = 0; label = 0; preventAnimation = FALSE; isApplicationFilter = FALSE; connect( &wakeUp, SIGNAL(timeout()), SLOT(showTip()) ); connect( &fallAsleep, SIGNAL(timeout()), SLOT(hideTip()) ); removeTimer = new QTimer( this );}QTipManager::~QTipManager(){ if ( isApplicationFilter && !qApp->closingDown() ) { qApp->setGlobalMouseTracking( FALSE ); qApp->removeEventFilter( tipManager ); } if ( tips ) { QPtrDictIterator<QTipManager::Tip> i( *tips ); QTipManager::Tip *t, *n; void *k; while( (t = i.current()) != 0 ) { k = i.currentKey(); ++i; tips->take( k ); while ( t ) { n = t->next; delete t; t = n; } } delete tips; } delete label;}void QTipManager::add( const QRect &gm, QWidget *w, const QRect &r, const QString &s, QToolTipGroup *g, const QString& gs, QToolTip *tt, bool a ){ QTipManager::Tip *h = (*tips)[ w ]; QTipManager::Tip *t = new QTipManager::Tip; t->next = h; t->tip = tt; t->autoDelete = a; t->text = s; t->rect = r; t->groupText = gs; t->group = g; t->geometry = gm; if ( h ) tips->take( w ); else connect( w, SIGNAL(destroyed()), this, SLOT(clientWidgetDestroyed()) ); tips->insert( w, t ); if ( a && t->rect.contains( pos ) && (!g || g->enabled()) ) { removeTimer->stop(); showTip(); } if ( !isApplicationFilter && qApp ) { isApplicationFilter = TRUE; qApp->installEventFilter( tipManager ); qApp->setGlobalMouseTracking( TRUE ); } if ( t->group ) { disconnect( removeTimer, SIGNAL( timeout() ), t->group, SIGNAL( removeTip() ) ); connect( removeTimer, SIGNAL( timeout() ), t->group, SIGNAL( removeTip() ) ); }}void QTipManager::add( QWidget *w, const QRect &r, const QString &s, QToolTipGroup *g, const QString& gs, QToolTip *tt, bool a ){ add( QRect( -1, -1, -1, -1 ), w, r, s, g, gs, tt, a );}void QTipManager::remove( QWidget *w, const QRect & r ){ QTipManager::Tip *t = (*tips)[ w ]; if ( t == 0 ) return; if ( t == currentTip ) hideTip(); if ( t == previousTip ) previousTip = 0; if ( t->rect == r ) { tips->take( w ); if ( t->next ) tips->insert( w, t->next ); delete t; } else { while( t->next && t->next->rect != r ) t = t->next; if ( t->next ) { QTipManager::Tip *d = t->next; t->next = t->next->next; delete d; } } if ( (*tips)[ w ] == 0 ) disconnect( w, SIGNAL(destroyed()), this, SLOT(clientWidgetDestroyed()) );#if 0 // not needed, leads sometimes to crashes if ( tips->isEmpty() ) { // the manager will be recreated if needed delete tipManager; tipManager = 0; }#endif}/*! The label was destroyed in the program cleanup phase.*/void QTipManager::labelDestroyed(){ label = 0;}/*! Remove sender() from the tool tip data structures.*/void QTipManager::clientWidgetDestroyed(){ const QObject *s = sender(); if ( s ) remove( (QWidget*) s );}void QTipManager::remove( QWidget *w ){ QTipManager::Tip *t = (*tips)[ w ]; if ( t == 0 ) return; tips->take( w ); QTipManager::Tip * d; while ( t ) { if ( t == currentTip ) hideTip(); d = t->next; delete t; t = d; } disconnect( w, SIGNAL(destroyed()), this, SLOT(clientWidgetDestroyed()) );#if 0 if ( tips->isEmpty() ) { delete tipManager; tipManager = 0; }#endif}void QTipManager::removeFromGroup( QToolTipGroup *g ){ QPtrDictIterator<QTipManager::Tip> i( *tips ); QTipManager::Tip *t; while( (t = i.current()) != 0 ) { ++i; while ( t ) { if ( t->group == g ) { if ( t->group ) disconnect( removeTimer, SIGNAL( timeout() ), t->group, SIGNAL( removeTip() ) ); t->group = 0; } t = t->next; } }}bool QTipManager::eventFilter( QObject *obj, QEvent *e ){ // avoid dumping core in case of application madness, and return // quickly for some common but irrelevant events if ( !qApp || !qApp->activeWindow() || !obj || !obj->isWidgetType() || // isWidgetType() catches most stuff !e || e->type() == QEvent::Paint || e->type() == QEvent::Timer || e->type() == QEvent::SockAct || !tips ) return FALSE; QWidget *w = (QWidget *)obj; if ( e->type() == QEvent::FocusOut || e->type() == QEvent::FocusIn ) { // user moved focus somewhere - hide the tip and sleep hideTipAndSleep(); return FALSE; } QTipManager::Tip *t = 0; while( w && !t ) { t = (*tips)[ w ]; if ( !t ) w = w->isTopLevel() ? 0 : w->parentWidget(); } if ( !t ) { if ( ( e->type() >= QEvent::MouseButtonPress && e->type() <= QEvent::FocusOut) || e->type() == QEvent::Leave ) hideTip(); return FALSE; } // with that out of the way, let's get down to action switch( e->type() ) { case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: case QEvent::MouseButtonDblClick: case QEvent::KeyPress: case QEvent::KeyRelease: // input - turn off tool tip mode hideTipAndSleep(); break; case QEvent::MouseMove: { // a whole scope just for one variable QMouseEvent * m = (QMouseEvent *)e; QPoint mousePos = w->mapFromGlobal( m->globalPos() ); if ( currentTip && !currentTip->rect.contains( mousePos ) ) { hideTip(); if ( m->state() == 0 ) return FALSE; } wakeUp.stop(); if ( m->state() == 0 && mousePos.x() >= 0 && mousePos.x() < w->width() && mousePos.y() >= 0 && mousePos.y() < w->height() ) { if ( label && label->isVisible() ) { return FALSE; } else { if ( fallAsleep.isActive() ) { wakeUp.start( 1, TRUE ); } else { previousTip = 0; wakeUp.start( 700, TRUE ); } if ( t->group && t->group->ena && !t->group->del && !t->groupText.isEmpty() ) { removeTimer->stop(); emit t->group->showTip( t->groupText ); } } widget = w; pos = mousePos; return FALSE; } else { hideTip(); } } break; case QEvent::Leave: case QEvent::Hide: case QEvent::Destroy: if ( w == widget ) hideTip(); break; default: break; } return FALSE;}void QTipManager::showTip(){ if ( !widget || !globally_enabled ) return; QTipManager::Tip *t = (*tips)[ widget ]; while ( t && !t->rect.contains( pos ) ) t = t->next; if ( t == 0 ) return; if ( t == currentTip ) return; // nothing to do if ( t->tip ) { t->tip->maybeTip( pos ); return; } if ( t->group && !t->group->ena ) return; if ( label ) { label->setText( t->text ); label->adjustSize(); if ( t->geometry != QRect( -1, -1, -1, -1 ) ) label->resize( t->geometry.size() ); } else { label = new QTipLabel(t->text); if ( t->geometry != QRect( -1, -1, -1, -1 ) ) label->resize( t->geometry.size() ); CHECK_PTR( label ); connect( label, SIGNAL(destroyed()), SLOT(labelDestroyed()) ); } QPoint p; if ( t->geometry == QRect( -1, -1, -1, -1 ) ) { p = widget->mapToGlobal( pos ) + QPoint( 2, 16 ); } else { p = widget->mapToGlobal( t->geometry.topLeft() ); label->setAlignment( WordBreak | AlignCenter ); int h = label->heightForWidth( t->geometry.width() - 4 ); label->resize( label->width(), h ); } if ( p.x() + label->width() > QApplication::desktop()->width() ) p.setX( QApplication::desktop()->width() - label->width() ); if ( p.y() + label->height() > QApplication::desktop()->height() ) p.setY( p.y() - 20 - label->height() ); if ( label->text().length() ) { label->move( p );#ifndef QT_NO_EFFECTS if ( QApplication::isEffectEnabled( UI_AnimateTooltip ) == FALSE || previousTip || preventAnimation ) label->show(); else if ( QApplication::isEffectEnabled( UI_FadeTooltip ) ) qFadeEffect( label ); else qScrollEffect( label );#else label->show();#endif label->raise(); fallAsleep.start( 10000, TRUE ); } if ( t->group && t->group->del && !t->groupText.isEmpty() ) { removeTimer->stop(); emit t->group->showTip( t->groupText ); } currentTip = t; previousTip = 0;}void QTipManager::hideTip(){ QTimer::singleShot( 250, this, SLOT(allowAnimation()) ); preventAnimation = TRUE; if ( label && label->isVisible() ) { label->hide(); fallAsleep.start( 2000, TRUE ); wakeUp.stop(); if ( currentTip && currentTip->group ) removeTimer->start( 100, TRUE ); } else if ( wakeUp.isActive() ) { wakeUp.stop(); if ( currentTip && currentTip->group && !currentTip->group->del && !currentTip->groupText.isEmpty() ) removeTimer->start( 100, TRUE ); } previousTip = currentTip;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -