source: trunk/src/widgets/qtooltip.cpp@ 108

Last change on this file since 108 was 8, checked in by dmik, 20 years ago

Transferred Qt for OS/2 version 3.3.1-rc5 sources from the CVS

  • Property svn:keywords set to Id
File size: 33.1 KB
Line 
1/****************************************************************************
2** $Id: qtooltip.cpp 8 2005-11-16 19:36:46Z dmik $
3**
4** Tool Tips (or Balloon Help) for any widget or rectangle
5**
6** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
7**
8** This file is part of the widgets module of the Qt GUI Toolkit.
9**
10** This file may be distributed under the terms of the Q Public License
11** as defined by Trolltech AS of Norway and appearing in the file
12** LICENSE.QPL included in the packaging of this file.
13**
14** This file may be distributed and/or modified under the terms of the
15** GNU General Public License version 2 as published by the Free Software
16** Foundation and appearing in the file LICENSE.GPL included in the
17** packaging of this file.
18**
19** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
20** licenses may use this file in accordance with the Qt Commercial License
21** Agreement provided with the Software.
22**
23** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
24** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
25**
26** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
27** information about Qt Commercial License Agreements.
28** See http://www.trolltech.com/qpl/ for QPL licensing information.
29** See http://www.trolltech.com/gpl/ for GPL licensing information.
30**
31** Contact info@trolltech.com if any conditions of this licensing are
32** not clear to you.
33**
34**********************************************************************/
35
36#include "qtooltip.h"
37#ifndef QT_NO_TOOLTIP
38#include "qlabel.h"
39#include "qptrdict.h"
40#include "qapplication.h"
41#include "qguardedptr.h"
42#include "qtimer.h"
43#include "qeffects_p.h"
44
45static bool globally_enabled = TRUE;
46
47// Magic value meaning an entire widget - if someone tries to insert a
48// tool tip on this part of a widget it will be interpreted as the
49// entire widget.
50
51static inline QRect entireWidget()
52{
53 return QRect( -QWIDGETSIZE_MAX, -QWIDGETSIZE_MAX,
54 2*QWIDGETSIZE_MAX, 2*QWIDGETSIZE_MAX );
55}
56
57// Internal class - don't touch
58
59class QTipLabel : public QLabel
60{
61 Q_OBJECT
62public:
63 QTipLabel( QWidget* parent, const QString& text) : QLabel( parent, "toolTipTip",
64 WStyle_StaysOnTop | WStyle_Customize | WStyle_NoBorder | WStyle_Tool | WX11BypassWM )
65 {
66 setMargin(1);
67 setAutoMask( FALSE );
68 setFrameStyle( QFrame::Plain | QFrame::Box );
69 setLineWidth( 1 );
70 setAlignment( AlignAuto | AlignTop );
71 setIndent(0);
72 polish();
73 setText(text);
74 adjustSize();
75 }
76 void setWidth( int w ) { resize( sizeForWidth( w ) ); }
77};
78
79// Internal class - don't touch
80
81class QTipManager : public QObject
82{
83 Q_OBJECT
84public:
85 QTipManager();
86 ~QTipManager();
87
88 struct Tip
89 {
90 QRect rect;
91 QString text;
92 QString groupText;
93 QToolTipGroup *group;
94 QToolTip *tip;
95 bool autoDelete;
96 QRect geometry;
97 Tip *next;
98 };
99
100 bool eventFilter( QObject * o, QEvent * e );
101 void add( const QRect &gm, QWidget *, const QRect &, const QString& ,
102 QToolTipGroup *, const QString& , QToolTip *, bool );
103 void add( QWidget *, const QRect &, const QString& ,
104 QToolTipGroup *, const QString& , QToolTip *, bool );
105 void remove( QWidget *, const QRect &, bool delayhide = FALSE );
106 void remove( QWidget * );
107
108 void removeFromGroup( QToolTipGroup * );
109
110 void hideTipAndSleep();
111
112 QString find( QWidget *, const QPoint& );
113 void setWakeUpDelay(int);
114
115public slots:
116 void hideTip();
117
118private slots:
119 void labelDestroyed();
120 void clientWidgetDestroyed();
121 void showTip();
122 void allowAnimation();
123
124private:
125 QTimer wakeUp;
126 int wakeUpDelay;
127 QTimer fallAsleep;
128#ifdef Q_WS_PM
129 QTimer doAllowAnimation;
130#endif
131
132 QPtrDict<Tip> *tips;
133 QTipLabel *label;
134 QPoint pos;
135 QGuardedPtr<QWidget> widget;
136 Tip *currentTip;
137 Tip *previousTip;
138 bool preventAnimation;
139 bool isApplicationFilter;
140 QTimer *removeTimer;
141};
142
143
144// We have a global, internal QTipManager object
145
146static QTipManager *tipManager = 0;
147
148static void initTipManager()
149{
150 if ( !tipManager ) {
151 tipManager = new QTipManager;
152 Q_CHECK_PTR( tipManager );
153 }
154}
155
156
157QTipManager::QTipManager()
158 : QObject( qApp, "toolTipManager" )
159{
160 wakeUpDelay = 700;
161 tips = new QPtrDict<QTipManager::Tip>( 313 );
162 currentTip = 0;
163 previousTip = 0;
164 label = 0;
165 preventAnimation = FALSE;
166 isApplicationFilter = FALSE;
167 connect( &wakeUp, SIGNAL(timeout()), SLOT(showTip()) );
168 connect( &fallAsleep, SIGNAL(timeout()), SLOT(hideTip()) );
169#ifdef Q_WS_PM
170 connect( &doAllowAnimation, SIGNAL(timeout()), SLOT(allowAnimation()) );
171#endif
172 removeTimer = new QTimer( this );
173}
174
175
176QTipManager::~QTipManager()
177{
178 if ( isApplicationFilter && !qApp->closingDown() ) {
179 qApp->setGlobalMouseTracking( FALSE );
180 qApp->removeEventFilter( tipManager );
181 }
182
183 if ( tips ) {
184 QPtrDictIterator<QTipManager::Tip> i( *tips );
185 QTipManager::Tip *t, *n;
186 void *k;
187 while( (t = i.current()) != 0 ) {
188 k = i.currentKey();
189 ++i;
190 tips->take( k );
191 while ( t ) {
192 n = t->next;
193 delete t;
194 t = n;
195 }
196 }
197 delete tips;
198 }
199
200 delete label;
201
202 tipManager = 0;
203}
204
205void QTipManager::add( const QRect &gm, QWidget *w,
206 const QRect &r, const QString &s,
207 QToolTipGroup *g, const QString& gs,
208 QToolTip *tt, bool a )
209{
210 remove( w, r, TRUE );
211 QTipManager::Tip *h = (*tips)[ w ];
212 QTipManager::Tip *t = new QTipManager::Tip;
213 t->next = h;
214 t->tip = tt;
215 t->autoDelete = a;
216 t->text = s;
217 t->rect = r;
218 t->groupText = gs;
219 t->group = g;
220 t->geometry = gm;
221
222 if ( h ) {
223 tips->take( w );
224 if ( h != currentTip && h->autoDelete ) {
225 t->next = h->next;
226 delete h;
227 }
228 } else
229 connect( w, SIGNAL(destroyed()), this, SLOT(clientWidgetDestroyed()) );
230
231 tips->insert( w, t );
232
233 if ( a && t->rect.contains( pos ) && (!g || g->enabled()) ) {
234 removeTimer->stop();
235 showTip();
236 }
237
238 if ( !isApplicationFilter && qApp ) {
239 isApplicationFilter = TRUE;
240 qApp->installEventFilter( tipManager );
241 qApp->setGlobalMouseTracking( TRUE );
242 }
243
244 if ( t->group ) {
245 disconnect( removeTimer, SIGNAL( timeout() ),
246 t->group, SIGNAL( removeTip() ) );
247 connect( removeTimer, SIGNAL( timeout() ),
248 t->group, SIGNAL( removeTip() ) );
249 }
250}
251
252void QTipManager::add( QWidget *w, const QRect &r, const QString &s,
253 QToolTipGroup *g, const QString& gs,
254 QToolTip *tt, bool a )
255{
256 add( QRect( -1, -1, -1, -1 ), w, r, s, g, gs, tt, a );
257}
258
259
260void QTipManager::remove( QWidget *w, const QRect & r, bool delayhide )
261{
262 QTipManager::Tip *t = (*tips)[ w ];
263 if ( t == 0 )
264 return;
265
266 if ( t == currentTip )
267 if (!delayhide)
268 hideTip();
269 else
270 currentTip->autoDelete = true;
271
272 if ( t == previousTip )
273 previousTip = 0;
274
275 if ( ( currentTip != t || !delayhide ) && t->rect == r ) {
276 tips->take( w );
277 if ( t->next )
278 tips->insert( w, t->next );
279 delete t;
280 } else {
281 while( t->next && t->next->rect != r && ( currentTip != t->next || !delayhide ))
282 t = t->next;
283 if ( t->next ) {
284 QTipManager::Tip *d = t->next;
285 t->next = t->next->next;
286 delete d;
287 }
288 }
289
290 if ( (*tips)[ w ] == 0 )
291 disconnect( w, SIGNAL(destroyed()), this, SLOT(clientWidgetDestroyed()) );
292#if 0 // not needed, leads sometimes to crashes
293 if ( tips->isEmpty() ) {
294 // the manager will be recreated if needed
295 delete tipManager;
296 tipManager = 0;
297 }
298#endif
299}
300
301
302/*
303 The label was destroyed in the program cleanup phase.
304*/
305
306void QTipManager::labelDestroyed()
307{
308 label = 0;
309}
310
311
312/*
313 Remove sender() from the tool tip data structures.
314*/
315
316void QTipManager::clientWidgetDestroyed()
317{
318 const QObject *s = sender();
319 if ( s )
320 remove( (QWidget*) s );
321}
322
323
324void QTipManager::remove( QWidget *w )
325{
326 QTipManager::Tip *t = (*tips)[ w ];
327 if ( t == 0 )
328 return;
329
330 tips->take( w );
331 QTipManager::Tip * d;
332 while ( t ) {
333 if ( t == currentTip )
334 hideTip();
335 d = t->next;
336 delete t;
337 t = d;
338 }
339
340 disconnect( w, SIGNAL(destroyed()), this, SLOT(clientWidgetDestroyed()) );
341#if 0
342 if ( tips->isEmpty() ) {
343 delete tipManager;
344 tipManager = 0;
345 }
346#endif
347}
348
349
350void QTipManager::removeFromGroup( QToolTipGroup *g )
351{
352 QPtrDictIterator<QTipManager::Tip> i( *tips );
353 QTipManager::Tip *t;
354 while( (t = i.current()) != 0 ) {
355 ++i;
356 while ( t ) {
357 if ( t->group == g ) {
358 if ( t->group )
359 disconnect( removeTimer, SIGNAL( timeout() ),
360 t->group, SIGNAL( removeTip() ) );
361 t->group = 0;
362 }
363 t = t->next;
364 }
365 }
366}
367
368
369
370bool QTipManager::eventFilter( QObject *obj, QEvent *e )
371{
372 // avoid dumping core in case of application madness, and return
373 // quickly for some common but irrelevant events
374 if ( e->type() == QEvent::WindowDeactivate &&
375 qApp && !qApp->activeWindow() &&
376 label && label->isVisible() )
377 hideTipAndSleep();
378
379 if ( !qApp
380 || !obj || !obj->isWidgetType() // isWidgetType() catches most stuff
381 || e->type() == QEvent::Paint
382 || e->type() == QEvent::Timer
383 || e->type() == QEvent::SockAct
384 || !tips )
385 return FALSE;
386 QWidget *w = (QWidget *)obj;
387
388 if ( e->type() == QEvent::FocusOut || e->type() == QEvent::FocusIn ) {
389 // user moved focus somewhere - hide the tip and sleep
390 if ( ((QFocusEvent*)e)->reason() != QFocusEvent::Popup )
391 hideTipAndSleep();
392 return FALSE;
393 }
394
395 QTipManager::Tip *t = 0;
396 while( w && !t ) {
397 t = (*tips)[ w ];
398 if ( !t )
399 w = w->isTopLevel() ? 0 : w->parentWidget();
400 }
401 if ( !w )
402 return FALSE;
403
404 if ( !t && e->type() != QEvent::MouseMove) {
405 if ( ( e->type() >= QEvent::MouseButtonPress &&
406 e->type() <= QEvent::FocusOut) || e->type() == QEvent::Leave )
407 hideTip();
408 return FALSE;
409 }
410
411 // with that out of the way, let's get down to action
412
413 switch( e->type() ) {
414 case QEvent::MouseButtonPress:
415 case QEvent::MouseButtonRelease:
416 case QEvent::MouseButtonDblClick:
417 case QEvent::KeyPress:
418 case QEvent::KeyRelease:
419 // input - turn off tool tip mode
420 hideTipAndSleep();
421 break;
422 case QEvent::MouseMove:
423 {
424 QMouseEvent * m = (QMouseEvent *)e;
425 QPoint mousePos = w->mapFromGlobal( m->globalPos() );
426
427 if ( currentTip && !currentTip->rect.contains( mousePos ) ) {
428 hideTip();
429 if ( m->state() == 0 )
430 return FALSE;
431 }
432
433 wakeUp.stop();
434 if ( m->state() == 0 &&
435 mousePos.x() >= 0 && mousePos.x() < w->width() &&
436 mousePos.y() >= 0 && mousePos.y() < w->height() ) {
437 if ( label && label->isVisible() ) {
438 return FALSE;
439 } else {
440 if ( fallAsleep.isActive() ) {
441 wakeUp.start( 1, TRUE );
442 } else {
443 previousTip = 0;
444 wakeUp.start( wakeUpDelay, TRUE );
445 }
446 if ( t->group && t->group->ena &&
447 !t->group->del && !t->groupText.isEmpty() ) {
448 removeTimer->stop();
449 emit t->group->showTip( t->groupText );
450 currentTip = t;
451 }
452 }
453 widget = w;
454 pos = mousePos;
455 return FALSE;
456 } else {
457 hideTip();
458 }
459 }
460 break;
461 case QEvent::Leave:
462 case QEvent::Hide:
463 case QEvent::Destroy:
464 if ( w == widget )
465 hideTip();
466 break;
467 default:
468 break;
469 }
470 return FALSE;
471}
472
473
474
475void QTipManager::showTip()
476{
477 if ( !widget || !globally_enabled
478#ifndef Q_WS_X11
479 || !widget->isActiveWindow()
480#endif
481 )
482 return;
483
484 QTipManager::Tip *t = (*tips)[ widget ];
485 while ( t && !t->rect.contains( pos ) )
486 t = t->next;
487 if ( t == 0 )
488 return;
489
490 if ( t == currentTip && label && label->isVisible() )
491 return; // nothing to do
492
493 if ( t->tip ) {
494 t->tip->maybeTip( pos );
495 return;
496 }
497
498 if ( t->group && !t->group->ena )
499 return;
500
501 int scr;
502 if ( QApplication::desktop()->isVirtualDesktop() )
503 scr = QApplication::desktop()->screenNumber( widget->mapToGlobal( pos ) );
504 else
505 scr = QApplication::desktop()->screenNumber( widget );
506
507 if ( label
508#if defined(Q_WS_X11)
509 && label->x11Screen() == widget->x11Screen()
510#endif
511 ) {
512 // the next two lines are a workaround for QLabel being too intelligent.
513 // QLabel turns on the wordbreak flag once it gets a richtext. The two lines below
514 // ensure we get correct textflags when switching back and forth between a richtext and
515 // non richtext tooltip
516 label->setText( "" );
517 label->setAlignment( AlignAuto | AlignTop );
518 label->setText( t->text );
519 label->adjustSize();
520 if ( t->geometry != QRect( -1, -1, -1, -1 ) )
521 label->resize( t->geometry.size() );
522 } else {
523 delete label;
524 label = new QTipLabel( QApplication::desktop()->screen( scr ), t->text);
525 if ( t->geometry != QRect( -1, -1, -1, -1 ) )
526 label->resize( t->geometry.size() );
527 Q_CHECK_PTR( label );
528 connect( label, SIGNAL(destroyed()), SLOT(labelDestroyed()) );
529 }
530 // the above deletion and creation of a QTipLabel causes events to be sent. We had reports that the widget
531 // pointer was 0 after this. This is in principle possible if the wrong kind of events get sent through our event
532 // filter in this time. So better be safe and check widget once again here.
533 if (!widget)
534 return;
535
536#ifdef Q_WS_MAC
537 QRect screen = QApplication::desktop()->availableGeometry( scr );
538#else
539 QRect screen = QApplication::desktop()->screenGeometry( scr );
540#endif
541 QPoint p;
542 if ( t->geometry == QRect( -1, -1, -1, -1 ) ) {
543 p = widget->mapToGlobal( pos ) +
544#ifdef Q_WS_WIN
545 QPoint( 2, 24 );
546#else
547 QPoint( 2, 16 );
548#endif
549 if ( p.x() + label->width() > screen.x() + screen.width() )
550 p.rx() -= 4 + label->width();
551 if ( p.y() + label->height() > screen.y() + screen.height() )
552 p.ry() -= 24 + label->height();
553 } else {
554 p = widget->mapToGlobal( t->geometry.topLeft() );
555 label->setAlignment( WordBreak | AlignCenter );
556 label->setWidth( t->geometry.width() - 4 );
557 }
558 if ( p.y() < screen.y() )
559 p.setY( screen.y() );
560 if ( p.x() + label->width() > screen.x() + screen.width() )
561 p.setX( screen.x() + screen.width() - label->width() );
562 if ( p.x() < screen.x() )
563 p.setX( screen.x() );
564 if ( p.y() + label->height() > screen.y() + screen.height() )
565 p.setY( screen.y() + screen.height() - label->height() );
566 if ( label->text().length() ) {
567 label->move( p );
568
569#ifndef QT_NO_EFFECTS
570 if ( QApplication::isEffectEnabled( UI_AnimateTooltip ) == FALSE ||
571 previousTip || preventAnimation )
572 label->show();
573 else if ( QApplication::isEffectEnabled( UI_FadeTooltip ) )
574 qFadeEffect( label );
575 else
576 qScrollEffect( label );
577#else
578 label->show();
579#endif
580
581 label->raise();
582 fallAsleep.start( 10000, TRUE );
583 }
584
585 if ( t->group && t->group->del && !t->groupText.isEmpty() ) {
586 removeTimer->stop();
587 emit t->group->showTip( t->groupText );
588 }
589
590 currentTip = t;
591 previousTip = 0;
592}
593
594
595void QTipManager::hideTip()
596{
597#ifdef Q_WS_PM
598 // OS/2 PM has a very low limit on the number of simultaneous PM timers,
599 // so we reuse the same timer instead of creating a new one every time this
600 // function is invoked (it can happen more frequently than once per 250 ms).
601 doAllowAnimation.start( 250, TRUE );
602#else
603 QTimer::singleShot( 250, this, SLOT(allowAnimation()) );
604#endif
605 preventAnimation = TRUE;
606
607 if ( label && label->isVisible() ) {
608 label->hide();
609 fallAsleep.start( 2000, TRUE );
610 wakeUp.stop();
611 if ( currentTip && currentTip->group )
612 removeTimer->start( 100, TRUE );
613 } else if ( wakeUp.isActive() ) {
614 wakeUp.stop();
615 if ( currentTip && currentTip->group &&
616 !currentTip->group->del && !currentTip->groupText.isEmpty() )
617 removeTimer->start( 100, TRUE );
618 } else if ( currentTip && currentTip->group ) {
619 removeTimer->start( 100, TRUE );
620 }
621
622 previousTip = currentTip;
623 currentTip = 0;
624 if ( previousTip && previousTip->autoDelete )
625 remove( widget, previousTip->rect );
626 widget = 0;
627}
628
629void QTipManager::hideTipAndSleep()
630{
631 hideTip();
632 fallAsleep.stop();
633}
634
635
636void QTipManager::allowAnimation()
637{
638 preventAnimation = FALSE;
639}
640
641QString QTipManager::find( QWidget *w, const QPoint& pos )
642{
643 Tip *t = (*tips)[ w ];
644 while ( t && !t->rect.contains( pos ) )
645 t = t->next;
646
647 return t ? t->text : QString::null;
648}
649
650void QTipManager::setWakeUpDelay ( int i )
651{
652 wakeUpDelay = i;
653}
654
655/*!
656 \class QToolTip qtooltip.h
657 \brief The QToolTip class provides tool tips (balloon help) for
658 any widget or rectangular part of a widget.
659
660 \ingroup helpsystem
661 \mainclass
662
663 The tip is a short, single line of text reminding the user of the
664 widget's or rectangle's function. It is drawn immediately below
665 the region in a distinctive black-on-yellow combination.
666
667 The tip can be any Rich-Text formatted string.
668
669 QToolTipGroup provides a way for tool tips to display another text
670 elsewhere (most often in a \link QStatusBar status bar\endlink).
671
672 At any point in time, QToolTip is either dormant or active. In
673 dormant mode the tips are not shown and in active mode they are.
674 The mode is global, not particular to any one widget.
675
676 QToolTip switches from dormant to active mode when the user hovers
677 the mouse on a tip-equipped region for a second or so and remains
678 active until the user either clicks a mouse button, presses a key,
679 lets the mouse hover for five seconds or moves the mouse outside
680 \e all tip-equipped regions for at least a second.
681
682 The QToolTip class can be used in three different ways:
683 \list 1
684 \i Adding a tip to an entire widget.
685 \i Adding a tip to a fixed rectangle within a widget.
686 \i Adding a tip to a dynamic rectangle within a widget.
687 \endlist
688
689 To add a tip to a widget, call the \e static function
690 QToolTip::add() with the widget and tip as arguments:
691
692 \code
693 QToolTip::add( quitButton, "Leave the application" );
694 \endcode
695
696 This is the simplest and most common use of QToolTip. The tip
697 will be deleted automatically when \e quitButton is deleted, but
698 you can remove it yourself, too:
699
700 \code
701 QToolTip::remove( quitButton );
702 \endcode
703
704 You can also display another text (typically in a \link QStatusBar
705 status bar),\endlink courtesy of \l{QToolTipGroup}. This example
706 assumes that \e grp is a \c{QToolTipGroup *} and is already
707 connected to the appropriate status bar:
708
709 \code
710 QToolTip::add( quitButton, "Leave the application", grp,
711 "Leave the application, prompting to save if necessary" );
712 QToolTip::add( closeButton, "Close this window", grp,
713 "Close this window, prompting to save if necessary" );
714 \endcode
715
716 To add a tip to a fixed rectangle within a widget, call the static
717 function QToolTip::add() with the widget, rectangle and tip as
718 arguments. (See the \c tooltip/tooltip.cpp example.) Again, you
719 can supply a \c{QToolTipGroup *} and another text if you want.
720
721 Both of these are one-liners and cover the majority of cases. The
722 third and most general way to use QToolTip requires you to
723 reimplement a pure virtual function to decide whether to pop up a
724 tool tip. The \c tooltip/tooltip.cpp example demonstrates this
725 too. This mode can be used to implement tips for text that can
726 move as the user scrolls, for example.
727
728 To use QToolTip like this, you must subclass QToolTip and
729 reimplement maybeTip(). QToolTip calls maybeTip() when a tip
730 should pop up, and maybeTip() decides whether to show a tip.
731
732 Tool tips can be globally disabled using
733 QToolTip::setGloballyEnabled() or disabled in groups with
734 QToolTipGroup::setEnabled().
735
736 You can retrieve the text of a tooltip for a given position within
737 a widget using textFor().
738
739 The global tooltip font and palette can be set with the static
740 setFont() and setPalette() functions respectively.
741
742 \sa QStatusBar QWhatsThis QToolTipGroup
743 \link guibooks.html#fowler GUI Design Handbook: Tool Tip\endlink
744*/
745
746
747/*!
748 Returns the font common to all tool tips.
749
750 \sa setFont()
751*/
752
753QFont QToolTip::font()
754{
755 QTipLabel l(0,"");
756 return QApplication::font( &l );
757}
758
759
760/*!
761 Sets the font for all tool tips to \a font.
762
763 \sa font()
764*/
765
766void QToolTip::setFont( const QFont &font )
767{
768 QApplication::setFont( font, TRUE, "QTipLabel" );
769}
770
771
772/*!
773 Returns the palette common to all tool tips.
774
775 \sa setPalette()
776*/
777
778QPalette QToolTip::palette()
779{
780 QTipLabel l(0,"");
781 return QApplication::palette( &l );
782}
783
784
785/*!
786 Sets the palette for all tool tips to \a palette.
787
788 \sa palette()
789*/
790
791void QToolTip::setPalette( const QPalette &palette )
792{
793 QApplication::setPalette( palette, TRUE, "QTipLabel" );
794}
795
796/*!
797 Constructs a tool tip object. This is only necessary if you need
798 tool tips on regions that can move within the widget (most often
799 because the widget's contents can scroll).
800
801 \a widget is the widget you want to add dynamic tool tips to and
802 \a group (optional) is the tool tip group they should belong to.
803
804 \warning QToolTip is not a subclass of QObject, so the instance of
805 QToolTip is not deleted when \a widget is deleted.
806
807 \warning If you delete the tool tip before you have deleted
808 \a widget then you need to make sure you call remove() yourself from
809 \a widget in your reimplemented QToolTip destructor.
810
811 \code
812 MyToolTip::~MyToolTip()
813 {
814 remove( widget );
815 }
816 \endcode
817
818 \sa maybeTip().
819*/
820
821QToolTip::QToolTip( QWidget * widget, QToolTipGroup * group )
822{
823 p = widget;
824 g = group;
825 initTipManager();
826 tipManager->add( p, entireWidget(),
827 QString::null, g, QString::null, this, FALSE );
828}
829
830
831/*!
832 Adds a tool tip to \a widget. \a text is the text to be shown in
833 the tool tip.
834
835 This is the most common entry point to the QToolTip class; it is
836 suitable for adding tool tips to buttons, checkboxes, comboboxes
837 and so on.
838*/
839
840void QToolTip::add( QWidget *widget, const QString &text )
841{
842 initTipManager();
843 tipManager->add( widget, entireWidget(),
844 text, 0, QString::null, 0, FALSE );
845}
846
847
848/*!
849 \overload
850
851 Adds a tool tip to \a widget and to tool tip group \a group.
852
853 \a text is the text shown in the tool tip and \a longText is the
854 text emitted from \a group.
855
856 Normally, \a longText is shown in a \link QStatusBar status
857 bar\endlink or similar.
858*/
859
860void QToolTip::add( QWidget *widget, const QString &text,
861 QToolTipGroup *group, const QString& longText )
862{
863 initTipManager();
864 tipManager->add( widget, entireWidget(), text, group, longText, 0, FALSE );
865}
866
867
868/*!
869 Removes the tool tip from \a widget.
870
871 If there is more than one tool tip on \a widget, only the one
872 covering the entire widget is removed.
873*/
874
875void QToolTip::remove( QWidget * widget )
876{
877 if ( tipManager )
878 tipManager->remove( widget, entireWidget() );
879}
880
881/*!
882 \overload
883
884 Adds a tool tip to a fixed rectangle, \a rect, within \a widget.
885 \a text is the text shown in the tool tip.
886*/
887
888void QToolTip::add( QWidget * widget, const QRect & rect, const QString &text )
889{
890 initTipManager();
891 tipManager->add( widget, rect, text, 0, QString::null, 0, FALSE );
892}
893
894
895/*!
896 \overload
897
898 Adds a tool tip to an entire \a widget and to tool tip group \a
899 group. The tooltip will disappear when the mouse leaves the \a
900 rect.
901
902 \a text is the text shown in the tool tip and \a groupText is the
903 text emitted from \a group.
904
905 Normally, \a groupText is shown in a \link QStatusBar status
906 bar\endlink or similar.
907*/
908
909void QToolTip::add( QWidget *widget, const QRect &rect,
910 const QString& text,
911 QToolTipGroup *group, const QString& groupText )
912{
913 initTipManager();
914 tipManager->add( widget, rect, text, group, groupText, 0, FALSE );
915}
916
917
918/*!
919 \overload
920
921 Removes any tool tip for \a rect from \a widget.
922
923 If there is more than one tool tip on \a widget, only the one
924 covering rectangle \a rect is removed.
925*/
926
927void QToolTip::remove( QWidget * widget, const QRect & rect )
928{
929 if ( tipManager )
930 tipManager->remove( widget, rect );
931}
932
933/*!
934 Returns the tool tip text for \a widget at position \a pos, or
935 QString::null if there is no tool tip for the given widget and
936 position.
937*/
938
939QString QToolTip::textFor( QWidget *widget, const QPoint& pos )
940{
941 if ( tipManager )
942 return tipManager->find( widget, pos );
943 return QString::null;
944}
945
946/*!
947 Hides any tip that is currently being shown.
948
949 Normally, there is no need to call this function; QToolTip takes
950 care of showing and hiding the tips as the user moves the mouse.
951*/
952
953void QToolTip::hide()
954{
955 if ( tipManager )
956 tipManager->hideTipAndSleep();
957}
958
959/*!
960 \fn virtual void QToolTip::maybeTip( const QPoint & p);
961
962 This pure virtual function is half of the most versatile interface
963 QToolTip offers.
964
965 It is called when there is a possibility that a tool tip should be
966 shown and must decide whether there is a tool tip for the point \a
967 p in the widget that this QToolTip object relates to. If so,
968 maybeTip() must call tip() with the rectangle the tip applies to,
969 the tip's text and optionally the QToolTipGroup details and the
970 geometry in screen coordinates.
971
972 \a p is given in that widget's local coordinates. Most maybeTip()
973 implementations will be of the form:
974
975 \code
976 if ( <something> ) {
977 tip( <something>, <something> );
978 }
979 \endcode
980
981 The first argument to tip() (a rectangle) must encompass \a p,
982 i.e. the tip must apply to the current mouse position; otherwise
983 QToolTip's operation is undefined.
984
985 Note that the tip will disappear once the mouse moves outside the
986 rectangle you give to tip(), and will not reappear if the mouse
987 moves back in: maybeTip() is called again instead.
988
989 \sa tip()
990*/
991
992
993/*!
994 Immediately pops up a tip saying \a text and removes the tip once
995 the cursor moves out of rectangle \a rect (which is given in the
996 coordinate system of the widget this QToolTip relates to).
997
998 The tip will not reappear if the cursor moves back; your
999 maybeTip() must reinstate it each time.
1000*/
1001
1002void QToolTip::tip( const QRect & rect, const QString &text )
1003{
1004 initTipManager();
1005 tipManager->add( parentWidget(), rect, text, 0, QString::null, 0, TRUE );
1006}
1007
1008/*!
1009 \overload
1010
1011 Immediately pops up a tip saying \a text and removes that tip once
1012 the cursor moves out of rectangle \a rect (which is given in the
1013 coordinate system of the widget this QToolTip relates to). \a
1014 groupText is the text emitted from the group.
1015
1016 The tip will not reappear if the cursor moves back; your
1017 maybeTip() must reinstate it each time.
1018*/
1019
1020void QToolTip::tip( const QRect & rect, const QString &text,
1021 const QString& groupText )
1022{
1023 initTipManager();
1024 tipManager->add( parentWidget(), rect, text, group(), groupText, 0, TRUE );
1025}
1026
1027/*!
1028 \overload
1029
1030 Immediately pops up a tip within the rectangle \a geometry, saying
1031 \a text and removes the tip once the cursor moves out of rectangle
1032 \a rect. Both rectangles are given in the coordinate system of the
1033 widget this QToolTip relates to.
1034
1035 The tip will not reappear if the cursor moves back; your
1036 maybeTip() must reinstate it each time.
1037
1038 If the tip does not fit inside \a geometry, the tip expands.
1039*/
1040
1041void QToolTip::tip( const QRect &rect, const QString &text, const QRect &geometry )
1042{
1043 initTipManager();
1044 tipManager->add( geometry, parentWidget(), rect, text, 0, QString::null, 0, TRUE );
1045}
1046
1047/*!
1048 \overload
1049
1050 mmediately pops up a tip within the rectangle \a geometry, saying
1051 \a text and removes the tip once the cursor moves out of rectangle
1052 \a rect. \a groupText is the text emitted from the group. Both
1053 rectangles are given in the coordinate system of the widget this
1054 QToolTip relates to.
1055
1056 The tip will not reappear if the cursor moves back; your
1057 maybeTip() must reinstate it each time.
1058
1059 If the tip does not fit inside \a geometry, the tip expands.
1060*/
1061
1062void QToolTip::tip( const QRect &rect, const QString &text, const QString& groupText, const QRect &geometry )
1063{
1064 initTipManager();
1065 tipManager->add( geometry, parentWidget(), rect, text, group(), groupText, 0, TRUE );
1066}
1067
1068
1069
1070/*!
1071 Immediately removes all tool tips for this tooltip's parent
1072 widget.
1073*/
1074
1075void QToolTip::clear()
1076{
1077 if ( tipManager )
1078 tipManager->remove( parentWidget() );
1079}
1080
1081
1082/*!
1083 \fn QWidget * QToolTip::parentWidget() const
1084
1085 Returns the widget this QToolTip applies to.
1086
1087 The tool tip is destroyed automatically when the parent widget is
1088 destroyed.
1089
1090 \sa group()
1091*/
1092
1093
1094/*!
1095 \fn QToolTipGroup * QToolTip::group() const
1096
1097 Returns the tool tip group this QToolTip is a member of or 0 if it
1098 isn't a member of any group.
1099
1100 The tool tip group is the object responsible for maintaining
1101 contact between tool tips and a \link QStatusBar status
1102 bar\endlink or something else which can show the longer help text.
1103
1104 \sa parentWidget(), QToolTipGroup
1105*/
1106
1107
1108/*!
1109 \class QToolTipGroup qtooltip.h
1110 \brief The QToolTipGroup class collects tool tips into related groups.
1111
1112 \ingroup helpsystem
1113
1114 Tool tips can display \e two texts: one in the tip and
1115 (optionally) one that is typically in a \link QStatusBar status
1116 bar\endlink. QToolTipGroup provides a way to link tool tips to
1117 this status bar.
1118
1119 QToolTipGroup has practically no API; it is only used as an
1120 argument to QToolTip's member functions, for example like this:
1121
1122 \code
1123 QToolTipGroup * grp = new QToolTipGroup( this, "tool tip relay" );
1124 connect( grp, SIGNAL(showTip(const QString&)),
1125 myLabel, SLOT(setText(const QString&)) );
1126 connect( grp, SIGNAL(removeTip()),
1127 myLabel, SLOT(clear()) );
1128 QToolTip::add( giraffeButton, "feed giraffe",
1129 grp, "Give the giraffe a meal" );
1130 QToolTip::add( gorillaButton, "feed gorilla",
1131 grp, "Give the gorilla a meal" );
1132 \endcode
1133
1134 This example makes the object myLabel (which you must supply)
1135 display (one assumes, though you can make myLabel do anything, of
1136 course) the strings "Give the giraffe a meal" and "Give the
1137 gorilla a meal" while the relevant tool tips are being displayed.
1138
1139 Deleting a tool tip group removes the tool tips in it.
1140*/
1141
1142/*!
1143 \fn void QToolTipGroup::showTip (const QString &longText)
1144
1145 This signal is emitted when one of the tool tips in the group is
1146 displayed. \a longText is the extra text for the displayed tool
1147 tip.
1148
1149 \sa removeTip()
1150*/
1151
1152/*!
1153 \fn void QToolTipGroup::removeTip ()
1154
1155 This signal is emitted when a tool tip in this group is hidden.
1156 See the QToolTipGroup documentation for an example of use.
1157
1158 \sa showTip()
1159*/
1160
1161
1162/*!
1163 Constructs a tool tip group called \a name, with parent \a parent.
1164*/
1165
1166QToolTipGroup::QToolTipGroup( QObject *parent, const char *name )
1167 : QObject( parent, name )
1168{
1169 del = TRUE;
1170 ena = TRUE;
1171}
1172
1173
1174/*!
1175 Destroys this tool tip group and all tool tips in it.
1176*/
1177
1178QToolTipGroup::~QToolTipGroup()
1179{
1180 if ( tipManager )
1181 tipManager->removeFromGroup( this );
1182}
1183
1184
1185/*!
1186 \property QToolTipGroup::delay
1187 \brief whether the display of the group text is delayed.
1188
1189 If set to TRUE (the default), the group text is displayed at the
1190 same time as the tool tip. Otherwise, the group text is displayed
1191 immediately when the cursor enters the widget.
1192*/
1193
1194bool QToolTipGroup::delay() const
1195{
1196 return del;
1197}
1198
1199void QToolTipGroup::setDelay( bool enable )
1200{
1201#if 0
1202 if ( enable && !del ) {
1203 // maybe we should show the text at once?
1204 }
1205#endif
1206 del = enable;
1207}
1208
1209/*!
1210 \fn static void QToolTip::setEnabled( bool enable )
1211
1212 \obsolete
1213*/
1214/*!
1215 \fn static bool QToolTip::enabled()
1216
1217 \obsolete
1218*/
1219/*!
1220 \property QToolTipGroup::enabled
1221 \brief whether tool tips in the group are enabled.
1222
1223 This property's default is TRUE.
1224*/
1225
1226void QToolTipGroup::setEnabled( bool enable )
1227{
1228 ena = enable;
1229}
1230
1231bool QToolTipGroup::enabled() const
1232{
1233 return (bool)ena;
1234}
1235
1236/*!
1237 If \a enable is TRUE sets all tool tips to be enabled (shown when
1238 needed); if \a enable is FALSE sets all tool tips to be disabled
1239 (never shown).
1240
1241 By default, tool tips are enabled. Note that this function affects
1242 all tool tips in the entire application.
1243
1244 \sa QToolTipGroup::setEnabled()
1245*/
1246
1247void QToolTip::setGloballyEnabled( bool enable )
1248{
1249 globally_enabled = enable;
1250}
1251
1252/*!
1253 Returns whether tool tips are enabled globally.
1254
1255 \sa setGloballyEnabled()
1256*/
1257bool QToolTip::isGloballyEnabled()
1258{
1259 return globally_enabled;
1260}
1261
1262/*!
1263 Sets the wakeup delay for all tooltips to \a i.
1264*/
1265void QToolTip::setWakeUpDelay ( int i )
1266{
1267 initTipManager();
1268 tipManager->setWakeUpDelay(i);
1269}
1270
1271
1272#include "qtooltip.moc"
1273#endif
Note: See TracBrowser for help on using the repository browser.