Yearly bump
[quassel.git] / src / qtui / settingspages / shortcutsmodel.cpp
1 /***************************************************************************
2  *   Copyright (C) 2005-2013 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::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
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 }