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 | |
27 | ShortcutsModel::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 | |
53 | ShortcutsModel::~ShortcutsModel() |
54 | { |
55 | qDeleteAll(_categoryItems); |
56 | } |
57 | |
58 | |
59 | QModelIndex 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 | |
74 | QModelIndex 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 | |
84 | int 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 | |
100 | int 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 | |
115 | QVariant ShortcutsModel::(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 | |
130 | QVariant 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 | |
185 | bool 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 | |
216 | void 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 | |
231 | void 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 | |
245 | void 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 | |