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 return KisShortcutConfiguration::shortcutTypeToText(d->shortcuts.at(index.row())->type());
69 case 1: {
70 KisShortcutConfiguration *s = d->shortcuts.at(index.row());
71 QString output;
72
73 switch (s->type()) {
76 break;
77
80 s->keys(), s->buttons());
81 break;
82
85 s->keys(), s->wheel());
86 break;
87
90 break;
91
94 break;
95
96 default:
97 break;
98 }
99
100 return output;
101 }
102
103 case 2:
104 return d->action->shortcutIndexes().key(d->shortcuts.at(index.row())->mode());
105
106 case 3:
107 return KisIconUtils::loadIcon("edit-delete");
108
109 default:
110 break;
111 }
112 }
113 else if (role == Qt::EditRole) {
115
116 if (index.row() == d->shortcuts.count()) {
117 if (!d->temporaryShortcut) {
119 }
120
121 s = d->temporaryShortcut;
122 }
123 else {
124 s = d->shortcuts.at(index.row());
125 }
126
127 switch (index.column()) {
128 case 0:
129 return s->type();
130
131 case 1:
132 return QVariant::fromValue(s);
133
134 case 2:
135 return s->mode();
136
137 default:
138 break;
139 }
140 }
141
142 return QVariant();
143}
144
145int KisActionShortcutsModel::rowCount(const QModelIndex &parent) const
146{
147 if (parent.isValid()) {
148 return 0;
149 }
150
151 return d->shortcuts.count() + 1;
152}
153
154int KisActionShortcutsModel::columnCount(const QModelIndex & /*parent*/) const
155{
156 return 3;
157}
158
159QVariant KisActionShortcutsModel::headerData(int section, Qt::Orientation orientation, int role) const
160{
161 if (orientation != Qt::Horizontal || role != Qt::DisplayRole) {
162 return QVariant();
163 }
164
165 switch (section) {
166 case 0:
167 return i18nc("Type of shortcut", "Type");
168
169 case 1:
170 return i18nc("Input for shortcut", "Input");
171
172 case 2:
173 return i18nc("Action to trigger with shortcut", "Action");
174
175 default:
176 break;
177 }
178
179 return QVariant();
180}
181
182Qt::ItemFlags KisActionShortcutsModel::flags(const QModelIndex &index) const
183{
184 if (!index.isValid()) {
185 return Qt::ItemIsEnabled;
186 }
187
188 if (index.row() == d->shortcuts.count() && index.column() != 0) {
189 return Qt::ItemIsEnabled;
190 }
191
192 if (index.row() >= d->shortcuts.count()) {
193 return Qt::ItemIsEnabled | Qt::ItemIsEditable;
194 }
195
196 KisShortcutConfiguration* config = d->shortcuts.at(index.row());
197 if (index.column() == 2 && d->action->isShortcutRequired(config->mode()) && d->shortcutModeCount(config->mode()) < 2) {
198 return Qt::ItemIsSelectable;
199 }
200
201 return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
202}
203
205{
206 if (row >= d->shortcuts.size()) {
207 return false;
208 }
209 KisShortcutConfiguration* config = d->shortcuts.at(row);
210 return !(d->action->isShortcutRequired(config->mode()) && d->shortcutModeCount(config->mode()) < 2);
211}
212
213bool KisActionShortcutsModel::setData(const QModelIndex &index, const QVariant &value, int role)
214{
215 if (!index.isValid() || role != Qt::EditRole) {
216 return false;
217 }
218
219 if (index.row() == d->shortcuts.count()) {
220 if (!d->temporaryShortcut || (index.column() == 0 && value.toUInt() == 0)) {
221 return false;
222 }
223
224 beginInsertRows(QModelIndex(), d->shortcuts.count(), d->shortcuts.count());
227 d->shortcuts.append(d->temporaryShortcut);
228 d->temporaryShortcut = 0;
229 endInsertRows();
230 }
231
232 switch (index.column()) {
233 case 0:
234 d->shortcuts.at(index.row())->setType(static_cast<KisShortcutConfiguration::ShortcutType>(value.toUInt()));
235 break;
236
237 case 1: {
239 KisShortcutConfiguration *oldData = d->shortcuts.at(index.row());
240
241 if (newData == oldData) {
242 const QList<KisShortcutConfiguration *> conflictingShortcuts =
244 KisInputProfileManager::instance()->currentProfile());
245
246 // check if this shortcut resulted in a conflict
247 const bool isConflictingShortcut = std::find_if(conflictingShortcuts.begin(),
248 conflictingShortcuts.end(),
249 [&oldData](KisShortcutConfiguration *shortcut) {
250 return *oldData == *shortcut;
251 })
252 != conflictingShortcuts.end();
253
254 if (isConflictingShortcut) {
255 QMessageBox::warning(qApp->activeWindow(),
256 "Warning",
257 i18n("A conflict exists between two or more shortcuts."));
258 }
259 // change was done on the object
260 Q_EMIT dataChanged(index, index);
261 return true;
262 }
263
264 oldData->setKeys(newData->keys());
265 oldData->setButtons(newData->buttons());
266 oldData->setWheel(newData->wheel());
267 oldData->setTouchGesture(newData->touchGesture());
268 oldData->setNativeGesture(newData->nativeGesture());
269
270 break;
271 }
272
273 case 2:
274 d->shortcuts.at(index.row())->setMode(value.toUInt());
275 break;
276 }
277
278 Q_EMIT dataChanged(index, index);
279
280 return true;
281}
282
287
289{
290 if (action != d->action) {
291 if (d->action) {
292 beginRemoveRows(QModelIndex(), 0, d->shortcuts.count() - 1);
293 endRemoveRows();
294 }
295
296 d->action = action;
297
298 if (d->action && d->profile) {
300 beginInsertRows(QModelIndex(), 0, d->shortcuts.count() - 1);
301 endInsertRows();
302 }
303 }
304}
305
310
312{
313 if (profile != d->profile) {
314 if (d->profile) {
315 beginRemoveRows(QModelIndex(), 0, d->shortcuts.count() - 1);
316 endRemoveRows();
317 }
318
319 d->profile = profile;
320
321 if (d->action && d->profile) {
323 beginInsertRows(QModelIndex(), 0, d->shortcuts.count() - 1);
324 endInsertRows();
325 }
326 }
327}
328
333
334bool KisActionShortcutsModel::removeRows(int row, int count, const QModelIndex &parent)
335{
336 if (row < 0 || row >= d->shortcuts.count() || count == 0) {
337 return false;
338 }
339
340 beginRemoveRows(parent, row, row + count - 1);
341
342 for (int i = row; i < d->shortcuts.count() && count > 0; ++i, count--) {
344
346 d->shortcuts.removeOne(s);
347 delete s;
348 }
349
350 endRemoveRows();
351
352 return true;
353}
354
356{
357 int count = 0;
358 Q_FOREACH (KisShortcutConfiguration* s, shortcuts) {
359 if(s->mode() == mode) {
360 count++;
361 }
362 }
363
364 return count;
365}
float value(const T *src, size_t ch)
unsigned int uint
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)
static QString shortcutTypeToText(ShortcutType type)
@ 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)
static QString nativeGestureToText(NativeGestureAction action)
void setAction(KisAbstractInputAction *newAction)
static QString touchGestureToText(TouchGestureAction action)
NativeGestureAction nativeGesture() const
TouchGestureAction touchGesture() const
static QString buttonsInputToText(const QList< Qt::Key > &keys, Qt::MouseButtons buttons)
QIcon loadIcon(const QString &name)