1 /***************************************************************************
2 * Copyright (C) 2005-09 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 ***************************************************************************/
28 #include "actioncollection.h"
31 #include "uisettings.h"
33 ActionCollection::ActionCollection(QObject *parent) : QObject(parent) {
34 _connectTriggered = _connectHovered = false;
37 ActionCollection::~ActionCollection() {
41 void ActionCollection::clear() {
42 _actionByName.clear();
47 QAction *ActionCollection::action(const QString &name) const {
48 return _actionByName.value(name, 0);
51 QList<QAction *> ActionCollection::actions() const {
55 Action *ActionCollection::addAction(const QString &name, Action *action) {
56 QAction *act = addAction(name, static_cast<QAction *>(action));
58 Q_ASSERT(act == action);
62 Action *ActionCollection::addAction(const QString &name, const QObject *receiver, const char *member) {
63 Action *a = new Action(this);
64 if(receiver && member)
65 connect(a, SIGNAL(triggered(bool)), receiver, member);
66 return addAction(name, a);
69 QAction *ActionCollection::addAction(const QString &name, QAction *action) {
73 const QString origName = action->objectName();
74 QString indexName = name;
76 if(indexName.isEmpty())
77 indexName = action->objectName();
79 action->setObjectName(indexName);
80 if(indexName.isEmpty())
81 indexName = indexName.sprintf("unnamed-%p", (void *)action);
83 // do we already have this action?
84 if(_actionByName.value(indexName, 0) == action)
86 // or maybe another action under this name?
87 if(QAction *oldAction = _actionByName.value(indexName))
88 takeAction(oldAction);
90 // do we already have this action under a different name?
91 int oldIndex = _actions.indexOf(action);
93 _actionByName.remove(origName);
94 _actions.removeAt(oldIndex);
98 _actionByName.insert(indexName, action);
99 _actions.append(action);
101 foreach(QWidget *widget, _associatedWidgets) {
102 widget->addAction(action);
105 connect(action, SIGNAL(destroyed(QObject *)), SLOT(actionDestroyed(QObject *)));
107 connect(action, SIGNAL(hovered()), SLOT(slotActionHovered()));
108 if(_connectTriggered)
109 connect(action, SIGNAL(triggered(bool)), SLOT(slotActionTriggered()));
111 emit inserted(action);
115 void ActionCollection::removeAction(QAction *action) {
116 delete takeAction(action);
119 QAction *ActionCollection::takeAction(QAction *action) {
120 if(!unlistAction(action))
123 foreach(QWidget *widget, _associatedWidgets) {
124 widget->removeAction(action);
127 action->disconnect(this);
131 void ActionCollection::readSettings() {
133 QStringList savedShortcuts = s.savedShortcuts();
135 foreach(const QString &name, _actionByName.keys()) {
136 if(!savedShortcuts.contains(name))
138 Action *action = qobject_cast<Action *>(_actionByName.value(name));
140 action->setShortcut(s.loadShortcut(name), Action::ActiveShortcut);
144 void ActionCollection::writeSettings() const {
146 foreach(const QString &name, _actionByName.keys()) {
147 Action *action = qobject_cast<Action *>(_actionByName.value(name));
150 if(!action->isShortcutConfigurable())
152 if(action->shortcut(Action::ActiveShortcut) == action->shortcut(Action::DefaultShortcut))
154 s.saveShortcut(name, action->shortcut(Action::ActiveShortcut));
158 void ActionCollection::slotActionTriggered() {
159 QAction *action = qobject_cast<QAction *>(sender());
161 emit actionTriggered(action);
164 void ActionCollection::slotActionHovered() {
165 QAction *action = qobject_cast<QAction *>(sender());
167 emit actionHovered(action);
170 void ActionCollection::actionDestroyed(QObject *obj) {
171 // remember that this is not an QAction anymore at this point
172 QAction *action = static_cast<QAction *>(obj);
174 unlistAction(action);
177 void ActionCollection::connectNotify(const char *signal) {
178 if(_connectHovered && _connectTriggered)
181 if(QMetaObject::normalizedSignature(SIGNAL(actionHovered(QAction*))) == signal) {
182 if(!_connectHovered) {
183 _connectHovered = true;
184 foreach (QAction* action, actions())
185 connect(action, SIGNAL(hovered()), SLOT(slotActionHovered()));
187 } else if(QMetaObject::normalizedSignature(SIGNAL(actionTriggered(QAction*))) == signal) {
188 if(!_connectTriggered) {
189 _connectTriggered = true;
190 foreach (QAction* action, actions())
191 connect(action, SIGNAL(triggered(bool)), SLOT(slotActionTriggered()));
195 QObject::connectNotify(signal);
198 void ActionCollection::associateWidget(QWidget *widget) const {
199 foreach(QAction *action, actions()) {
200 if(!widget->actions().contains(action))
201 widget->addAction(action);
205 void ActionCollection::addAssociatedWidget(QWidget *widget) {
206 if(!_associatedWidgets.contains(widget)) {
207 widget->addActions(actions());
208 _associatedWidgets.append(widget);
209 connect(widget, SIGNAL(destroyed(QObject *)), SLOT(associatedWidgetDestroyed(QObject *)));
213 void ActionCollection::removeAssociatedWidget(QWidget *widget) {
214 foreach(QAction *action, actions())
215 widget->removeAction(action);
216 _associatedWidgets.removeAll(widget);
217 disconnect(widget, SIGNAL(destroyed(QObject *)), this, SLOT(associatedWidgetDestroyed(QObject *)));
220 QList<QWidget *> ActionCollection::associatedWidgets() const {
221 return _associatedWidgets;
224 void ActionCollection::clearAssociatedWidgets() {
225 foreach(QWidget *widget, _associatedWidgets)
226 foreach(QAction *action, actions())
227 widget->removeAction(action);
229 _associatedWidgets.clear();
232 void ActionCollection::associatedWidgetDestroyed(QObject *obj) {
233 _associatedWidgets.removeAll(static_cast<QWidget *>(obj));
236 bool ActionCollection::unlistAction(QAction *action) {
237 // This might be called with a partly destroyed QAction!
239 int index = _actions.indexOf(action);
240 if(index == -1) return false;
242 QString name = action->objectName();
243 _actionByName.remove(name);
244 _actions.removeAt(index);
246 // TODO: remove from ActionCategory if we ever get that
251 #endif /* HAVE_KDE */