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