source: vendor/trolltech/current/src/widgets/qbutton.cpp

Last change on this file was 2, checked in by dmik, 20 years ago

Imported xplatform parts of the official release 3.3.1 from Trolltech

  • Property svn:keywords set to Id
File size: 24.8 KB
Line 
1/****************************************************************************
2** $Id: qbutton.cpp 2 2005-11-16 15:49:26Z dmik $
3**
4** Implementation of QButton widget class
5**
6** Created : 940206
7**
8** Copyright (C) 1992-2003 Trolltech AS. All rights reserved.
9**
10** This file is part of the widgets module of the Qt GUI Toolkit.
11**
12** This file may be distributed under the terms of the Q Public License
13** as defined by Trolltech AS of Norway and appearing in the file
14** LICENSE.QPL included in the packaging of this file.
15**
16** This file may be distributed and/or modified under the terms of the
17** GNU General Public License version 2 as published by the Free Software
18** Foundation and appearing in the file LICENSE.GPL included in the
19** packaging of this file.
20**
21** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
22** licenses may use this file in accordance with the Qt Commercial License
23** Agreement provided with the Software.
24**
25** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27**
28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
29** information about Qt Commercial License Agreements.
30** See http://www.trolltech.com/qpl/ for QPL licensing information.
31** See http://www.trolltech.com/gpl/ for GPL licensing information.
32**
33** Contact info@trolltech.com if any conditions of this licensing are
34** not clear to you.
35**
36**********************************************************************/
37
38#undef QT_NO_COMPAT
39#include "qbutton.h"
40#ifndef QT_NO_BUTTON
41#include "qbuttongroup.h"
42#include "qbitmap.h"
43#include "qpainter.h"
44#include "qtimer.h"
45#include "qaccel.h"
46#include "qpixmapcache.h"
47#include "qapplication.h"
48#include "qpushbutton.h"
49#include "qradiobutton.h"
50#include "qguardedptr.h"
51#include "../kernel/qinternal_p.h"
52
53#if defined(QT_ACCESSIBILITY_SUPPORT)
54#include "qaccessible.h"
55#endif
56
57#define AUTO_REPEAT_DELAY 300
58#define AUTO_REPEAT_PERIOD 100
59
60class QButtonData
61{
62public:
63 QButtonData() {
64#ifndef QT_NO_BUTTONGROUP
65 group = 0;
66#endif
67#ifndef QT_NO_ACCEL
68 a = 0;
69#endif
70 }
71#ifndef QT_NO_BUTTONGROUP
72 QButtonGroup *group;
73#endif
74 QTimer timer;
75#ifndef QT_NO_ACCEL
76 QAccel *a;
77#endif
78};
79
80
81void QButton::ensureData()
82{
83 if ( !d ) {
84 d = new QButtonData;
85 Q_CHECK_PTR( d );
86 connect(&d->timer, SIGNAL(timeout()), this, SLOT(autoRepeatTimeout()));
87 }
88}
89
90
91/*!
92 Returns the group that this button belongs to.
93
94 If the button is not a member of any QButtonGroup, this function
95 returns 0.
96
97 \sa QButtonGroup
98*/
99
100QButtonGroup *QButton::group() const
101{
102#ifndef QT_NO_BUTTONGROUP
103 return d ? d->group : 0;
104#else
105 return 0;
106#endif
107}
108
109
110void QButton::setGroup( QButtonGroup* g )
111{
112#ifndef QT_NO_BUTTONGROUP
113 ensureData();
114 d->group = g;
115#endif
116}
117
118
119QTimer *QButton::timer()
120{
121 ensureData();
122 return &d->timer;
123}
124
125
126/*!
127 \class QButton qbutton.h
128 \brief The QButton class is the abstract base class of button
129 widgets, providing functionality common to buttons.
130
131 \ingroup abstractwidgets
132
133 <b>If you want to create a button use QPushButton.</b>
134
135 The QButton class implements an \e abstract button, and lets
136 subclasses specify how to reply to user actions and how to draw
137 the button.
138
139 QButton provides both push and toggle buttons. The QRadioButton
140 and QCheckBox classes provide only toggle buttons; QPushButton and
141 QToolButton provide both toggle and push buttons.
142
143 Any button can have either a text or pixmap label. setText() sets
144 the button to be a text button and setPixmap() sets it to be a
145 pixmap button. The text/pixmap is manipulated as necessary to
146 create the "disabled" appearance when the button is disabled.
147
148 QButton provides most of the states used for buttons:
149 \list
150 \i isDown() indicates whether the button is \e pressed down.
151 \i isOn() indicates whether the button is \e on.
152 Only toggle buttons can be switched on and off (see below).
153 \i isEnabled() indicates whether the button can be pressed by the
154 user.
155 \i setAutoRepeat() sets whether the button will auto-repeat
156 if the user holds it down.
157 \i setToggleButton() sets whether the button is a toggle
158 button or not.
159 \endlist
160
161 The difference between isDown() and isOn() is as follows: When the
162 user clicks a toggle button to toggle it on, the button is first
163 \e pressed and then released into the \e on state. When the user
164 clicks it again (to toggle it off), the button moves first to the
165 \e pressed state, then to the \e off state (isOn() and isDown()
166 are both FALSE).
167
168 Default buttons (as used in many dialogs) are provided by
169 QPushButton::setDefault() and QPushButton::setAutoDefault().
170
171 QButton provides five signals:
172 \list 1
173 \i pressed() is emitted when the left mouse button is pressed while
174 the mouse cursor is inside the button.
175 \i released() is emitted when the left mouse button is released.
176 \i clicked() is emitted when the button is first pressed and then
177 released when the accelerator key is typed, or when
178 animateClick() is called.
179 \i toggled(bool) is emitted when the state of a toggle button changes.
180 \i stateChanged(int) is emitted when the state of a tristate
181 toggle button changes.
182 \endlist
183
184 If the button is a text button with an ampersand (\&) in its text,
185 QButton creates an automatic accelerator key. This code creates a
186 push button labelled "Ro<u>c</u>k \& Roll" (where the c is
187 underlined). The button gets an automatic accelerator key, Alt+C:
188
189 \code
190 QPushButton *p = new QPushButton( "Ro&ck && Roll", this );
191 \endcode
192
193 In this example, when the user presses Alt+C the button will call
194 animateClick().
195
196 You can also set a custom accelerator using the setAccel()
197 function. This is useful mostly for pixmap buttons because they
198 have no automatic accelerator.
199
200 \code
201 p->setPixmap( QPixmap("print.png") );
202 p->setAccel( ALT+Key_F7 );
203 \endcode
204
205 All of the buttons provided by Qt (\l QPushButton, \l QToolButton,
206 \l QCheckBox and \l QRadioButton) can display both text and
207 pixmaps.
208
209 To subclass QButton, you must reimplement at least drawButton()
210 (to draw the button's outline) and drawButtonLabel() (to draw its
211 text or pixmap). It is generally advisable to reimplement
212 sizeHint() as well, and sometimes hitButton() (to determine
213 whether a button press is within the button).
214
215 To reduce flickering, QButton::paintEvent() sets up a pixmap that
216 the drawButton() function draws in. You should not reimplement
217 paintEvent() for a subclass of QButton unless you want to take
218 over all drawing.
219
220 \sa QButtonGroup
221*/
222
223
224/*!
225 \enum QButton::ToggleType
226
227 This enum type defines what a button can do in response to a
228 mouse/keyboard press:
229
230 \value SingleShot pressing the button causes an action, then the
231 button returns to the unpressed state.
232
233 \value Toggle pressing the button toggles it between an \c On and
234 an \c Off state.
235
236 \value Tristate pressing the button cycles between the three
237 states \c On, \c Off and \c NoChange
238*/
239
240/*!
241 \enum QButton::ToggleState
242
243 This enum defines the state of a toggle button.
244
245 \value Off the button is in the "off" state
246 \value NoChange the button is in the default/unchanged state
247 \value On the button is in the "on" state
248*/
249
250/*!
251 \property QButton::accel
252 \brief the accelerator associated with the button
253
254 This property is 0 if there is no accelerator set. If you set this
255 property to 0 then any current accelerator is removed.
256*/
257
258/*!
259 \property QButton::autoRepeat
260 \brief whether autoRepeat is enabled
261
262 If autoRepeat is enabled then the clicked() signal is emitted at
263 regular intervals if the button is down. This property has no
264 effect on toggle buttons. autoRepeat is off by default.
265*/
266
267/*! \property QButton::autoResize
268 \brief whether autoResize is enabled
269 \obsolete
270
271 If autoResize is enabled then the button will resize itself
272 whenever the contents are changed.
273*/
274
275/*!
276 \property QButton::down
277 \brief whether the button is pressed
278
279 If this property is TRUE, the button is pressed down. The signals
280 pressed() and clicked() are not emitted if you set this property
281 to TRUE. The default is FALSE.
282*/
283
284/*!
285 \property QButton::exclusiveToggle
286 \brief whether the button is an exclusive toggle
287
288 If this property is TRUE and the button is in a QButtonGroup, the
289 button can only be toggled off by another one being toggled on.
290 The default is FALSE.
291*/
292
293/*!
294 \property QButton::on
295 \brief whether the button is toggled
296
297 This property should only be set for toggle buttons.
298*/
299
300/*!
301 \fn void QButton::setOn( bool on )
302
303 Sets the state of this button to On if \a on is TRUE; otherwise to
304 Off.
305
306 \sa toggleState
307*/
308
309/*!
310 \property QButton::pixmap
311 \brief the pixmap shown on the button
312
313 If the pixmap is monochrome (i.e. it is a QBitmap or its \link
314 QPixmap::depth() depth\endlink is 1) and it does not have a mask,
315 this property will set the pixmap to be its own mask. The purpose
316 of this is to draw transparent bitmaps which are important for
317 toggle buttons, for example.
318
319 pixmap() returns 0 if no pixmap was set.
320*/
321
322/*!
323 \property QButton::text
324 \brief the text shown on the button
325
326 This property will return a QString::null if the button has no
327 text. If the text has an ampersand (\&) in it, then an
328 accelerator is automatically created for it using the character
329 that follows the '\&' as the accelerator key.
330
331 There is no default text.
332*/
333
334/*!
335 \property QButton::toggleButton
336 \brief whether the button is a toggle button
337
338 The default value is FALSE.
339*/
340
341/*!
342 \fn QButton::setToggleButton( bool b )
343
344 If \a b is TRUE, this button becomes a toggle button; if \a b is
345 FALSE, this button becomes a command button.
346
347 \sa toggleButton
348*/
349
350/*!
351 \property QButton::toggleState
352 \brief the state of the toggle button
353
354 If this property is changed then it does not cause the button
355 to be repainted.
356*/
357
358/*!
359 \property QButton::toggleType
360 \brief the type of toggle on the button
361
362 The default toggle type is \c SingleShot.
363
364 \sa QButton::ToggleType
365*/
366
367/*!
368 Constructs a standard button called \a name with parent \a parent,
369 using the widget flags \a f.
370
371 If \a parent is a QButtonGroup, this constructor calls
372 QButtonGroup::insert().
373*/
374
375QButton::QButton( QWidget *parent, const char *name, WFlags f )
376 : QWidget( parent, name, f )
377{
378 bpixmap = 0;
379 toggleTyp = SingleShot; // button is simple
380 buttonDown = FALSE; // button is up
381 stat = Off; // button is off
382 mlbDown = FALSE; // mouse left button up
383 autoresize = FALSE; // not auto resizing
384 animation = FALSE; // no pending animateClick
385 repeat = FALSE; // not in autorepeat mode
386 d = 0;
387#ifndef QT_NO_BUTTONGROUP
388 if ( ::qt_cast<QButtonGroup*>(parent) ) {
389 setGroup((QButtonGroup*)parent);
390 group()->insert( this ); // insert into button group
391 }
392#endif
393 setFocusPolicy( TabFocus );
394}
395
396/*!
397 Destroys the button.
398 */
399QButton::~QButton()
400{
401#ifndef QT_NO_BUTTONGROUP
402 if ( group() )
403 group()->remove( this );
404#endif
405 delete bpixmap;
406 delete d;
407}
408
409
410/*!
411 \fn void QButton::pressed()
412
413 This signal is emitted when the button is pressed down.
414
415 \sa released(), clicked()
416*/
417
418/*!
419 \fn void QButton::released()
420
421 This signal is emitted when the button is released.
422
423 \sa pressed(), clicked(), toggled()
424*/
425
426/*!
427 \fn void QButton::clicked()
428
429 This signal is emitted when the button is activated (i.e. first
430 pressed down and then released when the mouse cursor is inside the
431 button), when the accelerator key is typed or when animateClick()
432 is called. This signal is \e not emitted if you call setDown().
433
434 The QButtonGroup::clicked() signal does the same job, if you want
435 to connect several buttons to the same slot.
436
437 \warning Don't launch a model dialog in response to this signal
438 for a button that has \c autoRepeat turned on.
439
440 \sa pressed(), released(), toggled() autoRepeat down
441*/
442
443/*!
444 \fn void QButton::toggled( bool on )
445
446 This signal is emitted whenever a toggle button changes status. \a
447 on is TRUE if the button is on, or FALSE if the button is off.
448
449 This may be the result of a user action, toggle() slot activation,
450 or because setOn() was called.
451
452 \sa clicked()
453*/
454
455/*!
456 \fn void QButton::stateChanged( int state )
457
458 This signal is emitted whenever a toggle button changes state. \a
459 state is \c On if the button is on, \c NoChange if it is in the
460 \link QCheckBox::setTristate() "no change" state\endlink or \c Off
461 if the button is off.
462
463 This may be the result of a user action, toggle() slot activation,
464 setState(), or because setOn() was called.
465
466 \sa clicked() QButton::ToggleState
467*/
468
469void QButton::setText( const QString &text )
470{
471 if ( btext == text )
472 return;
473 btext = text;
474#ifndef QT_NO_ACCEL
475 setAccel( QAccel::shortcutKey( text ) );
476#endif
477
478 if ( bpixmap ) {
479 delete bpixmap;
480 bpixmap = 0;
481 }
482
483 if ( autoresize )
484 adjustSize();
485
486 update();
487 updateGeometry();
488
489#if defined(QT_ACCESSIBILITY_SUPPORT)
490 QAccessible::updateAccessibility( this, 0, QAccessible::NameChanged );
491#endif
492}
493
494void QButton::setPixmap( const QPixmap &pixmap )
495{
496 if ( bpixmap && bpixmap->serialNumber() == pixmap.serialNumber() )
497 return;
498
499 bool newSize;
500 if ( bpixmap ) {
501 newSize = pixmap.width() != bpixmap->width() ||
502 pixmap.height() != bpixmap->height();
503 *bpixmap = pixmap;
504 } else {
505 newSize = TRUE;
506 bpixmap = new QPixmap( pixmap );
507 Q_CHECK_PTR( bpixmap );
508 }
509 if ( bpixmap->depth() == 1 && !bpixmap->mask() )
510 bpixmap->setMask( *((QBitmap *)bpixmap) );
511 if ( !btext.isNull() ) {
512 btext = QString::null;
513#ifndef QT_NO_ACCEL
514 setAccel( QKeySequence() );
515#endif
516 }
517 if ( autoresize && newSize )
518 adjustSize();
519 if ( autoMask() )
520 updateMask();
521 update();
522 if ( newSize )
523 updateGeometry();
524}
525
526
527#ifndef QT_NO_ACCEL
528QKeySequence QButton::accel() const
529{
530 if ( d && d->a )
531 return d->a->key( 0 );
532 return QKeySequence();
533}
534
535void QButton::setAccel( const QKeySequence& key )
536{
537 if ( d && d->a )
538 d->a->clear();
539 if ( key.isEmpty() )
540 return;
541 ensureData();
542 if ( !d->a ) {
543 d->a = new QAccel( this, "buttonAccel" );
544 connect( d->a, SIGNAL( activated(int) ), this, SLOT( animateClick() ) );
545 connect( d->a, SIGNAL( activatedAmbiguously(int) ), this, SLOT( setFocus() ) );
546 }
547 d->a->insertItem( key, 0 );
548}
549#endif
550
551#ifndef QT_NO_COMPAT
552
553void QButton::setAutoResize( bool enable )
554{
555 if ( (bool)autoresize != enable ) {
556 autoresize = enable;
557 if ( autoresize )
558 adjustSize(); // calls resize which repaints
559 }
560}
561
562#endif
563
564void QButton::setAutoRepeat( bool enable )
565{
566 repeat = (uint)enable;
567 if ( repeat && mlbDown )
568 timer()->start( AUTO_REPEAT_DELAY, TRUE );
569}
570
571/*!
572 Performs an animated click: the button is pressed and released a
573 short while later.
574
575 The pressed(), released(), clicked(), toggled(), and
576 stateChanged() signals are emitted as appropriate.
577
578 This function does nothing if the button is \link setEnabled()
579 disabled. \endlink
580
581 \sa setAccel()
582*/
583
584void QButton::animateClick()
585{
586 if ( !isEnabled() || animation )
587 return;
588 animation = TRUE;
589 buttonDown = TRUE;
590 repaint( FALSE );
591 emit pressed();
592 QTimer::singleShot( 100, this, SLOT(animateTimeout()) );
593}
594
595void QButton::emulateClick()
596{
597 if ( !isEnabled() || animation )
598 return;
599 animation = TRUE;
600 buttonDown = TRUE;
601 emit pressed();
602 animateTimeout();
603}
604
605void QButton::setDown( bool enable )
606{
607 if ( d )
608 timer()->stop();
609 mlbDown = FALSE; // the safe setting
610 if ( (bool)buttonDown != enable ) {
611 buttonDown = enable;
612 repaint( FALSE );
613#if defined(QT_ACCESSIBILITY_SUPPORT)
614 QAccessible::updateAccessibility( this, 0, QAccessible::StateChanged );
615#endif
616 }
617}
618
619/*!
620 Sets the toggle state of the button to \a s. \a s can be \c Off, \c
621 NoChange or \c On.
622*/
623
624void QButton::setState( ToggleState s )
625{
626 if ( !toggleTyp ) {
627#if defined(QT_CHECK_STATE)
628 qWarning( "QButton::setState() / setOn: (%s) Only toggle buttons "
629 "may be switched", name( "unnamed" ) );
630#endif
631 return;
632 }
633
634 if ( (ToggleState)stat != s ) { // changed state
635 bool was = stat != Off;
636 stat = s;
637 if ( autoMask() )
638 updateMask();
639 repaint( FALSE );
640#if defined(QT_ACCESSIBILITY_SUPPORT)
641 QAccessible::updateAccessibility( this, 0, QAccessible::StateChanged );
642#endif
643 // ### toggled for tristate makes no sense. Don't emit the signal in 4.0
644 if ( was != (stat != Off) )
645 emit toggled( stat != Off );
646 emit stateChanged( s );
647 }
648}
649
650
651/*!
652 Returns TRUE if \a pos is inside the clickable button rectangle;
653 otherwise returns FALSE.
654
655 By default, the clickable area is the entire widget. Subclasses
656 may reimplement it, though.
657*/
658bool QButton::hitButton( const QPoint &pos ) const
659{
660 return rect().contains( pos );
661}
662
663/*!
664 Draws the button. The default implementation does nothing.
665
666 This virtual function is reimplemented by subclasses to draw real
667 buttons. At some point, these reimplementations should call
668 drawButtonLabel().
669
670 \sa drawButtonLabel(), paintEvent()
671*/
672#if (QT_VERSION-0 >= 0x040000)
673#error "QButton. Make pure virtual"
674#endif
675void QButton::drawButton( QPainter * )
676{
677 return;
678}
679
680/*!
681 Draws the button text or pixmap.
682
683 This virtual function is reimplemented by subclasses to draw real
684 buttons. It is invoked by drawButton().
685
686 \sa drawButton(), paintEvent()
687*/
688
689void QButton::drawButtonLabel( QPainter * )
690{
691 return;
692}
693
694/*! \reimp */
695void QButton::keyPressEvent( QKeyEvent *e )
696{
697 switch ( e->key() ) {
698 case Key_Enter:
699 case Key_Return:
700 {
701#ifndef QT_NO_PUSHBUTTON
702 QPushButton *pb = (QPushButton*)qt_cast( "QPushButton" );
703 if ( pb && ( pb->autoDefault() || pb->isDefault() ) )
704 emit clicked();
705 else
706#endif
707 e->ignore();
708 }
709 break;
710 case Key_Space:
711 if ( !e->isAutoRepeat() ) {
712 setDown( TRUE );
713#ifndef QT_NO_PUSHBUTTON
714 if ( ::qt_cast<QPushButton*>(this) )
715 emit pressed();
716 else
717#endif
718 e->ignore();
719 }
720 break;
721 case Key_Up:
722 case Key_Left:
723#ifndef QT_NO_BUTTONGROUP
724 if ( group() ) {
725 group()->moveFocus( e->key() );
726 if (hasFocus()) // nothing happend, propagate
727 e->ignore();
728 } else
729#endif
730 {
731 QFocusEvent::setReason(QFocusEvent::Backtab);
732 focusNextPrevChild( FALSE );
733 QFocusEvent::resetReason();
734 }
735 break;
736 case Key_Right:
737 case Key_Down:
738#ifndef QT_NO_BUTTONGROUP
739 if ( group() ) {
740 group()->moveFocus( e->key() );
741 if (hasFocus()) // nothing happend, propagate
742 e->ignore();
743 } else
744#endif
745 {
746 QFocusEvent::setReason(QFocusEvent::Tab);
747 focusNextPrevChild( TRUE );
748 QFocusEvent::resetReason();
749 }
750 break;
751 case Key_Escape:
752 if ( buttonDown ) {
753 buttonDown = FALSE;
754 update();
755 break;
756 }
757 // fall through
758 default:
759 e->ignore();
760 }
761}
762
763/*! \reimp */
764void QButton::keyReleaseEvent( QKeyEvent * e)
765{
766 switch ( e->key() ) {
767 case Key_Space:
768 if ( buttonDown && !e->isAutoRepeat() ) {
769 buttonDown = FALSE;
770 nextState();
771 emit released();
772 emit clicked();
773 }
774 break;
775 default:
776 e->ignore();
777 }
778}
779
780/*! \reimp */
781void QButton::mousePressEvent( QMouseEvent *e )
782{
783 if ( e->button() != LeftButton ) {
784 e->ignore();
785 return;
786 }
787 bool hit = hitButton( e->pos() );
788 if ( hit ) { // mouse press on button
789 mlbDown = TRUE; // left mouse button down
790 buttonDown = TRUE;
791 if ( autoMask() )
792 updateMask();
793
794 repaint( FALSE );
795#if defined(QT_ACCESSIBILITY_SUPPORT)
796 QAccessible::updateAccessibility( this, 0, QAccessible::StateChanged );
797#endif
798 QGuardedPtr<QTimer> t = timer();
799 emit pressed();
800 if ( t && repeat )
801 t->start( AUTO_REPEAT_DELAY, TRUE );
802 }
803}
804
805/*! \reimp */
806void QButton::mouseReleaseEvent( QMouseEvent *e)
807{
808 if ( e->button() != LeftButton ) {
809
810 // clean up apperance if left button has been pressed
811 if (mlbDown || buttonDown) {
812 mlbDown = FALSE;
813 buttonDown = FALSE;
814
815 if ( autoMask() )
816 updateMask();
817 repaint( FALSE );
818 }
819
820 e->ignore();
821 return;
822 }
823 if ( !mlbDown )
824 return;
825 if ( d )
826 timer()->stop();
827 mlbDown = FALSE; // left mouse button up
828 buttonDown = FALSE;
829 if ( hitButton( e->pos() ) ) { // mouse release on button
830 nextState();
831#if defined(QT_ACCESSIBILITY_SUPPORT)
832 QAccessible::updateAccessibility( this, 0, QAccessible::StateChanged );
833#endif
834 emit released();
835 emit clicked();
836 } else {
837 repaint( FALSE );
838#if defined(QT_ACCESSIBILITY_SUPPORT)
839 QAccessible::updateAccessibility( this, 0, QAccessible::StateChanged );
840#endif
841 emit released();
842 }
843}
844
845/*! \reimp */
846void QButton::mouseMoveEvent( QMouseEvent *e )
847{
848 if ( !((e->state() & LeftButton) && mlbDown) ) {
849 e->ignore();
850 return; // left mouse button is up
851 }
852 if ( hitButton(e->pos()) ) { // mouse move in button
853 if ( !buttonDown ) {
854 buttonDown = TRUE;
855 repaint( FALSE );
856#if defined(QT_ACCESSIBILITY_SUPPORT)
857 QAccessible::updateAccessibility( this, 0, QAccessible::StateChanged );
858#endif
859 emit pressed();
860 }
861 } else { // mouse move outside button
862 if ( buttonDown ) {
863 buttonDown = FALSE;
864 repaint( FALSE );
865#if defined(QT_ACCESSIBILITY_SUPPORT)
866 QAccessible::updateAccessibility( this, 0, QAccessible::StateChanged );
867#endif
868 emit released();
869 }
870 }
871}
872
873
874/*!
875 Handles paint events for buttons. Small and typically complex
876 buttons are painted double-buffered to reduce flicker. The
877 actually drawing is done in the virtual functions drawButton() and
878 drawButtonLabel().
879
880 \sa drawButton(), drawButtonLabel()
881*/
882void QButton::paintEvent( QPaintEvent *)
883{
884 QSharedDoubleBuffer buffer( this );
885 drawButton( buffer.painter() );
886}
887
888/*! \reimp */
889void QButton::focusInEvent( QFocusEvent * e)
890{
891 QWidget::focusInEvent( e );
892}
893
894/*! \reimp */
895void QButton::focusOutEvent( QFocusEvent * e )
896{
897 buttonDown = FALSE;
898 QWidget::focusOutEvent( e );
899}
900
901/*!
902 Internal slot used for auto repeat.
903*/
904void QButton::autoRepeatTimeout()
905{
906 if ( mlbDown && isEnabled() && autoRepeat() ) {
907 QGuardedPtr<QTimer> t = timer();
908 if ( buttonDown ) {
909 emit released();
910 emit clicked();
911 emit pressed();
912 }
913 if ( t )
914 t->start( AUTO_REPEAT_PERIOD, TRUE );
915 }
916}
917
918/*!
919 Internal slot used for the second stage of animateClick().
920*/
921void QButton::animateTimeout()
922{
923 if ( !animation )
924 return;
925 animation = FALSE;
926 buttonDown = FALSE;
927 nextState();
928 emit released();
929 emit clicked();
930}
931
932
933void QButton::nextState()
934{
935 bool t = isToggleButton() && !( isOn() && isExclusiveToggle() );
936 bool was = stat != Off;
937 if ( t ) {
938 if ( toggleTyp == Tristate )
939 stat = ( stat + 1 ) % 3;
940 else
941 stat = stat ? Off : On;
942 }
943 if ( autoMask() )
944 updateMask();
945 repaint( FALSE );
946 if ( t ) {
947#if defined(QT_ACCESSIBILITY_SUPPORT)
948 QAccessible::updateAccessibility( this, 0, QAccessible::StateChanged );
949#endif
950 if ( was != (stat != Off) )
951 emit toggled( stat != Off );
952 emit stateChanged( stat );
953 }
954}
955
956/*! \reimp */
957void QButton::enabledChange( bool e )
958{
959 if ( !isEnabled() )
960 setDown( FALSE );
961 QWidget::enabledChange( e );
962}
963
964
965/*!
966 Toggles the state of a toggle button.
967
968 \sa isOn(), setOn(), toggled(), isToggleButton()
969*/
970void QButton::toggle()
971{
972 if ( isToggleButton() )
973 setOn( !isOn() );
974}
975
976/*!
977 Sets the toggle type of the button to \a type.
978
979 \a type can be set to \c SingleShot, \c Toggle and \c Tristate.
980*/
981void QButton::setToggleType( ToggleType type )
982{
983 toggleTyp = type;
984 if ( type != Tristate && stat == NoChange )
985 setState( On );
986#if defined(QT_ACCESSIBILITY_SUPPORT)
987 else
988 QAccessible::updateAccessibility( this, 0, QAccessible::StateChanged );
989#endif
990}
991
992bool QButton::isExclusiveToggle() const
993{
994#ifndef QT_NO_BUTTONGROUP
995 return group() && ( group()->isExclusive() ||
996 group()->isRadioButtonExclusive() &&
997 ::qt_cast<QRadioButton*>(this) );
998#else
999 return FALSE;
1000#endif
1001}
1002
1003#endif
Note: See TracBrowser for help on using the repository browser.