Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_action_shortcuts_model.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the KDE project
3 * SPDX-FileCopyrightText: 2013 Arjen Hiemstra <ahiemstra@heimr.nl>
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 */
7
9
10#include <kis_debug.h>
11
12#include <KLocalizedString>
13#include <QApplication>
14#include <QMetaClassInfo>
15#include <QKeySequence>
16#include <QMessageBox>
17
18#include "kis_icon_utils.h"
19#include <QApplication>
20
25
39
41 : QAbstractListModel(parent), d(new Private)
42{
44}
45
49
50QVariant KisActionShortcutsModel::data(const QModelIndex &index, int role) const
51{
52 if (!index.isValid()) {
53 return QVariant();
54 }
55
56 if (index.row() == d->shortcuts.count() && role == Qt::DisplayRole) {
57 if (index.column() == 0) {
58 return i18n("Add shortcut...");
59 }
60 else {
61 return QVariant();
62 }
63 }
64
65 if (role == Qt::DisplayRole) {
66 switch (index.column()) {
67 case 0:
68 switch (d->shortcuts.at(index.row())->type()) {
70 return i18nc("Shortcut type", "Key Combination");
71
73 return i18nc("Shortcut type", "Mouse Button");
74
76 return i18nc("Shortcut type", "Mouse Wheel");
77
79 return i18nc("Shortcut type", "Gesture");
80
81 default:
82 return i18n("Unknown Input");
83 }
84
85 break;
86
87 case 1: {
88 KisShortcutConfiguration *s = d->shortcuts.at(index.row());
89 QString output;
90
91 switch (s->type()) {
94 break;
95
98 s->keys(), s->buttons());
99 break;
100
103 s->keys(), s->wheel());
104 break;
105
108 break;
109
110 default:
111 break;
112 }
113
114 return output;
115 }
116
117 case 2:
118 return d->action->shortcutIndexes().key(d->shortcuts.at(index.row())->mode());
119
120 case 3:
121 return KisIconUtils::loadIcon("edit-delete");
122
123 default:
124 break;
125 }
126 }
127 else if (role == Qt::EditRole) {
129
130 if (index.row() == d->shortcuts.count()) {
131 if (!d->temporaryShortcut) {
133 }
134
135 s = d->temporaryShortcut;
136 }
137 else {
138 s = d->shortcuts.at(index.row());
139 }
140
141 switch (index.column()) {
142 case 0:
143 return s->type();
144
145 case 1:
146 return QVariant::fromValue(s);
147
148 case 2:
149 return s->mode();
150
151 default:
152 break;
153 }
154 }
155
156 return QVariant();
157}
158
159int KisActionShortcutsModel::rowCount(const QModelIndex &parent) const
160{
161 if (parent.isValid()) {
162 return 0;
163 }
164
165 return d->shortcuts.count() + 1;
166}
167
168int KisActionShortcutsModel::columnCount(const QModelIndex & /*parent*/) const
169{
170 return 3;
171}
172
173QVariant KisActionShortcutsModel::headerData(int section, Qt::Orientation orientation, int role) const
174{
175 if (orientation != Qt::Horizontal || role != Qt::DisplayRole) {
176 return QVariant();
177 }
178
179 switch (section) {
180 case 0:
181 return i18nc("Type of shortcut", "Type");
182
183 case 1:
184 return i18nc("Input for shortcut", "Input");
185
186 case 2:
187 return i18nc("Action to trigger with shortcut", "Action");
188
189 default:
190 break;
191 }
192
193 return QVariant();
194}
195
196Qt::ItemFlags KisActionShortcutsModel::flags(const QModelIndex &index) const
197{
198 if (!index.isValid()) {
199 return Qt::ItemIsEnabled;
200 }
201
202 if (index.row() == d->shortcuts.count() && index.column() != 0) {
203 return Qt::ItemIsEnabled;
204 }
205
206 if (index.row() >= d->shortcuts.count()) {
207 return Qt::ItemIsEnabled | Qt::ItemIsEditable;
208 }
209
210 KisShortcutConfiguration* config = d->shortcuts.at(index.row());
211 if (index.column() == 2 && d->action->isShortcutRequired(config->mode()) && d->shortcutModeCount(config->mode()) < 2) {
212 return Qt::ItemIsSelectable;
213 }
214
215 return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
216}
217
219{
220 if (row >= d->shortcuts.size()) {
221 return false;
222 }
223 KisShortcutConfiguration* config = d->shortcuts.at(row);
224 return !(d->action->isShortcutRequired(config->mode()) && d->shortcutModeCount(config->mode()) < 2);
225}
226
227bool KisActionShortcutsModel::setData(const QModelIndex &index, const QVariant &value, int role)
228{
229 if (!index.isValid() || role != Qt::EditRole) {
230 return false;
231 }
232
233 if (index.row() == d->shortcuts.count()) {
234 if (!d->temporaryShortcut || (index.column() == 0 && value.toUInt() == 0)) {
235 return false;
236 }
237
238 beginInsertRows(QModelIndex(), d->shortcuts.count(), d->shortcuts.count());
241 d->shortcuts.append(d->temporaryShortcut);
242 d->temporaryShortcut = 0;
243 endInsertRows();
244 }
245
246 switch (index.column()) {
247 case 0:
248 d->shortcuts.at(index.row())->setType(static_cast<KisShortcutConfiguration::ShortcutType>(value.toUInt()));
249 break;
250
251 case 1: {
253 KisShortcutConfiguration *oldData = d->shortcuts.at(index.row());
254
255 if (newData == oldData) {
256 const QList<KisShortcutConfiguration *> conflictingShortcuts =
258 KisInputProfileManager::instance()->currentProfile());
259
260 // check if this shortcut resulted in a conflict
261 const bool isConflictingShortcut = std::find_if(conflictingShortcuts.begin(),
262 conflictingShortcuts.end(),
263 [&oldData](KisShortcutConfiguration *shortcut) {
264 return *oldData == *shortcut;
265 })
266 != conflictingShortcuts.end();
267
268 if (isConflictingShortcut) {
269 QMessageBox::warning(qApp->activeWindow(),
270 "Warning",
271 i18n("A conflict exists between two or more shortcuts."));
272 }
273 // change was done on the object
274 Q_EMIT dataChanged(index, index);
275 return true;
276 }
277
278 oldData->setKeys(newData->keys());
279 oldData->setButtons(newData->buttons());
280 oldData->setWheel(newData->wheel());
281 oldData->setGesture(newData->gesture());
282
283 break;
284 }
285
286 case 2:
287 d->shortcuts.at(index.row())->setMode(value.toUInt());
288 break;
289 }
290
291 Q_EMIT dataChanged(index, index);
292
293 return true;
294}
295
300
302{
303 if (action != d->action) {
304 if (d->action) {
305 beginRemoveRows(QModelIndex(), 0, d->shortcuts.count() - 1);
306 endRemoveRows();
307 }
308
309 d->action = action;
310
311 if (d->action && d->profile) {
313 beginInsertRows(QModelIndex(), 0, d->shortcuts.count() - 1);
314 endInsertRows();
315 }
316 }
317}
318
323
325{
326 if (profile != d->profile) {
327 if (d->profile) {
328 beginRemoveRows(QModelIndex(), 0, d->shortcuts.count() - 1);
329 endRemoveRows();
330 }
331
332 d->profile = profile;
333
334 if (d->action && d->profile) {
336 beginInsertRows(QModelIndex(), 0, d->shortcuts.count() - 1);
337 endInsertRows();
338 }
339 }
340}
341
346
347bool KisActionShortcutsModel::removeRows(int row, int count, const QModelIndex &parent)
348{
349 if (row < 0 || row >= d->shortcuts.count() || count == 0) {
350 return false;
351 }
352
353 beginRemoveRows(parent, row, row + count - 1);
354
355 for (int i = row; i < d->shortcuts.count() && count > 0; ++i, count--) {
357
359 d->shortcuts.removeOne(s);
360 delete s;
361 }
362
363 endRemoveRows();
364
365 return true;
366}
367
369{
370 int count = 0;
371 Q_FOREACH (KisShortcutConfiguration* s, shortcuts) {
372 if(s->mode() == mode) {
373 count++;
374 }
375 }
376
377 return count;
378}
float value(const T *src, size_t ch)
unsigned int uint
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
Abstract base class for input actions.
virtual bool isShortcutRequired(int shortcut) const
virtual QHash< QString, int > shortcutIndexes() const
QList< KisShortcutConfiguration * > shortcuts
void setProfile(KisInputProfile *profile)
void setAction(KisAbstractInputAction *action)
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
int rowCount(const QModelIndex &parent=QModelIndex()) const override
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
KisInputProfile * profile() const
int columnCount(const QModelIndex &) const override
KisAbstractInputAction * action() const
bool removeRows(int row, int count, const QModelIndex &parent=QModelIndex()) override
Qt::ItemFlags flags(const QModelIndex &index) const override
QList< KisShortcutConfiguration * > getConflictingShortcuts(KisInputProfile *profile)
static KisInputProfileManager * instance()
A container class for sets of shortcuts associated with an action.
QList< KisShortcutConfiguration * > shortcutsForAction(KisAbstractInputAction *action) const
void addShortcut(KisShortcutConfiguration *shortcut)
void removeShortcut(KisShortcutConfiguration *shortcut)
A class encapsulating all settings for a single shortcut.
static QString keysToText(const QList< Qt::Key > &keys)
@ MouseButtonType
A mouse button, possibly with key modifiers.
@ MouseWheelType
Mouse wheel movement, possibly with key modifiers.
@ KeyCombinationType
A list of keys that should be pressed.
static QString wheelInputToText(const QList< Qt::Key > &keys, MouseWheelMovement wheel)
void setAction(KisAbstractInputAction *newAction)
static QString gestureToText(GestureAction action)
static QString buttonsInputToText(const QList< Qt::Key > &keys, Qt::MouseButtons buttons)
QIcon loadIcon(const QString &name)