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