1 /***************************************************************************
2 * Copyright (C) 2005-08 by the Quassel Project *
3 * devel@quassel-irc.org *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************
20 * Parts of this implementation are based on KDE's KActionCollection. *
21 ***************************************************************************/
25 #include "actioncollection.h"
29 ActionCollection::ActionCollection(QObject *parent) : QObject(parent) {
30 _connectTriggered = _connectHovered = false;
33 ActionCollection::~ActionCollection() {
37 void ActionCollection::clear() {
38 _actionByName.clear();
43 QAction *ActionCollection::action(const QString &name) const {
44 return _actionByName.value(name, 0);
47 QList<QAction *> ActionCollection::actions() const {
51 Action *ActionCollection::addAction(const QString &name, Action *action) {
52 QAction *act = addAction(name, action);
53 Q_ASSERT(act == action);
57 Action *ActionCollection::addAction(const QString &name, const QObject *receiver, const char *member) {
58 Action *a = new Action(this);
59 if(receiver && member)
60 connect(a, SIGNAL(triggered(bool)), receiver, member);
61 return addAction(name, a);
64 QAction *ActionCollection::addAction(const QString &name, QAction *action) {
68 const QString origName = action->objectName();
69 QString indexName = name;
71 if(indexName.isEmpty())
72 indexName = action->objectName();
74 action->setObjectName(indexName);
75 if(indexName.isEmpty())
76 indexName = QString("unnamed-%1").arg((int)action, 16);
78 // do we already have this action?
79 if(_actionByName.value(indexName, 0) == action)
81 // or maybe another action under this name?
82 if(QAction *oldAction = _actionByName.value(indexName))
83 takeAction(oldAction);
85 // do we already have this action under a different name?
86 int oldIndex = _actions.indexOf(action);
88 _actionByName.remove(origName);
89 _actions.removeAt(oldIndex);
93 _actionByName.insert(indexName, action);
94 _actions.append(action);
96 foreach(QWidget *widget, _associatedWidgets) {
97 widget->addAction(action);
100 connect(action, SIGNAL(destroyed(QObject *)), SLOT(actionDestroyed(QObject *)));
102 connect(action, SIGNAL(hovered()), SLOT(slotActionHovered()));
103 if(_connectTriggered)
104 connect(action, SIGNAL(triggered(bool)), SLOT(slotActionTriggered()));
106 emit inserted(action);
110 void ActionCollection::removeAction(QAction *action) {
111 delete takeAction(action);
114 QAction *ActionCollection::takeAction(QAction *action) {
115 if(!unlistAction(action))
118 foreach(QWidget *widget, _associatedWidgets) {
119 widget->removeAction(action);
122 action->disconnect(this);
126 void ActionCollection::readSettings() {
130 void ActionCollection::writeSettings() const {
135 void ActionCollection::slotActionTriggered() {
136 QAction *action = qobject_cast<QAction *>(sender());
138 emit actionTriggered(action);
141 void ActionCollection::slotActionHovered() {
142 QAction *action = qobject_cast<QAction *>(sender());
144 emit actionHovered(action);
147 void ActionCollection::actionDestroyed(QObject *obj) {
148 // remember that this is not an QAction anymore at this point
149 QAction *action = static_cast<QAction *>(obj);
151 unlistAction(action);
154 void ActionCollection::connectNotify(const char *signal) {
155 if(_connectHovered && _connectTriggered)
158 if(QMetaObject::normalizedSignature(SIGNAL(actionHovered(QAction*))) == signal) {
159 if(!_connectHovered) {
160 _connectHovered = true;
161 foreach (QAction* action, actions())
162 connect(action, SIGNAL(hovered()), SLOT(slotActionHovered()));
164 } else if(QMetaObject::normalizedSignature(SIGNAL(actionTriggered(QAction*))) == signal) {
165 if(!_connectTriggered) {
166 _connectTriggered = true;
167 foreach (QAction* action, actions())
168 connect(action, SIGNAL(triggered(bool)), SLOT(slotActionTriggered()));
172 QObject::connectNotify(signal);
175 void ActionCollection::associateWidget(QWidget *widget) const {
176 foreach(QAction *action, actions()) {
177 if(!widget->actions().contains(action))
178 widget->addAction(action);
182 void ActionCollection::addAssociatedWidget(QWidget *widget) {
183 if(!_associatedWidgets.contains(widget)) {
184 widget->addActions(actions());
185 _associatedWidgets.append(widget);
186 connect(widget, SIGNAL(destroyed(QObject *)), SLOT(associatedWidgetDestroyed(QObject *)));
190 void ActionCollection::removeAssociatedWidget(QWidget *widget) {
191 foreach(QAction *action, actions())
192 widget->removeAction(action);
193 _associatedWidgets.removeAll(widget);
194 disconnect(widget, SIGNAL(destroyed(QObject *)), this, SLOT(associatedWidgetDestroyed(QObject *)));
197 QList<QWidget *> ActionCollection::associatedWidgets() const {
198 return _associatedWidgets;
201 void ActionCollection::clearAssociatedWidgets() {
202 foreach(QWidget *widget, _associatedWidgets)
203 foreach(QAction *action, actions())
204 widget->removeAction(action);
206 _associatedWidgets.clear();
209 bool ActionCollection::unlistAction(QAction *action) {
210 // This might be called with a partly destroyed QAction!
212 int index = _actions.indexOf(action);
213 if(index == -1) return false;
215 QString name = action->objectName();
216 _actionByName.remove(name);
217 _actions.removeAt(index);
219 // TODO: remove from ActionCategory if we ever get that