Fix keysequence strings for Mac again
[quassel.git] / src / qtui / settingspages / shortcutsmodel.cpp
1 /***************************************************************************
2  *   Copyright (C) 2010 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  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, 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 ShortcutsModel::~ShortcutsModel() {
53   qDeleteAll(_categoryItems);
54 }
55
56 QModelIndex ShortcutsModel::parent(const QModelIndex &child) const {
57   if(!child.isValid())
58     return QModelIndex();
59
60   Item *item = static_cast<Item *>(child.internalPointer());
61   Q_ASSERT(item);
62
63   if(!item->parentItem)
64     return QModelIndex();
65
66   return createIndex(item->parentItem->row, 0, item->parentItem);
67 }
68
69 QModelIndex ShortcutsModel::index(int row, int column, const QModelIndex &parent) const {
70
71   if(parent.isValid())
72     return createIndex(row, column, static_cast<Item *>(parent.internalPointer())->actionItems.at(row));
73
74   // top level category item
75   return createIndex(row, column, _categoryItems.at(row));
76 }
77
78 int ShortcutsModel::columnCount(const QModelIndex &parent) const {
79   return 2;
80   if(!parent.isValid())
81     return 2;
82
83   Item *item = static_cast<Item *>(parent.internalPointer());
84   Q_ASSERT(item);
85
86   if(!item->parentItem)
87     return 2;
88
89   return 2;
90 }
91
92 int ShortcutsModel::rowCount(const QModelIndex &parent) const {
93   if(!parent.isValid())
94     return _categoryItems.count();
95
96   Item *item = static_cast<Item *>(parent.internalPointer());
97   Q_ASSERT(item);
98
99   if(!item->parentItem)
100     return item->actionItems.count();
101
102   return 0;
103 }
104
105 QVariant ShortcutsModel::headerData(int section, Qt::Orientation orientation, int role) const {
106   if(orientation != Qt::Horizontal || role != Qt::DisplayRole)
107     return QVariant();
108   switch(section) {
109   case 0:
110     return tr("Action");
111   case 1:
112     return tr("Shortcut");
113   default:
114     return QVariant();
115   }
116 }
117
118 QVariant ShortcutsModel::data(const QModelIndex &index, int role) const {
119   if(!index.isValid())
120     return QVariant();
121
122   Item *item = static_cast<Item *>(index.internalPointer());
123   Q_ASSERT(item);
124
125   if(!item->parentItem) {
126     if(index.column() != 0)
127       return QVariant();
128     switch(role) {
129     case Qt::DisplayRole:
130       return item->collection->property("Category");
131     default:
132       return QVariant();
133     }
134   }
135
136   Action *action = qobject_cast<Action *>(item->action);
137   Q_ASSERT(action);
138
139   switch(role) {
140   case Qt::DisplayRole:
141     switch(index.column()) {
142     case 0:
143       return stripAcceleratorMarkers(action->text());
144     case 1:
145       return item->shortcut.toString(QKeySequence::NativeText);
146     default:
147       return QVariant();
148     }
149
150   case Qt::DecorationRole:
151     if(index.column() == 0)
152       return action->icon();
153     return QVariant();
154
155   case ActionRole:
156     return QVariant::fromValue<QObject *>(action);
157
158   case DefaultShortcutRole:
159     return action->shortcut(Action::DefaultShortcut);
160   case ActiveShortcutRole:
161     return item->shortcut;
162
163   case IsConfigurableRole:
164     return action->isShortcutConfigurable();
165
166   default:
167     return QVariant();
168   }
169 }
170
171 bool ShortcutsModel::setData(const QModelIndex &index, const QVariant &value, int role) {
172   if(role != ActiveShortcutRole)
173     return false;
174
175   if(!index.parent().isValid())
176     return false;
177
178   Item *item = static_cast<Item *>(index.internalPointer());
179   Q_ASSERT(item);
180
181   QKeySequence newSeq = value.value<QKeySequence>();
182   QKeySequence oldSeq = item->shortcut;
183   QKeySequence storedSeq = item->action->shortcut(Action::ActiveShortcut);
184
185   item->shortcut = newSeq;
186   emit dataChanged(index, index.sibling(index.row(), 1));
187
188   if(oldSeq == storedSeq && newSeq != storedSeq) {
189     if(++_changedCount == 1)
190       emit hasChanged(true);
191   } else if(oldSeq != storedSeq && newSeq == storedSeq) {
192     if(--_changedCount == 0)
193       emit hasChanged(false);
194   }
195
196   return true;
197 }
198
199 void ShortcutsModel::load() {
200   foreach(Item *catItem, _categoryItems) {
201     foreach(Item *actItem, catItem->actionItems) {
202       actItem->shortcut = actItem->action->shortcut(Action::ActiveShortcut);
203     }
204   }
205   emit dataChanged(index(0, 1), index(rowCount()-1, 1));
206   if(_changedCount != 0) {
207     _changedCount = 0;
208     emit hasChanged(false);
209   }
210 }
211
212 void ShortcutsModel::commit() {
213   foreach(Item *catItem, _categoryItems) {
214     foreach(Item *actItem, catItem->actionItems) {
215       actItem->action->setShortcut(actItem->shortcut, Action::ActiveShortcut);
216     }
217   }
218   if(_changedCount != 0) {
219     _changedCount = 0;
220     emit hasChanged(false);
221   }
222 }
223
224 void ShortcutsModel::defaults() {
225   for(int cat = 0; cat < rowCount(); cat++) {
226     QModelIndex catidx = index(cat, 0);
227     for(int act = 0; act < rowCount(catidx); act++) {
228       QModelIndex actidx = index(act, 1, catidx);
229       setData(actidx, actidx.data(DefaultShortcutRole), ActiveShortcutRole);
230     }
231   }
232 }