source: vendor/trolltech/current/src/widgets/qaction.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: 59.0 KB
Line 
1/****************************************************************************
2** $Id: qaction.cpp 2 2005-11-16 15:49:26Z dmik $
3**
4** Implementation of QAction class
5**
6** Copyright (C) 2000-2003 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 "qaction.h"
37
38#ifndef QT_NO_ACTION
39
40#include "qtoolbar.h"
41#include "qptrlist.h"
42#include "qpopupmenu.h"
43#include "qaccel.h"
44#include "qtoolbutton.h"
45#include "qcombobox.h"
46#include "qtooltip.h"
47#include "qwhatsthis.h"
48#include "qstatusbar.h"
49#include "qobjectlist.h"
50
51
52/*!
53 \class QAction qaction.h
54 \brief The QAction class provides an abstract user interface
55 action that can appear both in menus and tool bars.
56
57 \ingroup basic
58 \ingroup application
59 \mainclass
60
61 In GUI applications many commands can be invoked via a menu
62 option, a toolbar button and a keyboard accelerator. Since the
63 same action must be performed regardless of how the action was
64 invoked, and since the menu and toolbar should be kept in sync, it
65 is useful to represent a command as an \e action. An action can be
66 added to a menu and a toolbar and will automatically keep them in
67 sync. For example, if the user presses a Bold toolbar button the
68 Bold menu item will automatically be checked.
69
70 A QAction may contain an icon, a menu text, an accelerator, a
71 status text, a whats this text and a tool tip. Most of these can
72 be set in the constructor. They can also be set independently with
73 setIconSet(), setText(), setMenuText(), setToolTip(),
74 setStatusTip(), setWhatsThis() and setAccel().
75
76 An action may be a toggle action e.g. a Bold toolbar button, or a
77 command action, e.g. 'Open File' to invoke an open file dialog.
78 Toggle actions emit the toggled() signal when their state changes.
79 Both command and toggle actions emit the activated() signal when
80 they are invoked. Use setToggleAction() to set an action's toggled
81 status. To see if an action is a toggle action use
82 isToggleAction(). A toggle action may be "on", isOn() returns
83 TRUE, or "off", isOn() returns FALSE.
84
85 Actions are added to widgets (menus or toolbars) using addTo(),
86 and removed using removeFrom().
87
88 Once a QAction has been created it should be added to the relevant
89 menu and toolbar and then connected to the slot which will perform
90 the action. For example:
91
92 \quotefile action/application.cpp
93 \skipto QPixmap( fileopen
94 \printuntil connect
95
96 We create a "File Save" action with a menu text of "&Save" and
97 \e{Ctrl+S} as the keyboard accelerator. We connect the
98 fileSaveAction's activated() signal to our own save() slot. Note
99 that at this point there is no menu or toolbar action, we'll add
100 them next:
101
102 \skipto new QToolBar
103 \printline
104 \skipto fileSaveAction->addTo
105 \printline
106 \skipto new QPopupMenu
107 \printuntil insertItem
108 \skipto fileSaveAction->addTo
109 \printline
110
111 We create a toolbar and add our fileSaveAction to it. Similarly we
112 create a menu, add a top-level menu item, and add our
113 fileSaveAction.
114
115 We recommend that actions are created as children of the window
116 that they are used in. In most cases actions will be children of
117 the application's main window.
118
119 To prevent recursion, don't create an action as a child of a
120 widget that the action is later added to.
121*/
122
123class QActionPrivate
124{
125public:
126 QActionPrivate(QAction *act);
127 ~QActionPrivate();
128 QIconSet *iconset;
129 QString text;
130 QString menutext;
131 QString tooltip;
132 QString statustip;
133 QString whatsthis;
134#ifndef QT_NO_ACCEL
135 QKeySequence key;
136 QAccel* accel;
137 int accelid;
138#endif
139 uint enabled : 1;
140 uint visible : 1;
141 uint toggleaction : 1;
142 uint on : 1;
143 uint forceDisabled : 1;
144#ifndef QT_NO_TOOLTIP
145 QToolTipGroup tipGroup;
146#endif
147 QActionGroupPrivate* d_group;
148 QAction *action;
149
150 struct MenuItem {
151 MenuItem():popup(0),id(0){}
152 QPopupMenu* popup;
153 int id;
154 };
155 // ComboItem is only necessary for actions that are
156 // in dropdown/exclusive actiongroups. The actiongroup
157 // will clean this up
158 struct ComboItem {
159 ComboItem():combo(0), id(0) {}
160 QComboBox *combo;
161 int id;
162 };
163 QPtrList<MenuItem> menuitems;
164 QPtrList<QToolButton> toolbuttons;
165 QPtrList<ComboItem> comboitems;
166
167 enum Update { Icons = 1, Visibility = 2, State = 4, EverythingElse = 8 };
168 void update( uint upd = EverythingElse );
169
170 QString menuText() const;
171 QString toolTip() const;
172 QString statusTip() const;
173};
174
175QActionPrivate::QActionPrivate(QAction *act)
176 : iconset( 0 ),
177#ifndef QT_NO_ACCEL
178 key( 0 ), accel( 0 ), accelid( 0 ),
179#endif
180 enabled( TRUE ), visible( TRUE ), toggleaction( FALSE ), on( FALSE ),
181 forceDisabled( FALSE ),
182#ifndef QT_NO_TOOLTIP
183 tipGroup( 0 ),
184#endif
185 d_group( 0 ), action(act)
186{
187 menuitems.setAutoDelete( TRUE );
188 comboitems.setAutoDelete( TRUE );
189#ifndef QT_NO_TOOLTIP
190 tipGroup.setDelay( FALSE );
191#endif
192}
193
194QActionPrivate::~QActionPrivate()
195{
196 QPtrListIterator<QToolButton> ittb( toolbuttons );
197 QToolButton *tb;
198
199 while ( ( tb = ittb.current() ) ) {
200 ++ittb;
201 delete tb;
202 }
203
204 QPtrListIterator<QActionPrivate::MenuItem> itmi( menuitems);
205 QActionPrivate::MenuItem* mi;
206 while ( ( mi = itmi.current() ) ) {
207 ++itmi;
208 QPopupMenu* menu = mi->popup;
209 if ( menu->findItem( mi->id ) )
210 menu->removeItem( mi->id );
211 }
212
213 QPtrListIterator<QActionPrivate::ComboItem> itci(comboitems);
214 QActionPrivate::ComboItem* ci;
215 while ( ( ci = itci.current() ) ) {
216 ++itci;
217 QComboBox* combo = ci->combo;
218 combo->clear();
219 QActionGroup *group = ::qt_cast<QActionGroup*>(action->parent());
220 QObjectList *siblings = group ? group->queryList("QAction") : 0;
221 if (siblings) {
222 QObjectListIt it(*siblings);
223 while (it.current()) {
224 QAction *sib = ::qt_cast<QAction*>(it.current());
225 ++it;
226 sib->removeFrom(combo);
227 }
228 it = QObjectListIt(*siblings);
229 while (it.current()) {
230 QAction *sib = ::qt_cast<QAction*>(it.current());
231 ++it;
232 if (sib == action)
233 continue;
234 sib->addTo(combo);
235 }
236 }
237 delete siblings;
238 }
239
240#ifndef QT_NO_ACCEL
241 delete accel;
242#endif
243 delete iconset;
244}
245
246class QActionGroupPrivate
247{
248public:
249 uint exclusive: 1;
250 uint dropdown: 1;
251 QPtrList<QAction> actions;
252 QAction* selected;
253 QAction* separatorAction;
254
255 struct MenuItem {
256 MenuItem():popup(0),id(0){}
257 QPopupMenu* popup;
258 int id;
259 };
260
261 QPtrList<QComboBox> comboboxes;
262 QPtrList<QToolButton> menubuttons;
263 QPtrList<MenuItem> menuitems;
264 QPtrList<QPopupMenu> popupmenus;
265
266 void update( const QActionGroup * );
267};
268
269void QActionPrivate::update( uint upd )
270{
271 for ( QPtrListIterator<MenuItem> it( menuitems); it.current(); ++it ) {
272 MenuItem* mi = it.current();
273 QString t = menuText();
274#ifndef QT_NO_ACCEL
275 if ( key )
276 t += '\t' + QAccel::keyToString( key );
277#endif
278 if ( upd & State ) {
279 mi->popup->setItemEnabled( mi->id, enabled );
280 if ( toggleaction )
281 mi->popup->setItemChecked( mi->id, on );
282 }
283 if ( upd & Visibility )
284 mi->popup->setItemVisible( mi->id, visible );
285
286 if ( upd & Icons )
287 if ( iconset )
288 mi->popup->changeItem( mi->id, *iconset, t );
289 else
290 mi->popup->changeItem( mi->id, QIconSet(), t );
291 if ( upd & EverythingElse ) {
292 mi->popup->changeItem( mi->id, t );
293 if ( !whatsthis.isEmpty() )
294 mi->popup->setWhatsThis( mi->id, whatsthis );
295 if ( toggleaction ) {
296 mi->popup->setCheckable( TRUE );
297 mi->popup->setItemChecked( mi->id, on );
298 }
299 }
300 }
301 for ( QPtrListIterator<QToolButton> it2(toolbuttons); it2.current(); ++it2 ) {
302 QToolButton* btn = it2.current();
303 if ( upd & State ) {
304 btn->setEnabled( enabled );
305 if ( toggleaction )
306 btn->setOn( on );
307 }
308 if ( upd & Visibility )
309 visible ? btn->show() : btn->hide();
310 if ( upd & Icons ) {
311 if ( iconset )
312 btn->setIconSet( *iconset );
313 else
314 btn->setIconSet( QIconSet() );
315 }
316 if ( upd & EverythingElse ) {
317 btn->setToggleButton( toggleaction );
318 if ( !text.isEmpty() )
319 btn->setTextLabel( text, FALSE );
320#ifndef QT_NO_TOOLTIP
321 QToolTip::remove( btn );
322 QToolTip::add( btn, toolTip(), &tipGroup, statusTip() );
323#endif
324#ifndef QT_NO_WHATSTHIS
325 QWhatsThis::remove( btn );
326 if ( !whatsthis.isEmpty() )
327 QWhatsThis::add( btn, whatsthis );
328#endif
329 }
330 }
331#ifndef QT_NO_ACCEL
332 if ( accel ) {
333 accel->setEnabled( enabled && visible );
334 if ( !whatsthis.isEmpty() )
335 accel->setWhatsThis( accelid, whatsthis );
336 }
337#endif
338 // Only used by actiongroup
339 for ( QPtrListIterator<ComboItem> it3( comboitems ); it3.current(); ++it3 ) {
340 ComboItem *ci = it3.current();
341 if ( !ci->combo )
342 return;
343 if ( iconset )
344 ci->combo->changeItem( iconset->pixmap(), text, ci->id );
345 else
346 ci->combo->changeItem( text, ci->id );
347 }
348}
349
350QString QActionPrivate::menuText() const
351{
352 if ( menutext.isNull() ) {
353 QString t(text);
354 t.replace('&', "&&");
355 return t;
356 }
357 return menutext;
358}
359
360QString QActionPrivate::toolTip() const
361{
362 if ( tooltip.isNull() ) {
363#ifndef QT_NO_ACCEL
364 if ( accel )
365 return text + " (" + QAccel::keyToString( accel->key( accelid )) + ")";
366#endif
367 return text;
368 }
369 return tooltip;
370}
371
372QString QActionPrivate::statusTip() const
373{
374 if ( statustip.isNull() )
375 return toolTip();
376 return statustip;
377}
378
379/*
380 internal: guesses a descriptive text from a menu text
381 */
382static QString qt_stripMenuText( QString s )
383{
384 s.remove( QString::fromLatin1("...") );
385 s.remove( QChar('&' ) );
386 return s.stripWhiteSpace();
387};
388
389/*!
390 Constructs an action called \a name with parent \a parent.
391
392 If \a parent is a QActionGroup, the new action inserts itself into
393 \a parent.
394
395 For accelerators and status tips to work, \a parent must either be
396 a widget, or an action group whose parent is a widget.
397
398 \warning To prevent recursion, don't create an action as a child
399 of a widget that the action is later added to.
400*/
401QAction::QAction( QObject* parent, const char* name )
402 : QObject( parent, name )
403{
404 d = new QActionPrivate(this);
405 init();
406}
407
408/*! \obsolete
409 Constructs an action called \a name with parent \a parent.
410
411 If \a toggle is TRUE the action will be a toggle action, otherwise
412 it will be a command action.
413
414 If \a parent is a QActionGroup, the new action inserts itself into
415 \a parent.
416
417 For accelerators and status tips to work, \a parent must either be
418 a widget, or an action group whose parent is a widget.
419*/
420QAction::QAction( QObject* parent, const char* name, bool toggle )
421 : QObject( parent, name )
422{
423 d = new QActionPrivate(this);
424 d->toggleaction = toggle;
425 init();
426}
427
428
429#ifndef QT_NO_ACCEL
430
431/*!
432 This constructor creates an action with the following properties:
433 the icon or iconset \a icon, the menu text \a menuText and
434 keyboard accelerator \a accel. It is a child of \a parent and
435 called \a name.
436
437 If \a parent is a QActionGroup, the action automatically becomes
438 a member of it.
439
440 For accelerators and status tips to work, \a parent must either be
441 a widget, or an action group whose parent is a widget.
442
443 The action uses a stripped version of \a menuText (e.g. "\&Menu
444 Option..." becomes "Menu Option") as descriptive text for
445 toolbuttons. You can override this by setting a specific
446 description with setText(). The same text and \a accel will be
447 used for tool tips and status tips unless you provide text for
448 these using setToolTip() and setStatusTip().
449
450 Call setToggleAction(TRUE) to make the action a toggle action.
451
452 \warning To prevent recursion, don't create an action as a child
453 of a widget that the action is later added to.
454*/
455QAction::QAction( const QIconSet& icon, const QString& menuText, QKeySequence accel,
456 QObject* parent, const char* name )
457 : QObject( parent, name )
458{
459 d = new QActionPrivate(this);
460 if ( !icon.isNull() )
461 setIconSet( icon );
462 d->text = qt_stripMenuText( menuText );
463 d->menutext = menuText;
464 setAccel( accel );
465 init();
466}
467
468/*!
469 This constructor results in an icon-less action with the the menu
470 text \a menuText and keyboard accelerator \a accel. It is a child
471 of \a parent and called \a name.
472
473 If \a parent is a QActionGroup, the action automatically becomes
474 a member of it.
475
476 For accelerators and status tips to work, \a parent must either be
477 a widget, or an action group whose parent is a widget.
478
479 The action uses a stripped version of \a menuText (e.g. "\&Menu
480 Option..." becomes "Menu Option") as descriptive text for
481 toolbuttons. You can override this by setting a specific
482 description with setText(). The same text and \a accel will be
483 used for tool tips and status tips unless you provide text for
484 these using setToolTip() and setStatusTip().
485
486 Call setToggleAction(TRUE) to make the action a toggle action.
487
488 \warning To prevent recursion, don't create an action as a child
489 of a widget that the action is later added to.
490*/
491QAction::QAction( const QString& menuText, QKeySequence accel,
492 QObject* parent, const char* name )
493 : QObject( parent, name )
494{
495 d = new QActionPrivate(this);
496 d->text = qt_stripMenuText( menuText );
497 d->menutext = menuText;
498 setAccel( accel );
499 init();
500}
501
502/*! \obsolete
503 This constructor creates an action with the following properties:
504 the description \a text, the icon or iconset \a icon, the menu
505 text \a menuText and keyboard accelerator \a accel. It is a child
506 of \a parent and called \a name. If \a toggle is TRUE the action
507 will be a toggle action, otherwise it will be a command action.
508
509 If \a parent is a QActionGroup, the action automatically becomes
510 a member of it.
511
512 For accelerators and status tips to work, \a parent must either be
513 a widget, or an action group whose parent is a widget.
514
515 The \a text and \a accel will be used for tool tips and status
516 tips unless you provide specific text for these using setToolTip()
517 and setStatusTip().
518*/
519QAction::QAction( const QString& text, const QIconSet& icon, const QString& menuText, QKeySequence accel, QObject* parent, const char* name, bool toggle )
520 : QObject( parent, name )
521{
522 d = new QActionPrivate(this);
523 d->toggleaction = toggle;
524 if ( !icon.isNull() )
525 setIconSet( icon );
526
527 d->text = text;
528 d->menutext = menuText;
529 setAccel( accel );
530 init();
531}
532
533/*! \obsolete
534 This constructor results in an icon-less action with the
535 description \a text, the menu text \a menuText and the keyboard
536 accelerator \a accel. Its parent is \a parent and it is called \a
537 name. If \a toggle is TRUE the action will be a toggle action,
538 otherwise it will be a command action.
539
540 The action automatically becomes a member of \a parent if \a
541 parent is a QActionGroup.
542
543 For accelerators and status tips to work, \a parent must either be
544 a widget, or an action group whose parent is a widget.
545
546 The \a text and \a accel will be used for tool tips and status
547 tips unless you provide specific text for these using setToolTip()
548 and setStatusTip().
549*/
550QAction::QAction( const QString& text, const QString& menuText, QKeySequence accel, QObject* parent, const char* name, bool toggle )
551 : QObject( parent, name )
552{
553 d = new QActionPrivate(this);
554 d->toggleaction = toggle;
555 d->text = text;
556 d->menutext = menuText;
557 setAccel( accel );
558 init();
559}
560#endif
561
562/*!
563 \internal
564*/
565void QAction::init()
566{
567 if ( ::qt_cast<QActionGroup*>(parent()) )
568 ((QActionGroup*) parent())->add( this ); // insert into action group
569}
570
571/*!
572 Destroys the object and frees allocated resources.
573*/
574
575QAction::~QAction()
576{
577 delete d;
578}
579
580/*!
581 \property QAction::iconSet
582 \brief the action's icon
583
584 The icon is used as the tool button icon and in the menu to the
585 left of the menu text. There is no default icon.
586
587 If a null icon (QIconSet::isNull() is passed into this function,
588 the icon of the action is cleared.
589
590 (See the action/toggleaction/toggleaction.cpp example.)
591
592*/
593void QAction::setIconSet( const QIconSet& icon )
594{
595 register QIconSet *i = d->iconset;
596 if ( !icon.isNull() )
597 d->iconset = new QIconSet( icon );
598 else
599 d->iconset = 0;
600 delete i;
601 d->update( QActionPrivate::Icons );
602}
603
604QIconSet QAction::iconSet() const
605{
606 if ( d->iconset )
607 return *d->iconset;
608 return QIconSet();
609}
610
611/*!
612 \property QAction::text
613 \brief the action's descriptive text
614
615 If \l QMainWindow::usesTextLabel is TRUE, the text appears as a
616 label in the relevant tool button. It also serves as the default
617 text in menus and tool tips if these have not been specifically
618 defined. There is no default text.
619
620 \sa setMenuText() setToolTip() setStatusTip()
621*/
622void QAction::setText( const QString& text )
623{
624 d->text = text;
625 d->update();
626}
627
628QString QAction::text() const
629{
630 return d->text;
631}
632
633
634/*!
635 \property QAction::menuText
636 \brief the action's menu text
637
638 If the action is added to a menu the menu option will consist of
639 the icon (if there is one), the menu text and the accelerator (if
640 there is one). If the menu text is not explicitly set in the
641 constructor or by using setMenuText() the action's description
642 text will be used as the menu text. There is no default menu text.
643
644 \sa text
645*/
646void QAction::setMenuText( const QString& text )
647{
648 if ( d->menutext == text )
649 return;
650
651 d->menutext = text;
652 d->update();
653}
654
655QString QAction::menuText() const
656{
657 return d->menuText();
658}
659
660/*!
661 \property QAction::toolTip
662 \brief the action's tool tip
663
664 This text is used for the tool tip. If no status tip has been set
665 the tool tip will be used for the status tip.
666
667 If no tool tip is specified the action's text is used, and if that
668 hasn't been specified the description text is used as the tool tip
669 text.
670
671 There is no default tool tip text.
672
673 \sa setStatusTip() setAccel()
674*/
675void QAction::setToolTip( const QString& tip )
676{
677 if ( d->tooltip == tip )
678 return;
679
680 d->tooltip = tip;
681 d->update();
682}
683
684QString QAction::toolTip() const
685{
686 return d->toolTip();
687}
688
689/*!
690 \property QAction::statusTip
691 \brief the action's status tip
692
693 The statusTip is displayed on all status bars that this action's
694 toplevel parent widget provides.
695
696 If no status tip is defined, the action uses the tool tip text.
697
698 There is no default statusTip text.
699
700 \sa setStatusTip() setToolTip()
701*/
702//#### Please reimp for QActionGroup!
703//#### For consistency reasons even action groups should show
704//#### status tips (as they already do with tool tips)
705//#### Please change QActionGroup class doc appropriately after
706//#### reimplementation.
707void QAction::setStatusTip( const QString& tip )
708{
709 if ( d->statustip == tip )
710 return;
711
712 d->statustip = tip;
713 d->update();
714}
715
716QString QAction::statusTip() const
717{
718 return d->statusTip();
719}
720
721/*!
722 \property QAction::whatsThis
723 \brief the action's "What's This?" help text
724
725 The whats this text is used to provide a brief description of the
726 action. The text may contain rich text (HTML-like tags -- see
727 QStyleSheet for the list of supported tags). There is no default
728 "What's This" text.
729
730 \sa QWhatsThis
731*/
732void QAction::setWhatsThis( const QString& whatsThis )
733{
734 if ( d->whatsthis == whatsThis )
735 return;
736 d->whatsthis = whatsThis;
737 d->update();
738}
739
740QString QAction::whatsThis() const
741{
742 return d->whatsthis;
743}
744
745
746#ifndef QT_NO_ACCEL
747/*!
748 \property QAction::accel
749 \brief the action's accelerator key
750
751 The keycodes can be found in \l Qt::Key and \l Qt::Modifier. There
752 is no default accelerator key.
753*/
754//#### Please reimp for QActionGroup!
755//#### For consistency reasons even QActionGroups should respond to
756//#### their accelerators and e.g. open the relevant submenu.
757//#### Please change appropriate QActionGroup class doc after
758//#### reimplementation.
759void QAction::setAccel( const QKeySequence& key )
760{
761 if ( d->key == key )
762 return;
763
764 d->key = key;
765 delete d->accel;
766 d->accel = 0;
767
768 if ( !(int)key ) {
769 d->update();
770 return;
771 }
772
773 QObject* p = parent();
774 while ( p && !p->isWidgetType() ) {
775 p = p->parent();
776 }
777 if ( p ) {
778 d->accel = new QAccel( (QWidget*)p, this, "qt_action_accel" );
779 d->accelid = d->accel->insertItem( d->key );
780 d->accel->connectItem( d->accelid, this, SLOT( internalActivation() ) );
781 }
782#if defined(QT_CHECK_STATE)
783 else
784 qWarning( "QAction::setAccel() (%s) requires widget in parent chain", name() );
785#endif
786 d->update();
787}
788
789
790QKeySequence QAction::accel() const
791{
792 return d->key;
793}
794#endif
795
796
797/*!
798 \property QAction::toggleAction
799 \brief whether the action is a toggle action
800
801 A toggle action is one which has an on/off state. For example a
802 Bold toolbar button is either on or off. An action which is not a
803 toggle action is a command action; a command action is simply
804 executed, e.g. file save. This property's default is FALSE.
805
806 In some situations, the state of one toggle action should depend
807 on the state of others. For example, "Left Align", "Center" and
808 "Right Align" toggle actions are mutually exclusive. To achieve
809 exclusive toggling, add the relevant toggle actions to a
810 QActionGroup with the \l QActionGroup::exclusive property set to
811 TRUE.
812*/
813void QAction::setToggleAction( bool enable )
814{
815 if ( enable == (bool)d->toggleaction )
816 return;
817
818 if ( !enable )
819 d->on = FALSE;
820
821 d->toggleaction = enable;
822 d->update();
823}
824
825bool QAction::isToggleAction() const
826{
827 return d->toggleaction;
828}
829
830/*!
831 Activates the action and executes all connected slots.
832 This only works for actions that are not toggle action.
833
834 \sa toggle()
835*/
836void QAction::activate()
837{
838 if ( isToggleAction() ) {
839#if defined(QT_CHECK_STATE)
840 qWarning( "QAction::%s() (%s) Toggle actions "
841 "can not be activated", "activate", name() );
842#endif
843 return;
844 }
845 emit activated();
846}
847
848/*!
849 Toggles the state of a toggle action.
850
851 \sa on, activate(), toggled(), isToggleAction()
852*/
853void QAction::toggle()
854{
855 if ( !isToggleAction() ) {
856#if defined(QT_CHECK_STATE)
857 qWarning( "QAction::%s() (%s) Only toggle actions "
858 "can be switched", "toggle", name() );
859#endif
860 return;
861 }
862 setOn( !isOn() );
863}
864
865/*!
866 \property QAction::on
867 \brief whether a toggle action is on
868
869 This property is always on (TRUE) for command actions and
870 \l{QActionGroup}s; setOn() has no effect on them. For action's
871 where isToggleAction() is TRUE, this property's default value is
872 off (FALSE).
873
874 \sa toggleAction
875*/
876void QAction::setOn( bool enable )
877{
878 if ( !isToggleAction() ) {
879#if defined(QT_CHECK_STATE)
880 if ( enable )
881 qWarning( "QAction::%s() (%s) Only toggle actions "
882 "can be switched", "setOn", name() );
883#endif
884 return;
885 }
886 if ( enable == (bool)d->on )
887 return;
888 d->on = enable;
889 d->update( QActionPrivate::State );
890 emit toggled( enable );
891}
892
893bool QAction::isOn() const
894{
895 return d->on;
896}
897
898/*!
899 \property QAction::enabled
900 \brief whether the action is enabled
901
902 Disabled actions can't be chosen by the user. They don't disappear
903 from the menu/tool bar but are displayed in a way which indicates
904 that they are unavailable, e.g. they might be displayed grayed
905 out.
906
907 What's this? help on disabled actions is still available provided
908 the \l QAction::whatsThis property is set.
909*/
910void QAction::setEnabled( bool enable )
911{
912 d->forceDisabled = !enable;
913
914 if ( (bool)d->enabled == enable )
915 return;
916
917 d->enabled = enable;
918 d->update( QActionPrivate::State );
919}
920
921bool QAction::isEnabled() const
922{
923 return d->enabled;
924}
925
926/*!
927 Disables the action if \a disable is TRUE; otherwise
928 enables the action.
929
930 See the \l enabled documentation for more information.
931*/
932void QAction::setDisabled( bool disable )
933{
934 setEnabled( !disable );
935}
936
937/*!
938 \property QAction::visible
939 \brief whether the action can be seen (e.g. in menus and toolbars)
940
941 If \e visible is TRUE the action can be seen (e.g. in menus and
942 toolbars) and chosen by the user; if \e visible is FALSE the
943 action cannot be seen or chosen by the user.
944
945 Actions which are not visible are \e not grayed out; they do not
946 appear at all.
947*/
948void QAction::setVisible( bool visible )
949{
950 if ( (bool)d->visible == visible )
951 return;
952 d->visible = visible;
953 d->update( QActionPrivate::Visibility );
954#if (QT_VERSION-0 >= 0x040000)
955#error "QAction::setVisible function wants to be virtual. Also add virtual change() function"
956#endif
957 if ( d->d_group ) //### this function wants to be virtual in 4.0
958 d->d_group->update( (QActionGroup*) this );
959}
960
961/*
962 Returns TRUE if the action is visible (e.g. in menus and
963 toolbars); otherwise returns FALSE.
964*/
965bool QAction::isVisible() const
966{
967 return d->visible;
968}
969
970/*! \internal
971*/
972void QAction::internalActivation()
973{
974 if ( isToggleAction() )
975 setOn( !isOn() );
976 emit activated();
977}
978
979/*! \internal
980*/
981void QAction::toolButtonToggled( bool on )
982{
983 if ( !isToggleAction() )
984 return;
985 setOn( on );
986}
987
988/*!
989 Adds this action to widget \a w.
990
991 Currently actions may be added to QToolBar and QPopupMenu widgets.
992
993 An action added to a tool bar is automatically displayed as a tool
994 button; an action added to a pop up menu appears as a menu option.
995
996 addTo() returns TRUE if the action was added successfully and
997 FALSE otherwise. (If \a w is not a QToolBar or QPopupMenu the
998 action will not be added and FALSE will be returned.)
999
1000 \sa removeFrom()
1001*/
1002bool QAction::addTo( QWidget* w )
1003{
1004#ifndef QT_NO_TOOLBAR
1005 if ( ::qt_cast<QToolBar*>(w) ) {
1006 if ( !qstrcmp( name(), "qt_separator_action" ) ) {
1007 ((QToolBar*)w)->addSeparator();
1008 } else {
1009 QCString bname = name() + QCString( "_action_button" );
1010 QToolButton* btn = new QToolButton( (QToolBar*) w, bname );
1011 addedTo( btn, w );
1012 btn->setToggleButton( d->toggleaction );
1013 d->toolbuttons.append( btn );
1014 if ( d->iconset )
1015 btn->setIconSet( *d->iconset );
1016 d->update( QActionPrivate::State | QActionPrivate::Visibility | QActionPrivate::EverythingElse ) ;
1017 connect( btn, SIGNAL( clicked() ), this, SIGNAL( activated() ) );
1018 connect( btn, SIGNAL( toggled(bool) ), this, SLOT( toolButtonToggled(bool) ) );
1019 connect( btn, SIGNAL( destroyed() ), this, SLOT( objectDestroyed() ) );
1020#ifndef QT_NO_TOOLTIP
1021 connect( &(d->tipGroup), SIGNAL(showTip(const QString&)), this, SLOT(showStatusText(const QString&)) );
1022 connect( &(d->tipGroup), SIGNAL(removeTip()), this, SLOT(clearStatusText()) );
1023#endif
1024 }
1025 } else
1026#endif
1027 if ( ::qt_cast<QPopupMenu*>(w) ) {
1028 QActionPrivate::MenuItem* mi = new QActionPrivate::MenuItem;
1029 mi->popup = (QPopupMenu*) w;
1030 QIconSet* diconset = d->iconset;
1031 if ( !qstrcmp( name(), "qt_separator_action" ) )
1032 mi->id = ((QPopupMenu*)w)->insertSeparator();
1033 else if ( diconset )
1034 mi->id = mi->popup->insertItem( *diconset, QString::fromLatin1("") );
1035 else
1036 mi->id = mi->popup->insertItem( QString::fromLatin1("") );
1037 addedTo( mi->popup->indexOf( mi->id ), mi->popup );
1038 mi->popup->connectItem( mi->id, this, SLOT(internalActivation()) );
1039 d->menuitems.append( mi );
1040 d->update( QActionPrivate::State | QActionPrivate::Visibility | QActionPrivate::EverythingElse ) ;
1041 w->topLevelWidget()->className();
1042 connect( mi->popup, SIGNAL(highlighted(int)), this, SLOT(menuStatusText(int)) );
1043 connect( mi->popup, SIGNAL(aboutToHide()), this, SLOT(clearStatusText()) );
1044 connect( mi->popup, SIGNAL( destroyed() ), this, SLOT( objectDestroyed() ) );
1045 // Makes only sense when called by QActionGroup::addTo
1046 } else if ( ::qt_cast<QComboBox*>(w) ) {
1047 QActionPrivate::ComboItem *ci = new QActionPrivate::ComboItem;
1048 ci->combo = (QComboBox*)w;
1049 connect( ci->combo, SIGNAL( destroyed() ), this, SLOT( objectDestroyed() ) );
1050 ci->id = ci->combo->count();
1051 if ( qstrcmp( name(), "qt_separator_action" ) ) {
1052 if ( d->iconset )
1053 ci->combo->insertItem( d->iconset->pixmap(), text() );
1054 else
1055 ci->combo->insertItem( text() );
1056 } else {
1057 ci->id = -1;
1058 }
1059 d->comboitems.append( ci );
1060
1061 d->update( QActionPrivate::State | QActionPrivate::EverythingElse );
1062 } else {
1063 qWarning( "QAction::addTo(), unknown object" );
1064 return FALSE;
1065 }
1066 return TRUE;
1067}
1068
1069/*!
1070 This function is called from the addTo() function when it has
1071 created a widget (\a actionWidget) for the action in the \a
1072 container.
1073*/
1074
1075void QAction::addedTo( QWidget *actionWidget, QWidget *container )
1076{
1077 Q_UNUSED( actionWidget );
1078 Q_UNUSED( container );
1079}
1080
1081/*!
1082 \overload
1083
1084 This function is called from the addTo() function when it has
1085 created a menu item at the index position \a index in the popup
1086 menu \a menu.
1087*/
1088
1089void QAction::addedTo( int index, QPopupMenu *menu )
1090{
1091 Q_UNUSED( index );
1092 Q_UNUSED( menu );
1093}
1094
1095/*!
1096 Sets the status message to \a text
1097*/
1098void QAction::showStatusText( const QString& text )
1099{
1100#ifndef QT_NO_STATUSBAR
1101 // find out whether we are clearing the status bar by the popup that actually set the text
1102 static QPopupMenu *lastmenu = 0;
1103 QObject *s = (QObject*)sender();
1104 if ( s ) {
1105 QPopupMenu *menu = (QPopupMenu*)s->qt_cast( "QPopupMenu" );
1106 if ( menu && !!text )
1107 lastmenu = menu;
1108 else if ( menu && text.isEmpty() ) {
1109 if ( lastmenu && menu != lastmenu )
1110 return;
1111 lastmenu = 0;
1112 }
1113 }
1114
1115 QObject* par = parent();
1116 QObject* lpar = 0;
1117 QStatusBar *bar = 0;
1118 while ( par && !bar ) {
1119 lpar = par;
1120 bar = (QStatusBar*)par->child( 0, "QStatusBar", FALSE );
1121 par = par->parent();
1122 }
1123 if ( !bar && lpar ) {
1124 QObjectList *l = lpar->queryList( "QStatusBar" );
1125 if ( !l )
1126 return;
1127 // #### hopefully the last one is the one of the mainwindow...
1128 bar = (QStatusBar*)l->last();
1129 delete l;
1130 }
1131 if ( bar ) {
1132 if ( text.isEmpty() )
1133 bar->clear();
1134 else
1135 bar->message( text );
1136 }
1137#endif
1138}
1139
1140/*!
1141 Sets the status message to the menu item's status text, or to the
1142 tooltip, if there is no status text.
1143*/
1144void QAction::menuStatusText( int id )
1145{
1146 static int lastId = 0;
1147 QString text;
1148 QPtrListIterator<QActionPrivate::MenuItem> it( d->menuitems);
1149 QActionPrivate::MenuItem* mi;
1150 while ( ( mi = it.current() ) ) {
1151 ++it;
1152 if ( mi->id == id ) {
1153 text = statusTip();
1154 break;
1155 }
1156 }
1157
1158 if ( !text.isEmpty() )
1159 showStatusText( text );
1160 else if ( id != lastId )
1161 clearStatusText();
1162 lastId = id;
1163}
1164
1165/*!
1166 Clears the status text.
1167*/
1168void QAction::clearStatusText()
1169{
1170 if (!statusTip().isEmpty())
1171 showStatusText( QString::null );
1172}
1173
1174/*!
1175 Removes the action from widget \a w.
1176
1177 Returns TRUE if the action was removed successfully; otherwise
1178 returns FALSE.
1179
1180 \sa addTo()
1181*/
1182bool QAction::removeFrom( QWidget* w )
1183{
1184#ifndef QT_NO_TOOLBAR
1185 if ( ::qt_cast<QToolBar*>(w) ) {
1186 QPtrListIterator<QToolButton> it( d->toolbuttons);
1187 QToolButton* btn;
1188 while ( ( btn = it.current() ) ) {
1189 ++it;
1190 if ( btn->parentWidget() == w ) {
1191 d->toolbuttons.removeRef( btn );
1192 disconnect( btn, SIGNAL( destroyed() ), this, SLOT( objectDestroyed() ) );
1193 delete btn;
1194 // no need to disconnect from statusbar
1195 }
1196 }
1197 } else
1198#endif
1199 if ( ::qt_cast<QPopupMenu*>(w) ) {
1200 QPtrListIterator<QActionPrivate::MenuItem> it( d->menuitems);
1201 QActionPrivate::MenuItem* mi;
1202 while ( ( mi = it.current() ) ) {
1203 ++it;
1204 if ( mi->popup == w ) {
1205 disconnect( mi->popup, SIGNAL(highlighted(int)), this, SLOT(menuStatusText(int)) );
1206 disconnect( mi->popup, SIGNAL(aboutToHide()), this, SLOT(clearStatusText()) );
1207 disconnect( mi->popup, SIGNAL( destroyed() ), this, SLOT( objectDestroyed() ) );
1208 mi->popup->removeItem( mi->id );
1209 d->menuitems.removeRef( mi );
1210 }
1211 }
1212 } else if ( ::qt_cast<QComboBox*>(w) ) {
1213 QPtrListIterator<QActionPrivate::ComboItem> it( d->comboitems );
1214 QActionPrivate::ComboItem *ci;
1215 while ( ( ci = it.current() ) ) {
1216 ++it;
1217 if ( ci->combo == w ) {
1218 disconnect( ci->combo, SIGNAL(destroyed()), this, SLOT(objectDestroyed()) );
1219 d->comboitems.removeRef( ci );
1220 }
1221 }
1222 } else {
1223 qWarning( "QAction::removeFrom(), unknown object" );
1224 return FALSE;
1225 }
1226 return TRUE;
1227}
1228
1229/*!
1230 \internal
1231*/
1232void QAction::objectDestroyed()
1233{
1234 const QObject* obj = sender();
1235 QPtrListIterator<QActionPrivate::MenuItem> it( d->menuitems );
1236 QActionPrivate::MenuItem* mi;
1237 while ( ( mi = it.current() ) ) {
1238 ++it;
1239 if ( mi->popup == obj )
1240 d->menuitems.removeRef( mi );
1241 }
1242 QActionPrivate::ComboItem *ci;
1243 QPtrListIterator<QActionPrivate::ComboItem> it2( d->comboitems );
1244 while ( ( ci = it2.current() ) ) {
1245 ++it2;
1246 if ( ci->combo == obj )
1247 d->comboitems.removeRef( ci );
1248 }
1249 d->toolbuttons.removeRef( (QToolButton*) obj );
1250}
1251
1252/*!
1253 \fn void QAction::activated()
1254
1255 This signal is emitted when an action is activated by the user,
1256 e.g. when the user clicks a menu option or a toolbar button or
1257 presses an action's accelerator key combination.
1258
1259 Connect to this signal for command actions. Connect to the
1260 toggled() signal for toggle actions.
1261*/
1262
1263/*!
1264 \fn void QAction::toggled(bool on)
1265
1266 This signal is emitted when a toggle action changes state; command
1267 actions and \l{QActionGroup}s don't emit toggled().
1268
1269 The \a on argument denotes the new state: If \a on is TRUE the
1270 toggle action is switched on, and if \a on is FALSE the toggle
1271 action is switched off.
1272
1273 To trigger a user command depending on whether a toggle action has
1274 been switched on or off connect it to a slot that takes a bool to
1275 indicate the state, e.g.
1276
1277 \quotefile action/toggleaction/toggleaction.cpp
1278 \skipto QMainWindow * window
1279 \printline QMainWindow * window
1280 \skipto labelonoffaction
1281 \printline labelonoffaction
1282 \skipto connect
1283 \printuntil setUsesTextLabel
1284
1285 \sa activated() setToggleAction() setOn()
1286*/
1287
1288void QActionGroupPrivate::update( const QActionGroup* that )
1289{
1290 for ( QPtrListIterator<QAction> it( actions ); it.current(); ++it ) {
1291 if ( that->isEnabled() && !it.current()->d->forceDisabled )
1292 it.current()->setEnabled( TRUE );
1293 else if ( !that->isEnabled() && it.current()->isEnabled() ) {
1294 it.current()->setEnabled( FALSE );
1295 it.current()->d->forceDisabled = FALSE;
1296 }
1297 it.current()->setVisible( that->isVisible() );
1298 }
1299 for ( QPtrListIterator<QComboBox> cb( comboboxes ); cb.current(); ++cb ) {
1300 QComboBox *combobox = cb.current();
1301 combobox->setEnabled( that->isEnabled() );
1302 combobox->setShown( that->isVisible() );
1303
1304#ifndef QT_NO_TOOLTIP
1305 QToolTip::remove( combobox );
1306 if ( !!that->toolTip() )
1307 QToolTip::add( combobox, that->toolTip() );
1308#endif
1309#ifndef QT_NO_WHATSTHIS
1310 QWhatsThis::remove( combobox );
1311 if ( !!that->whatsThis() )
1312 QWhatsThis::add( combobox, that->whatsThis() );
1313#endif
1314
1315 }
1316 for ( QPtrListIterator<QToolButton> mb( menubuttons ); mb.current(); ++mb ) {
1317 QToolButton *button = mb.current();
1318 button->setEnabled( that->isEnabled() );
1319 button->setShown( that->isVisible() );
1320
1321 if ( !that->text().isNull() )
1322 button->setTextLabel( that->text() );
1323 if ( !that->iconSet().isNull() )
1324 button->setIconSet( that->iconSet() );
1325
1326#ifndef QT_NO_TOOLTIP
1327 QToolTip::remove( mb.current() );
1328 if ( !!that->toolTip() )
1329 QToolTip::add( button, that->toolTip() );
1330#endif
1331#ifndef QT_NO_WHATSTHIS
1332 QWhatsThis::remove( button );
1333 if ( !!that->whatsThis() )
1334 QWhatsThis::add( button, that->whatsThis() );
1335#endif
1336 }
1337 for ( QPtrListIterator<QActionGroupPrivate::MenuItem> pu( menuitems ); pu.current(); ++pu ) {
1338 QWidget* parent = pu.current()->popup->parentWidget();
1339 if ( ::qt_cast<QPopupMenu*>(parent) ) {
1340 QPopupMenu* ppopup = (QPopupMenu*)parent;
1341 ppopup->setItemEnabled( pu.current()->id, that->isEnabled() );
1342 ppopup->setItemVisible( pu.current()->id, that->isVisible() );
1343 } else {
1344 pu.current()->popup->setEnabled( that->isEnabled() );
1345 }
1346 }
1347 for ( QPtrListIterator<QPopupMenu> pm( popupmenus ); pm.current(); ++pm ) {
1348 QPopupMenu *popup = pm.current();
1349 QPopupMenu *parent = ::qt_cast<QPopupMenu*>(popup->parentWidget());
1350 if ( !parent )
1351 continue;
1352
1353 int index;
1354 parent->findPopup( popup, &index );
1355 int id = parent->idAt( index );
1356 if ( !that->iconSet().isNull() )
1357 parent->changeItem( id, that->iconSet(), that->menuText() );
1358 else
1359 parent->changeItem( id, that->menuText() );
1360 parent->setItemEnabled( id, that->isEnabled() );
1361#ifndef QT_NO_ACCEL
1362 parent->setAccel( that->accel(), id );
1363#endif
1364 }
1365}
1366
1367/*!
1368 \class QActionGroup qaction.h
1369 \brief The QActionGroup class groups actions together.
1370
1371 \ingroup basic
1372 \ingroup application
1373
1374 In some situations it is useful to group actions together. For
1375 example, if you have a left justify action, a right justify action
1376 and a center action, only one of these actions should be active at
1377 any one time, and one simple way of achieving this is to group the
1378 actions together in an action group.
1379
1380 An action group can also be added to a menu or a toolbar as a
1381 single unit, with all the actions within the action group
1382 appearing as separate menu options and toolbar buttons.
1383
1384 Here's an example from examples/textedit:
1385 \quotefile textedit/textedit.cpp
1386 \skipto QActionGroup
1387 \printuntil connect
1388
1389 Here we create a new action group. Since the action group is exclusive
1390 by default, only one of the actions in the group is ever active at any
1391 one time. We then connect the group's selected() signal to our
1392 textAlign() slot.
1393
1394 \printuntil actionAlignLeft->setToggleAction
1395
1396 We create a left align action, add it to the toolbar and the menu
1397 and make it a toggle action. We create center and right align
1398 actions in exactly the same way.
1399
1400 \omit
1401 A QActionGroup emits an activated() signal when one of its actions
1402 is activated.
1403 \endomit
1404 The actions in an action group emit their activated() (and for
1405 toggle actions, toggled()) signals as usual.
1406
1407 The setExclusive() function is used to ensure that only one action
1408 is active at any one time: it should be used with actions which
1409 have their \c toggleAction set to TRUE.
1410
1411 Action group actions appear as individual menu options and toolbar
1412 buttons. For exclusive action groups use setUsesDropDown() to
1413 display the actions in a subwidget of any widget the action group
1414 is added to. For example, the actions would appear in a combobox
1415 in a toolbar or as a submenu in a menu.
1416
1417 Actions can be added to an action group using add(), but normally
1418 they are added by creating the action with the action group as
1419 parent. Actions can have separators dividing them using
1420 addSeparator(). Action groups are added to widgets with addTo().
1421*/
1422
1423/*!
1424 Constructs an action group called \a name, with parent \a parent.
1425
1426 The action group is exclusive by default. Call setExclusive(FALSE) to make
1427 the action group non-exclusive.
1428*/
1429QActionGroup::QActionGroup( QObject* parent, const char* name )
1430 : QAction( parent, name )
1431{
1432 d = new QActionGroupPrivate;
1433 d->exclusive = TRUE;
1434 d->dropdown = FALSE;
1435 d->selected = 0;
1436 d->separatorAction = 0;
1437 QAction::d->d_group = d;
1438
1439 connect( this, SIGNAL(selected(QAction*)), SLOT(internalToggle(QAction*)) );
1440}
1441
1442/*!
1443 Constructs an action group called \a name, with parent \a parent.
1444
1445 If \a exclusive is TRUE only one toggle action in the group will
1446 ever be active.
1447
1448 \sa exclusive
1449*/
1450QActionGroup::QActionGroup( QObject* parent, const char* name, bool exclusive )
1451 : QAction( parent, name )
1452{
1453 d = new QActionGroupPrivate;
1454 d->exclusive = exclusive;
1455 d->dropdown = FALSE;
1456 d->selected = 0;
1457 d->separatorAction = 0;
1458 QAction::d->d_group = d;
1459
1460 connect( this, SIGNAL(selected(QAction*)), SLOT(internalToggle(QAction*)) );
1461}
1462
1463/*!
1464 Destroys the object and frees allocated resources.
1465*/
1466
1467QActionGroup::~QActionGroup()
1468{
1469 QPtrListIterator<QActionGroupPrivate::MenuItem> mit( d->menuitems );
1470 while ( mit.current() ) {
1471 QActionGroupPrivate::MenuItem *mi = mit.current();
1472 ++mit;
1473 if ( mi->popup )
1474 mi->popup->disconnect( SIGNAL(destroyed()), this, SLOT(objectDestroyed()) );
1475 }
1476
1477 QPtrListIterator<QComboBox> cbit( d->comboboxes );
1478 while ( cbit.current() ) {
1479 QComboBox *cb = cbit.current();
1480 ++cbit;
1481 cb->disconnect( SIGNAL(destroyed()), this, SLOT(objectDestroyed()) );
1482 }
1483 QPtrListIterator<QToolButton> mbit( d->menubuttons );
1484 while ( mbit.current() ) {
1485 QToolButton *mb = mbit.current();
1486 ++mbit;
1487 mb->disconnect( SIGNAL(destroyed()), this, SLOT(objectDestroyed()) );
1488 }
1489 QPtrListIterator<QPopupMenu> pmit( d->popupmenus );
1490 while ( pmit.current() ) {
1491 QPopupMenu *pm = pmit.current();
1492 ++pmit;
1493 pm->disconnect( SIGNAL(destroyed()), this, SLOT(objectDestroyed()) );
1494 }
1495
1496 delete d->separatorAction;
1497 d->menubuttons.setAutoDelete( TRUE );
1498 d->comboboxes.setAutoDelete( TRUE );
1499 d->menuitems.setAutoDelete( TRUE );
1500 d->popupmenus.setAutoDelete( TRUE );
1501 delete d;
1502}
1503
1504/*!
1505 \property QActionGroup::exclusive
1506 \brief whether the action group does exclusive toggling
1507
1508 If exclusive is TRUE only one toggle action in the action group
1509 can ever be active at any one time. If the user chooses another
1510 toggle action in the group the one they chose becomes active and
1511 the one that was active becomes inactive.
1512
1513 \sa QAction::toggleAction
1514*/
1515void QActionGroup::setExclusive( bool enable )
1516{
1517 d->exclusive = enable;
1518}
1519
1520bool QActionGroup::isExclusive() const
1521{
1522 return d->exclusive;
1523}
1524
1525/*!
1526 \property QActionGroup::usesDropDown
1527 \brief whether the group's actions are displayed in a subwidget of
1528 the widgets the action group is added to
1529
1530 Exclusive action groups added to a toolbar display their actions
1531 in a combobox with the action's \l QAction::text and \l
1532 QAction::iconSet properties shown. Non-exclusive groups are
1533 represented by a tool button showing their \l QAction::iconSet and
1534 -- depending on \l QMainWindow::usesTextLabel() -- text()
1535 property.
1536
1537 In a popup menu the member actions are displayed in a submenu.
1538
1539 Changing usesDropDown only affects \e subsequent calls to addTo().
1540
1541 This property's default is FALSE.
1542
1543*/
1544void QActionGroup::setUsesDropDown( bool enable )
1545{
1546 d->dropdown = enable;
1547}
1548
1549bool QActionGroup::usesDropDown() const
1550{
1551 return d->dropdown;
1552}
1553
1554/*!
1555 Adds action \a action to this group.
1556
1557 Normally an action is added to a group by creating it with the
1558 group as parent, so this function is not usually used.
1559
1560 \sa addTo()
1561*/
1562void QActionGroup::add( QAction* action )
1563{
1564 if ( d->actions.containsRef( action ) )
1565 return;
1566
1567 d->actions.append( action );
1568
1569 if ( action->whatsThis().isNull() )
1570 action->setWhatsThis( whatsThis() );
1571 if ( action->toolTip().isNull() )
1572 action->setToolTip( toolTip() );
1573 action->d->enabled = isEnabled();
1574 action->d->visible = isVisible();
1575
1576 connect( action, SIGNAL( destroyed() ), this, SLOT( childDestroyed() ) );
1577 connect( action, SIGNAL( activated() ), this, SIGNAL( activated() ) );
1578 connect( action, SIGNAL( toggled(bool) ), this, SLOT( childToggled(bool) ) );
1579
1580 for ( QPtrListIterator<QComboBox> cb( d->comboboxes ); cb.current(); ++cb ) {
1581 action->addTo( cb.current() );
1582 }
1583 for ( QPtrListIterator<QToolButton> mb( d->menubuttons ); mb.current(); ++mb ) {
1584 QPopupMenu* popup = mb.current()->popup();
1585 if ( !popup )
1586 continue;
1587 action->addTo( popup );
1588 }
1589 for ( QPtrListIterator<QActionGroupPrivate::MenuItem> mi( d->menuitems ); mi.current(); ++mi ) {
1590 QPopupMenu* popup = mi.current()->popup;
1591 if ( !popup )
1592 continue;
1593 action->addTo( popup );
1594 }
1595}
1596
1597/*!
1598 Adds a separator to the group.
1599*/
1600void QActionGroup::addSeparator()
1601{
1602 if ( !d->separatorAction )
1603 d->separatorAction = new QAction( 0, "qt_separator_action" );
1604 d->actions.append( d->separatorAction );
1605}
1606
1607
1608/*! \fn void QActionGroup::insert( QAction* a )
1609
1610 \obsolete
1611
1612 Use add() instead, or better still create the action with the action
1613 group as its parent.
1614 */
1615
1616/*!
1617 Adds this action group to the widget \a w.
1618
1619 If isExclusive() is FALSE or usesDropDown() is FALSE, the actions within
1620 the group are added to the widget individually. For example, if the widget
1621 is a menu, the actions will appear as individual menu options, and
1622 if the widget is a toolbar, the actions will appear as toolbar buttons.
1623
1624 If both isExclusive() and usesDropDown() are TRUE, the actions
1625 are presented either in a combobox (if \a w is a toolbar) or in a
1626 submenu (if \a w is a menu).
1627
1628 All actions should be added to the action group \e before the
1629 action group is added to the widget. If actions are added to the
1630 action group \e after the action group has been added to the
1631 widget these later actions will \e not appear.
1632
1633 \sa setExclusive() setUsesDropDown() removeFrom()
1634*/
1635bool QActionGroup::addTo( QWidget* w )
1636{
1637#ifndef QT_NO_TOOLBAR
1638 if ( ::qt_cast<QToolBar*>(w) ) {
1639 if ( d->dropdown ) {
1640 if ( !d->exclusive ) {
1641 QPtrListIterator<QAction> it( d->actions);
1642 if ( !it.current() )
1643 return TRUE;
1644
1645 QAction *defAction = it.current();
1646
1647 QToolButton* btn = new QToolButton( (QToolBar*) w, "qt_actiongroup_btn" );
1648 addedTo( btn, w );
1649 connect( btn, SIGNAL(destroyed()), SLOT(objectDestroyed()) );
1650 d->menubuttons.append( btn );
1651
1652 if ( !iconSet().isNull() )
1653 btn->setIconSet( iconSet() );
1654 else if ( !defAction->iconSet().isNull() )
1655 btn->setIconSet( defAction->iconSet() );
1656 if ( !!text() )
1657 btn->setTextLabel( text() );
1658 else if ( !!defAction->text() )
1659 btn->setTextLabel( defAction->text() );
1660#ifndef QT_NO_TOOLTIP
1661 if ( !!toolTip() )
1662 QToolTip::add( btn, toolTip() );
1663 else if ( !!defAction->toolTip() )
1664 QToolTip::add( btn, defAction->toolTip() );
1665#endif
1666#ifndef QT_NO_WHATSTHIS
1667 if ( !!whatsThis() )
1668 QWhatsThis::add( btn, whatsThis() );
1669 else if ( !!defAction->whatsThis() )
1670 QWhatsThis::add( btn, defAction->whatsThis() );
1671#endif
1672
1673 connect( btn, SIGNAL( clicked() ), defAction, SIGNAL( activated() ) );
1674 connect( btn, SIGNAL( toggled(bool) ), defAction, SLOT( toolButtonToggled(bool) ) );
1675 connect( btn, SIGNAL( destroyed() ), defAction, SLOT( objectDestroyed() ) );
1676
1677 QPopupMenu *menu = new QPopupMenu( btn, "qt_actiongroup_menu" );
1678 btn->setPopupDelay( 0 );
1679 btn->setPopup( menu );
1680
1681 while( it.current() ) {
1682 it.current()->addTo( menu );
1683 ++it;
1684 }
1685 d->update( this );
1686 return TRUE;
1687 } else {
1688 QComboBox *box = new QComboBox( FALSE, w, "qt_actiongroup_combo" );
1689 addedTo( box, w );
1690 connect( box, SIGNAL(destroyed()), SLOT(objectDestroyed()) );
1691 d->comboboxes.append( box );
1692#ifndef QT_NO_TOOLTIP
1693 if ( !!toolTip() )
1694 QToolTip::add( box, toolTip() );
1695#endif
1696#ifndef QT_NO_WHATSTHIS
1697 if ( !!whatsThis() )
1698 QWhatsThis::add( box, whatsThis() );
1699#endif
1700
1701 int onIndex = 0;
1702 bool foundOn = FALSE;
1703 for ( QPtrListIterator<QAction> it( d->actions); it.current(); ++it ) {
1704 QAction *action = it.current();
1705 if ( !foundOn )
1706 foundOn = action->isOn();
1707 if ( qstrcmp( action->name(), "qt_separator_action" ) && !foundOn )
1708 onIndex++;
1709 action->addTo( box );
1710 }
1711 if ( foundOn )
1712 box->setCurrentItem( onIndex );
1713 connect( box, SIGNAL(activated(int)), this, SLOT( internalComboBoxActivated(int)) );
1714 connect( box, SIGNAL(highlighted(int)), this, SLOT( internalComboBoxHighlighted(int)) );
1715 d->update( this );
1716 return TRUE;
1717 }
1718 }
1719 } else
1720#endif
1721 if ( ::qt_cast<QPopupMenu*>(w) ) {
1722 QPopupMenu *popup;
1723 if ( d->dropdown ) {
1724 QPopupMenu *menu = (QPopupMenu*)w;
1725 popup = new QPopupMenu( w, "qt_actiongroup_menu" );
1726 d->popupmenus.append( popup );
1727 connect( popup, SIGNAL(destroyed()), SLOT(objectDestroyed()) );
1728
1729 int id;
1730 if ( !iconSet().isNull() ) {
1731 if ( menuText().isEmpty() )
1732 id = menu->insertItem( iconSet(), text(), popup );
1733 else
1734 id = menu->insertItem( iconSet(), menuText(), popup );
1735 } else {
1736 if ( menuText().isEmpty() )
1737 id = menu->insertItem( text(), popup );
1738 else
1739 id = menu->insertItem( menuText(), popup );
1740 }
1741
1742 addedTo( menu->indexOf( id ), menu );
1743
1744 QActionGroupPrivate::MenuItem *item = new QActionGroupPrivate::MenuItem;
1745 item->id = id;
1746 item->popup = popup;
1747 d->menuitems.append( item );
1748 } else {
1749 popup = (QPopupMenu*)w;
1750 }
1751 for ( QPtrListIterator<QAction> it( d->actions); it.current(); ++it ) {
1752 // #### do an addedTo( index, popup, action), need to find out index
1753 it.current()->addTo( popup );
1754 }
1755 return TRUE;
1756 }
1757
1758 for ( QPtrListIterator<QAction> it( d->actions); it.current(); ++it ) {
1759 // #### do an addedTo( index, popup, action), need to find out index
1760 it.current()->addTo( w );
1761 }
1762
1763 return TRUE;
1764}
1765
1766/*! \reimp
1767*/
1768bool QActionGroup::removeFrom( QWidget* w )
1769{
1770 for ( QPtrListIterator<QAction> it( d->actions); it.current(); ++it ) {
1771 it.current()->removeFrom( w );
1772 }
1773
1774#ifndef QT_NO_TOOLBAR
1775 if ( ::qt_cast<QToolBar*>(w) ) {
1776 QPtrListIterator<QComboBox> cb( d->comboboxes );
1777 while( cb.current() ) {
1778 QComboBox *box = cb.current();
1779 ++cb;
1780 if ( box->parentWidget() == w )
1781 delete box;
1782 }
1783 QPtrListIterator<QToolButton> mb( d->menubuttons );
1784 while( mb.current() ) {
1785 QToolButton *btn = mb.current();
1786 ++mb;
1787 if ( btn->parentWidget() == w )
1788 delete btn;
1789 }
1790 } else
1791#endif
1792 if ( ::qt_cast<QPopupMenu*>(w) ) {
1793 QPtrListIterator<QActionGroupPrivate::MenuItem> pu( d->menuitems );
1794 while ( pu.current() ) {
1795 QActionGroupPrivate::MenuItem *mi = pu.current();
1796 ++pu;
1797 if ( d->dropdown && mi->popup )
1798 ( (QPopupMenu*)w )->removeItem( mi->id );
1799 delete mi->popup;
1800 }
1801 }
1802
1803 return TRUE;
1804}
1805
1806/*! \internal
1807*/
1808void QActionGroup::childToggled( bool b )
1809{
1810 if ( !isExclusive() )
1811 return;
1812 QAction* s = (QAction*) sender();
1813 if ( b ) {
1814 if ( s != d->selected ) {
1815 d->selected = s;
1816 for ( QPtrListIterator<QAction> it( d->actions); it.current(); ++it ) {
1817 if ( it.current()->isToggleAction() && it.current() != s )
1818 it.current()->setOn( FALSE );
1819 }
1820 emit activated();
1821 emit selected( s );
1822 } else if ( !s->isToggleAction() ) {
1823 emit activated();
1824 }
1825 } else {
1826 if ( s == d->selected ) {
1827 // at least one has to be selected
1828 s->setOn( TRUE );
1829 }
1830 }
1831}
1832
1833/*! \internal
1834*/
1835void QActionGroup::childDestroyed()
1836{
1837 d->actions.removeRef( (QAction*) sender() );
1838 if ( d->selected == sender() )
1839 d->selected = 0;
1840}
1841
1842/*! \reimp
1843*/
1844void QActionGroup::setEnabled( bool enable )
1845{
1846 if ( enable == isEnabled() )
1847 return;
1848
1849 QAction::setEnabled( enable );
1850 d->update( this );
1851}
1852
1853/*! \reimp
1854*/
1855void QActionGroup::setToggleAction( bool toggle )
1856{
1857 for ( QPtrListIterator<QAction> it( d->actions); it.current(); ++it )
1858 it.current()->setToggleAction( toggle );
1859
1860 QAction::setToggleAction( TRUE );
1861 d->update( this );
1862}
1863
1864/*! \reimp
1865*/
1866void QActionGroup::setOn( bool on )
1867{
1868 for ( QPtrListIterator<QAction> it( d->actions); it.current(); ++it ) {
1869 QAction *act = it.current();
1870 if ( act->isToggleAction() )
1871 act->setOn( on );
1872 }
1873
1874 QAction::setOn( on );
1875 d->update( this );
1876}
1877
1878/*! \reimp
1879*/
1880void QActionGroup::setIconSet( const QIconSet& icon )
1881{
1882 QAction::setIconSet( icon );
1883 d->update( this );
1884}
1885
1886/*! \reimp
1887*/
1888void QActionGroup::setText( const QString& txt )
1889{
1890 if ( txt == text() )
1891 return;
1892
1893 QAction::setText( txt );
1894 d->update( this );
1895}
1896
1897/*! \reimp
1898*/
1899void QActionGroup::setMenuText( const QString& text )
1900{
1901 if ( text == menuText() )
1902 return;
1903
1904 QAction::setMenuText( text );
1905 d->update( this );
1906}
1907
1908/*! \reimp
1909*/
1910void QActionGroup::setToolTip( const QString& text )
1911{
1912 if ( text == toolTip() )
1913 return;
1914 for ( QPtrListIterator<QAction> it( d->actions); it.current(); ++it ) {
1915 if ( it.current()->toolTip().isNull() )
1916 it.current()->setToolTip( text );
1917 }
1918 QAction::setToolTip( text );
1919 d->update( this );
1920}
1921
1922/*! \reimp
1923*/
1924void QActionGroup::setWhatsThis( const QString& text )
1925{
1926 if ( text == whatsThis() )
1927 return;
1928 for ( QPtrListIterator<QAction> it( d->actions); it.current(); ++it ) {
1929 if ( it.current()->whatsThis().isNull() )
1930 it.current()->setWhatsThis( text );
1931 }
1932 QAction::setWhatsThis( text );
1933 d->update( this );
1934}
1935
1936/*! \reimp
1937*/
1938void QActionGroup::childEvent( QChildEvent *e )
1939{
1940 if ( !e->removed() )
1941 return;
1942
1943 QAction *action = ::qt_cast<QAction*>(e->child());
1944 if ( !action )
1945 return;
1946
1947 for ( QPtrListIterator<QComboBox> cb( d->comboboxes ); cb.current(); ++cb ) {
1948 for ( int i = 0; i < cb.current()->count(); i++ ) {
1949 if ( cb.current()->text( i ) == action->text() ) {
1950 cb.current()->removeItem( i );
1951 break;
1952 }
1953 }
1954 }
1955 for ( QPtrListIterator<QToolButton> mb( d->menubuttons ); mb.current(); ++mb ) {
1956 QPopupMenu* popup = mb.current()->popup();
1957 if ( !popup )
1958 continue;
1959 action->removeFrom( popup );
1960 }
1961 for ( QPtrListIterator<QActionGroupPrivate::MenuItem> mi( d->menuitems ); mi.current(); ++mi ) {
1962 QPopupMenu* popup = mi.current()->popup;
1963 if ( !popup )
1964 continue;
1965 action->removeFrom( popup );
1966 }
1967}
1968
1969/*!
1970 \fn void QActionGroup::selected( QAction* )
1971
1972 This signal is emitted from exclusive groups when toggle actions
1973 change state.
1974
1975 The argument is the action whose state changed to "on".
1976
1977 \sa setExclusive(), isOn() QAction::toggled()
1978*/
1979
1980/*! \internal
1981*/
1982void QActionGroup::internalComboBoxActivated( int index )
1983{
1984 QAction *a = 0;
1985 for ( int i = 0; i <= index && i < (int)d->actions.count(); ++i ) {
1986 a = d->actions.at( i );
1987 if ( a && !qstrcmp( a->name(), "qt_separator_action" ) )
1988 index++;
1989 }
1990 a = d->actions.at( index );
1991 if ( a ) {
1992 if ( a != d->selected ) {
1993 d->selected = a;
1994 for ( QPtrListIterator<QAction> it( d->actions); it.current(); ++it ) {
1995 if ( it.current()->isToggleAction() && it.current() != a )
1996 it.current()->setOn( FALSE );
1997 }
1998 if ( a->isToggleAction() )
1999 a->setOn( TRUE );
2000
2001 emit activated();
2002 if ( a->isToggleAction() )
2003 emit selected( d->selected );
2004 emit ((QActionGroup*)a)->activated();
2005 } else if ( !a->isToggleAction() ) {
2006 emit activated();
2007 emit ((QActionGroup*)a)->activated();
2008 }
2009 a->clearStatusText();
2010 }
2011}
2012
2013/*! \internal
2014*/
2015void QActionGroup::internalComboBoxHighlighted( int index )
2016{
2017 QAction *a = 0;
2018 for ( int i = 0; i <= index && i < (int)d->actions.count(); ++i ) {
2019 a = d->actions.at( i );
2020 if ( a && !qstrcmp( a->name(), "qt_separator_action" ) )
2021 index++;
2022 }
2023 a = d->actions.at( index );
2024 if ( a )
2025 a->showStatusText(a->statusTip());
2026 else
2027 clearStatusText();
2028}
2029
2030/*! \internal
2031*/
2032void QActionGroup::internalToggle( QAction *a )
2033{
2034 int index = d->actions.find( a );
2035 if ( index == -1 )
2036 return;
2037
2038 int lastItem = index;
2039 for ( int i = 0; i < lastItem; i++ ) {
2040 QAction *action = d->actions.at( i );
2041 if ( !qstrcmp( action->name(), "qt_separator_action" ) )
2042 index--;
2043 }
2044
2045 for ( QPtrListIterator<QComboBox> it( d->comboboxes); it.current(); ++it )
2046 it.current()->setCurrentItem( index );
2047}
2048
2049/*! \internal
2050*/
2051void QActionGroup::objectDestroyed()
2052{
2053 const QObject* obj = sender();
2054 d->menubuttons.removeRef( (QToolButton*)obj );
2055 for ( QPtrListIterator<QActionGroupPrivate::MenuItem> mi( d->menuitems ); mi.current(); ++mi ) {
2056 if ( mi.current()->popup == obj ) {
2057 d->menuitems.removeRef( mi.current() );
2058 break;
2059 }
2060 }
2061 d->popupmenus.removeRef( (QPopupMenu*)obj );
2062 d->comboboxes.removeRef( (QComboBox*)obj );
2063}
2064
2065/*!
2066 This function is called from the addTo() function when it has
2067 created a widget (\a actionWidget) for the child action \a a in
2068 the \a container.
2069*/
2070
2071void QActionGroup::addedTo( QWidget *actionWidget, QWidget *container, QAction *a )
2072{
2073 Q_UNUSED( actionWidget );
2074 Q_UNUSED( container );
2075 Q_UNUSED( a );
2076}
2077
2078/*!
2079 \overload
2080
2081 This function is called from the addTo() function when it has
2082 created a menu item for the child action at the index position \a
2083 index in the popup menu \a menu.
2084*/
2085
2086void QActionGroup::addedTo( int index, QPopupMenu *menu, QAction *a )
2087{
2088 Q_UNUSED( index );
2089 Q_UNUSED( menu );
2090 Q_UNUSED( a );
2091}
2092
2093/*!
2094 \reimp
2095 \overload
2096
2097 This function is called from the addTo() function when it has
2098 created a widget (\a actionWidget) in the \a container.
2099*/
2100
2101void QActionGroup::addedTo( QWidget *actionWidget, QWidget *container )
2102{
2103 Q_UNUSED( actionWidget );
2104 Q_UNUSED( container );
2105}
2106
2107/*!
2108 \reimp
2109 \overload
2110
2111 This function is called from the addTo() function when it has
2112 created a menu item at the index position \a index in the popup
2113 menu \a menu.
2114*/
2115
2116void QActionGroup::addedTo( int index, QPopupMenu *menu )
2117{
2118 Q_UNUSED( index );
2119 Q_UNUSED( menu );
2120}
2121
2122#endif
Note: See TracBrowser for help on using the repository browser.