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