Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_shortcut_configuration.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 <QDebug>
11#include <QStringList>
12#include <QKeySequence>
13#include <KLocalizedString>
14
15#include <boost/preprocessor/repeat_from_to.hpp>
16
39
45
47 : d(new Private)
48{
49 d->action = other.action();
50 d->type = other.type();
51 d->mode = other.mode();
52 d->keys = other.keys();
53 d->buttons = other.buttons();
54 d->wheel = other.wheel();
55 d->touchGesture = other.touchGesture();
56 d->nativeGesture = other.nativeGesture();
57}
58
60{
61 d->action = other.action();
62 d->type = other.type();
63 d->mode = other.mode();
64 d->keys = other.keys();
65 d->buttons = other.buttons();
66 d->wheel = other.wheel();
67 d->touchGesture = other.touchGesture();
68 d->nativeGesture = other.nativeGesture();
69
70 return *this;
71}
72
74{
75 return d->type == other.d->type && d->keys == other.d->keys && d->buttons == other.d->buttons
76 && d->wheel == other.d->wheel && d->touchGesture == other.d->touchGesture && d->nativeGesture == other.d->nativeGesture;
77}
78
83
85{
86 QString serialized("{");
87
88 serialized.append(QString::number(d->mode, 16));
89 serialized.append(';');
90 serialized.append(QString::number(d->type, 16));
91 serialized.append(";[");
92
93 for (QList<Qt::Key>::iterator itr = d->keys.begin(); itr != d->keys.end(); ++itr) {
94 serialized.append(QString::number(*itr, 16));
95
96 if (itr + 1 != d->keys.end()) {
97 serialized.append(',');
98 }
99 }
100
101 serialized.append("];");
102
103 serialized.append(QString::number(d->buttons, 16));
104 serialized.append(';');
105 serialized.append(QString::number(d->wheel, 16));
106 serialized.append(';');
107 if (d->type == NativeGestureType) {
108 serialized.append(QString::number(d->nativeGesture, 16));
109 } else {
110 serialized.append(QString::number(d->touchGesture, 16));
111 }
112 serialized.append('}');
113
114 return serialized;
115}
116
117bool KisShortcutConfiguration::unserialize(const QString &serialized)
118{
119 if (!serialized.startsWith('{'))
120 return false;
121
122 //Parse the serialized data and apply it to the current shortcut
123 QString remainder = serialized;
124
125 //Remove brackets
126 remainder.remove('{').remove('}');
127
128 //Split the remainder by ;
129 QStringList parts = remainder.split(';');
130
131 if (parts.size() < 6)
132 return false; //Invalid input, abort
133
134 //First entry in the list is the mode
135 d->mode = parts.at(0).toUInt(nullptr, 16);
136
137 //Second entry is the shortcut type
138 d->type = static_cast<ShortcutType>(parts.at(1).toInt(nullptr, 16));
139
140 if (d->type == UnknownType) {
141 //Reject input that would set this shortcut to "Unknown"
142 return false;
143 }
144
145 //Third entry is the list of keys
146 QString serializedKeys = parts.at(2);
147 //Remove brackets
148 serializedKeys.remove('[').remove(']');
149 //Split by , and add each entry as a key
150 QStringList keylist = serializedKeys.split(',');
151 Q_FOREACH(QString key, keylist) {
152 if (!key.isEmpty()) {
153 d->keys.append(static_cast<Qt::Key>(key.toUInt(nullptr, 16)));
154 }
155 }
156
157 //Fourth entry is the button mask
158 d->buttons = static_cast<Qt::MouseButtons>(parts.at(3).toInt(nullptr, 16));
159 d->wheel = static_cast<MouseWheelMovement>(parts.at(4).toUInt(nullptr, 16));
160
161 if (d->type == MouseWheelType && d->wheel == WheelReserved_0) {
162 qWarning() << "WARNING: input profile contains deprecated Mouse Wheel shortcut (WheelReserved_0), skipping...";
163 return false;
164 }
165
166 if (d->type == NativeGestureType) {
167 d->nativeGesture = static_cast<NativeGestureAction>(parts.at(5).toUInt(nullptr, 16));
168 } else {
169 d->touchGesture = static_cast<TouchGestureAction>(parts.at(5).toUInt(nullptr, 16));
170 }
171
172 return true;
173}
174
179
181{
182 if (d->action != newAction) {
183 d->action = newAction;
184 }
185}
186
191
193{
194 if (d->type != newType) {
195 d->type = newType;
196 }
197}
198
200{
201 return d->mode;
202}
203
205{
206 if (d->mode != newMode) {
207 d->mode = newMode;
208 }
209}
210
215
217{
218 if (d->keys != newKeys) {
219 d->keys = newKeys;
220 }
221}
222
223Qt::MouseButtons KisShortcutConfiguration::buttons() const
224{
225 return d->buttons;
226}
227
228void KisShortcutConfiguration::setButtons(Qt::MouseButtons newButtons)
229{
230 if (d->buttons != newButtons) {
231 d->buttons = newButtons;
232 }
233}
234
239
246
251
256
261
266
268{
269 return d->type == UnknownType || (d->type == KeyCombinationType && d->keys.isEmpty())
270 || (d->type == MouseButtonType && d->buttons.testFlag(Qt::NoButton))
271 || (d->type == MouseWheelType && d->wheel == NoMovement)
272 || (d->type == TouchGestureType
274 || (d->type == NativeGestureType
276
277}
278
280{
281 switch (d->type) {
283 return keysToText(d->keys);
284 case MouseButtonType:
285 return buttonsInputToText(d->keys, d->buttons);
286 case MouseWheelType:
287 return wheelInputToText(d->keys, d->wheel);
288 case TouchGestureType:
292 default:
293 return QString();
294 }
295}
296
298{
299 QString text;
300 QString sep = i18nc("Separator in the list of mouse buttons for shortcut", " + ");
301
302 int buttonCount = 0;
303
304 if (buttons & Qt::LeftButton) {
305 text.append(i18nc("Left Mouse Button", "Left"));
306 buttonCount++;
307 }
308
309 if (buttons & Qt::RightButton) {
310 if (buttonCount++ > 0) {
311 text.append(sep);
312 }
313
314 text.append(i18nc("Right Mouse Button", "Right"));
315 }
316
317 if (buttons & Qt::MiddleButton) {
318 if (buttonCount++ > 0) {
319 text.append(sep);
320 }
321
322 text.append(i18nc("Middle Mouse Button", "Middle"));
323 }
324
325 if (buttons & Qt::BackButton) {
326 if (buttonCount++ > 0) {
327 text.append(sep);
328 }
329
330 text.append(i18nc("Mouse Back Button", "Back"));
331 }
332
333 if (buttons & Qt::ForwardButton) {
334 if (buttonCount++ > 0) {
335 text.append(sep);
336 }
337
338 text.append(i18nc("Mouse Forward Button", "Forward"));
339 }
340
341 if (buttons & Qt::TaskButton) {
342 if (buttonCount++ > 0) {
343 text.append(sep);
344 }
345
346 text.append(i18nc("Mouse Task Button", "Task"));
347 }
348
349// Qt supports up to ExtraButton24 so include those
350#define EXTRA_BUTTON(z, n, _)\
351 if (buttons & Qt::ExtraButton##n) { \
352 if (buttonCount++ > 0) { text.append(sep); } \
353 text.append(i18nc("Mouse Button", "Mouse %1", n + 3)); \
354 }
355BOOST_PP_REPEAT_FROM_TO(4, 25, EXTRA_BUTTON, _)
356#undef EXTRA_BUTTON
357
358 if (buttonCount == 0) {
359 text.append(i18nc("No mouse buttons for shortcut", "None"));
360 }
361 else {
362 text = i18ncp(
363 "%1 = List of mouse buttons for shortcut. "
364 "Plural form is chosen upon the number of buttons in that list.",
365 "%1 Button", "%1 Buttons", text, buttonCount);
366 }
367
368 return text;
369}
370
372{
373 QString output;
374
375 Q_FOREACH (Qt::Key key, keys) {
376#if defined(Q_OS_MAC)
377 // This works for modifier keys on macOS but not other platforms.
378 // They are shown with symbols, so no translation or separators needed.
379 output.append(QKeySequence(key).toString(QKeySequence::NativeText));
380#else
381 if (output.size() > 0) {
382 output.append(i18nc("Separator in the list of keys for shortcut", " + "));
383 }
384
385 switch (key) { //Because QKeySequence fails for Ctrl, Alt, Shift and Meta
386 case Qt::Key_Control:
387 output.append(i18nc("Ctrl key", "Ctrl"));
388 break;
389
390 case Qt::Key_Meta:
391 output.append(i18nc("Meta key", "Meta"));
392 break;
393
394 case Qt::Key_Alt:
395 output.append(i18nc("Alt key", "Alt"));
396 break;
397
398 case Qt::Key_Shift:
399 output.append(i18nc("Shift key", "Shift"));
400 break;
401
402 default:
403 QKeySequence s(key);
404 output.append(s.toString(QKeySequence::NativeText));
405 break;
406 }
407#endif
408 }
409
410 if (output.size() == 0) {
411 output = i18nc("No keys for shortcut", "None");
412 }
413
414 return output;
415}
416
418{
419 switch (wheel) {
421 return i18n("Mouse Wheel Up");
422 break;
423
425 return i18n("Mouse Wheel Down");
426 break;
427
429 return i18n("Mouse Wheel Left");
430 break;
431
433 return i18n("Mouse Wheel Right");
434 break;
435
436 default:
437 return i18nc("No mouse wheel buttons for shortcut", "None");
438 break;
439 }
440}
441
443{
445
446 if (keys.size() > 0) {
447 return i18nc(
448 "%1 = modifier keys in shortcut; %2 = mouse buttons in shortcut",
449 "%1 + %2",
451 buttonsText);
452 }
453 else {
454 return buttonsText;
455 }
456}
457
459{
460 QString wheelText = KisShortcutConfiguration::wheelToText(wheel);
461
462 if (keys.size() > 0) {
463 return i18nc(
464 "%1 = modifier keys in shortcut; %2 = mouse wheel buttons in shortcut",
465 "%1 + %2",
467 wheelText);
468 }
469 else {
470 return wheelText;
471 }
472}
473
475{
476 switch (action) {
477 case PinchGesture:
478 return i18n("Pinch Gesture");
479 case SmartZoomGesture:
480 return i18n("Smart Zoom Gesture");
481 case TouchpadScroll:
482 return i18n("Touchpad Scroll Gesture");
483 default:
484 return i18n("No Gesture");
485 }
486}
487
489{
490 switch (action) {
491 case OneFingerTap:
492 return i18n("One Finger Tap");
493 case TwoFingerTap:
494 return i18n("Two Finger Tap");
495 case ThreeFingerTap:
496 return i18n("Three Finger Tap");
497 case FourFingerTap:
498 return i18n("Four Finger Tap");
499 case FiveFingerTap:
500 return i18n("Five Finger Tap");
501 case OneFingerDrag:
502 return i18n("One Finger Drag");
503 case TwoFingerDrag:
504 return i18n("Two Finger Drag");
505 case ThreeFingerDrag:
506 return i18n("Three Finger Drag");
507 case FourFingerDrag:
508 return i18n("Four Finger Drag");
509 case FiveFingerDrag:
510 return i18n("Five Finger Drag");
511 case OneFingerHold:
512 return i18n("One Finger Hold");
513 default:
514 return i18n("No Gesture");
515 }
516}
517
519{
520 switch (type) {
522 return i18nc("Shortcut type", "Key Combination");
523
525 return i18nc("Shortcut type", "Mouse Button");
526
528 return i18nc("Shortcut type", "Mouse Wheel");
529
531 return i18nc("Shortcut type", "Touch Gesture");
532
534 return i18nc("Shortcut type", "Touchpad Gesture");
535
536 default:
537 return i18n("Unknown Input");
538 }
539}
unsigned int uint
Abstract base class for input actions.
A class encapsulating all settings for a single shortcut.
void setButtons(Qt::MouseButtons newButtons)
void setWheel(MouseWheelMovement type)
bool operator==(const KisShortcutConfiguration &other) const
static QString buttonsToText(Qt::MouseButtons buttons)
static QString keysToText(const QList< Qt::Key > &keys)
void setNativeGesture(NativeGestureAction type)
KisAbstractInputAction * action() const
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.
@ UnknownType
Unknown, empty shortcut.
KisShortcutConfiguration & operator=(const KisShortcutConfiguration &other)
static QString wheelInputToText(const QList< Qt::Key > &keys, MouseWheelMovement wheel)
bool unserialize(const QString &serialized)
void setTouchGesture(TouchGestureAction type)
static QString wheelToText(MouseWheelMovement wheel)
static QString nativeGestureToText(NativeGestureAction action)
void setAction(KisAbstractInputAction *newAction)
static QString touchGestureToText(TouchGestureAction action)
NativeGestureAction nativeGesture() const
void setType(ShortcutType newType)
TouchGestureAction touchGesture() const
void setKeys(const QList< Qt::Key > &newKeys)
@ TouchpadScroll
Two-dimensional pixel scrolling on a touchpad, supported on MacOS and Wayland only.
@ SmartZoomGesture
Smart zoom gesture, typically a double tap that is a boolean zoom/unzoom.
@ PinchGesture
Pinch gesture, a two finger gesture used for navigating the canvas.
@ WheelDown
Downwards movement, toward the user.
@ WheelUp
Upwards movement, away from the user.
@ WheelReserved_0
Do not use! Previously was used for TouchpadScroll shortcut.
static QString buttonsInputToText(const QList< Qt::Key > &keys, Qt::MouseButtons buttons)
#define EXTRA_BUTTON(z, n, _)
QString buttons(const T &ev)