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