1/***************************************************************************
2 * Copyright (C) 2005-2014 by the Quassel Project *
3 * devel@quassel-irc.org *
4 * *
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) version 3. *
9 * *
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. *
14 * *
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
21#include "shortcutsmodel.h"
22
23#include "action.h"
24#include "actioncollection.h"
25#include "util.h"
26
27ShortcutsModel::ShortcutsModel(const QHash<QString, ActionCollection *> &actionCollections, QObject *parent)
28 : QAbstractItemModel(parent),
29 _changedCount(0)
30{
31 for (int r = 0; r < actionCollections.values().count(); r++) {
32 ActionCollection *coll = actionCollections.values().at(r);
33 Item *item = new Item();
34 item->row = r;
35 item->collection = coll;
36 for (int i = 0; i < coll->actions().count(); i++) {
37 Action *action = qobject_cast<Action *>(coll->actions().at(i));
38 if (!action)
39 continue;
40 Item *actionItem = new Item();
41 actionItem->parentItem = item;
42 actionItem->row = i;
43 actionItem->collection = coll;
44 actionItem->action = action;
45 actionItem->shortcut = action->shortcut();
46 item->actionItems.append(actionItem);
47 }
48 _categoryItems.append(item);
49 }
50}
51
52
53ShortcutsModel::~ShortcutsModel()
54{
55 qDeleteAll(_categoryItems);
56}
57
58
59QModelIndex ShortcutsModel::parent(const QModelIndex &child) const
60{
61 if (!child.isValid())
62 return QModelIndex();
63
64 Item *item = static_cast<Item *>(child.internalPointer());
65 Q_ASSERT(item);
66
67 if (!item->parentItem)
68 return QModelIndex();
69
70 return createIndex(item->parentItem->row, 0, item->parentItem);
71}
72
73
74QModelIndex ShortcutsModel::index(int row, int column, const QModelIndex &parent) const
75{
76 if (parent.isValid())
77 return createIndex(row, column, static_cast<Item *>(parent.internalPointer())->actionItems.at(row));
78
79 // top level category item
80 return createIndex(row, column, _categoryItems.at(row));
81}
82
83
84int ShortcutsModel::columnCount(const QModelIndex &parent) const
85{
86 return 2;
87 if (!parent.isValid())
88 return 2;
89
90 Item *item = static_cast<Item *>(parent.internalPointer());
91 Q_ASSERT(item);
92
93 if (!item->parentItem)
94 return 2;
95
96 return 2;
97}
98
99
100int ShortcutsModel::rowCount(const QModelIndex &parent) const
101{
102 if (!parent.isValid())
103 return _categoryItems.count();
104
105 Item *item = static_cast<Item *>(parent.internalPointer());
106 Q_ASSERT(item);
107
108 if (!item->parentItem)
109 return item->actionItems.count();
110
111 return 0;
112}
113
114
115QVariant ShortcutsModel::headerData(int section, Qt::Orientation orientation, int role) const
116{
117 if (orientation != Qt::Horizontal || role != Qt::DisplayRole)
118 return QVariant();
119 switch (section) {
120 case 0:
121 return tr("Action");
122 case 1:
123 return tr("Shortcut");
124 default:
125 return QVariant();
126 }
127}
128
129
130QVariant ShortcutsModel::data(const QModelIndex &index, int role) const
131{
132 if (!index.isValid())
133 return QVariant();
134
135 Item *item = static_cast<Item *>(index.internalPointer());
136 Q_ASSERT(item);
137
138 if (!item->parentItem) {
139 if (index.column() != 0)
140 return QVariant();
141 switch (role) {
142 case Qt::DisplayRole:
143 return item->collection->property("Category");
144 default:
145 return QVariant();
146 }
147 }
148
149 Action *action = qobject_cast<Action *>(item->action);
150 Q_ASSERT(action);
151
152 switch (role) {
153 case Qt::DisplayRole:
154 switch (index.column()) {
155 case 0:
156 return stripAcceleratorMarkers(action->text());
157 case 1:
158 return item->shortcut.toString(QKeySequence::NativeText);
159 default:
160 return QVariant();
161 }
162
163 case Qt::DecorationRole:
164 if (index.column() == 0)
165 return action->icon();
166 return QVariant();
167
168 case ActionRole:
169 return QVariant::fromValue<QObject *>(action);
170
171 case DefaultShortcutRole:
172 return action->shortcut(Action::DefaultShortcut);
173 case ActiveShortcutRole:
174 return item->shortcut;
175
176 case IsConfigurableRole:
177 return action->isShortcutConfigurable();
178
179 default:
180 return QVariant();
181 }
182}
183
184
185bool ShortcutsModel::setData(const QModelIndex &index, const QVariant &value, int role)
186{
187 if (role != ActiveShortcutRole)
188 return false;
189
190 if (!index.parent().isValid())
191 return false;
192
193 Item *item = static_cast<Item *>(index.internalPointer());
194 Q_ASSERT(item);
195
196 QKeySequence newSeq = value.value<QKeySequence>();
197 QKeySequence oldSeq = item->shortcut;
198 QKeySequence storedSeq = item->action->shortcut(Action::ActiveShortcut);
199
200 item->shortcut = newSeq;
201 emit dataChanged(index, index.sibling(index.row(), 1));
202
203 if (oldSeq == storedSeq && newSeq != storedSeq) {
204 if (++_changedCount == 1)
205 emit hasChanged(true);
206 }
207 else if (oldSeq != storedSeq && newSeq == storedSeq) {
208 if (--_changedCount == 0)
209 emit hasChanged(false);
210 }
211
212 return true;
213}
214
215
216void ShortcutsModel::load()
217{
218 foreach(Item *catItem, _categoryItems) {
219 foreach(Item *actItem, catItem->actionItems) {
220 actItem->shortcut = actItem->action->shortcut(Action::ActiveShortcut);
221 }
222 }
223 emit dataChanged(index(0, 1), index(rowCount()-1, 1));
224 if (_changedCount != 0) {
225 _changedCount = 0;
226 emit hasChanged(false);
227 }
228}
229
230
231void ShortcutsModel::commit()
232{
233 foreach(Item *catItem, _categoryItems) {
234 foreach(Item *actItem, catItem->actionItems) {
235 actItem->action->setShortcut(actItem->shortcut, Action::ActiveShortcut);
236 }
237 }
238 if (_changedCount != 0) {
239 _changedCount = 0;
240 emit hasChanged(false);
241 }
242}
243
244
245void ShortcutsModel::defaults()
246{
247 for (int cat = 0; cat < rowCount(); cat++) {
248 QModelIndex catidx = index(cat, 0);
249 for (int act = 0; act < rowCount(catidx); act++) {
250 QModelIndex actidx = index(act, 1, catidx);
251 setData(actidx, actidx.data(DefaultShortcutRole), ActiveShortcutRole);
252 }
253 }
254}
255