1 /***************************************************************************
2 * Copyright (C) 2005-2014 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 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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)
35 _connectTriggered = _connectHovered = false;
39 ActionCollection::~ActionCollection()
44 void ActionCollection::clear()
46 _actionByName.clear();
52 QAction *ActionCollection::action(const QString &name) const
54 return _actionByName.value(name, 0);
58 QList<QAction *> ActionCollection::actions() const
64 Action *ActionCollection::addAction(const QString &name, Action *action)
66 QAction *act = addAction(name, static_cast<QAction *>(action));
68 Q_ASSERT(act == action);
73 Action *ActionCollection::addAction(const QString &name, const QObject *receiver, const char *member)
75 Action *a = new Action(this);
76 if (receiver && member)
77 connect(a, SIGNAL(triggered(bool)), receiver, member);
78 return addAction(name, a);
82 QAction *ActionCollection::addAction(const QString &name, QAction *action)
87 const QString origName = action->objectName();
88 QString indexName = name;
90 if (indexName.isEmpty())
91 indexName = action->objectName();
93 action->setObjectName(indexName);
94 if (indexName.isEmpty())
95 indexName = indexName.sprintf("unnamed-%p", (void *)action);
97 // do we already have this action?
98 if (_actionByName.value(indexName, 0) == action)
100 // or maybe another action under this name?
101 if (QAction *oldAction = _actionByName.value(indexName))
102 takeAction(oldAction);
104 // do we already have this action under a different name?
105 int oldIndex = _actions.indexOf(action);
106 if (oldIndex != -1) {
107 _actionByName.remove(origName);
108 _actions.removeAt(oldIndex);
112 _actionByName.insert(indexName, action);
113 _actions.append(action);
115 foreach(QWidget *widget, _associatedWidgets) {
116 widget->addAction(action);
119 connect(action, SIGNAL(destroyed(QObject *)), SLOT(actionDestroyed(QObject *)));
121 connect(action, SIGNAL(hovered()), SLOT(slotActionHovered()));
122 if (_connectTriggered)
123 connect(action, SIGNAL(triggered(bool)), SLOT(slotActionTriggered()));
125 emit inserted(action);
130 void ActionCollection::removeAction(QAction *action)
132 delete takeAction(action);
136 QAction *ActionCollection::takeAction(QAction *action)
138 if (!unlistAction(action))
141 foreach(QWidget *widget, _associatedWidgets) {
142 widget->removeAction(action);
145 action->disconnect(this);
150 void ActionCollection::readSettings()
153 QStringList savedShortcuts = s.savedShortcuts();
155 foreach(const QString &name, _actionByName.keys()) {
156 if (!savedShortcuts.contains(name))
158 Action *action = qobject_cast<Action *>(_actionByName.value(name));
160 action->setShortcut(s.loadShortcut(name), Action::ActiveShortcut);
165 void ActionCollection::writeSettings() const
168 foreach(const QString &name, _actionByName.keys()) {
169 Action *action = qobject_cast<Action *>(_actionByName.value(name));
172 if (!action->isShortcutConfigurable())
174 if (action->shortcut(Action::ActiveShortcut) == action->shortcut(Action::DefaultShortcut))
176 s.saveShortcut(name, action->shortcut(Action::ActiveShortcut));
181 void ActionCollection::slotActionTriggered()
183 QAction *action = qobject_cast<QAction *>(sender());
185 emit actionTriggered(action);
189 void ActionCollection::slotActionHovered()
191 QAction *action = qobject_cast<QAction *>(sender());
193 emit actionHovered(action);
197 void ActionCollection::actionDestroyed(QObject *obj)
199 // remember that this is not an QAction anymore at this point
200 QAction *action = static_cast<QAction *>(obj);
202 unlistAction(action);
206 void ActionCollection::connectNotify(const char *signal)
208 if (_connectHovered && _connectTriggered)
211 if (QMetaObject::normalizedSignature(SIGNAL(actionHovered(QAction *))) == signal) {
212 if (!_connectHovered) {
213 _connectHovered = true;
214 foreach(QAction* action, actions())
215 connect(action, SIGNAL(hovered()), SLOT(slotActionHovered()));
218 else if (QMetaObject::normalizedSignature(SIGNAL(actionTriggered(QAction *))) == signal) {
219 if (!_connectTriggered) {
220 _connectTriggered = true;
221 foreach(QAction* action, actions())
222 connect(action, SIGNAL(triggered(bool)), SLOT(slotActionTriggered()));
226 QObject::connectNotify(signal);
230 void ActionCollection::associateWidget(QWidget *widget) const
232 foreach(QAction *action, actions()) {
233 if (!widget->actions().contains(action))
234 widget->addAction(action);
239 void ActionCollection::addAssociatedWidget(QWidget *widget)
241 if (!_associatedWidgets.contains(widget)) {
242 widget->addActions(actions());
243 _associatedWidgets.append(widget);
244 connect(widget, SIGNAL(destroyed(QObject *)), SLOT(associatedWidgetDestroyed(QObject *)));
249 void ActionCollection::removeAssociatedWidget(QWidget *widget)
251 foreach(QAction *action, actions())
252 widget->removeAction(action);
253 _associatedWidgets.removeAll(widget);
254 disconnect(widget, SIGNAL(destroyed(QObject *)), this, SLOT(associatedWidgetDestroyed(QObject *)));
258 QList<QWidget *> ActionCollection::associatedWidgets() const
260 return _associatedWidgets;
264 void ActionCollection::clearAssociatedWidgets()
266 foreach(QWidget *widget, _associatedWidgets)
267 foreach(QAction *action, actions())
268 widget->removeAction(action);
270 _associatedWidgets.clear();
274 void ActionCollection::associatedWidgetDestroyed(QObject *obj)
276 _associatedWidgets.removeAll(static_cast<QWidget *>(obj));
280 bool ActionCollection::unlistAction(QAction *action)
282 // This might be called with a partly destroyed QAction!
284 int index = _actions.indexOf(action);
285 if (index == -1) return false;
287 QString name = action->objectName();
288 _actionByName.remove(name);
289 _actions.removeAt(index);
291 // TODO: remove from ActionCategory if we ever get that
297 #endif /* HAVE_KDE */