KDeclarative

keysequencehelper.cpp
1 /*
2  SPDX-FileCopyrightText: 2020 David Redondo <[email protected]>
3  SPDX-FileCopyrightText: 2014 David Edmundson <[email protected]>
4  SPDX-FileCopyrightText: 1998 Mark Donohoe <[email protected]>
5  SPDX-FileCopyrightText: 2001 Ellis Whitehead <[email protected]>
6  SPDX-FileCopyrightText: 2007 Andreas Hartmetz <[email protected]>
7 
8  SPDX-License-Identifier: LGPL-2.1-or-later
9 */
10 
11 #include "keysequencehelper.h"
12 
13 #include <QDebug>
14 #include <QHash>
15 #include <QPointer>
16 #include <QQuickRenderControl>
17 #include <QQmlEngine>
18 #include <QQuickWindow>
19 
20 #include <KLocalizedString>
21 #include <KMessageBox>
22 #include <KGlobalAccel>
23 #include <KGlobalShortcutInfo>
24 #include <KStandardShortcut>
25 
26 class KeySequenceHelperPrivate
27 {
28 public:
29  KeySequenceHelperPrivate(KeySequenceHelper *q);
30 
35  bool conflictWithStandardShortcuts(const QKeySequence &seq);
36 
41  bool conflictWithGlobalShortcuts(const QKeySequence &seq);
42 
46  bool stealStandardShortcut(KStandardShortcut::StandardShortcut std, const QKeySequence &seq);
47 
48  bool checkAgainstStandardShortcuts() const
49  {
50  return checkAgainstShortcutTypes & KeySequenceHelper::StandardShortcuts;
51  }
52 
53  bool checkAgainstGlobalShortcuts() const
54  {
55  return checkAgainstShortcutTypes & KeySequenceHelper::GlobalShortcuts;
56  }
57 
58 
59 //members
60  KeySequenceHelper *const q;
61 
63  KeySequenceHelper::ShortcutTypes checkAgainstShortcutTypes;
64 };
65 
66 KeySequenceHelperPrivate::KeySequenceHelperPrivate(KeySequenceHelper *q)
67  : q(q)
68  , checkAgainstShortcutTypes(KeySequenceHelper::StandardShortcuts | KeySequenceHelper::GlobalShortcuts)
69 {
70 }
71 
72 KeySequenceHelper::KeySequenceHelper(QObject *parent)
73  : KeySequenceRecorder(nullptr, parent)
74  , d(new KeySequenceHelperPrivate(this))
75 {
76 }
77 
78 
79 KeySequenceHelper::~KeySequenceHelper()
80 {
81  delete d;
82 }
83 
84 bool KeySequenceHelper::isKeySequenceAvailable(const QKeySequence& keySequence) const
85 {
86  if (keySequence.isEmpty()) {
87  return true;
88  }
89  bool conflict = false;
90  if (d->checkAgainstShortcutTypes.testFlag(GlobalShortcuts)) {
91  conflict |= d->conflictWithGlobalShortcuts(keySequence);
92  }
93  if (d->checkAgainstShortcutTypes.testFlag(StandardShortcuts)) {
94  conflict |= d->conflictWithStandardShortcuts(keySequence);
95  }
96  return !conflict;
97 }
98 
99 
100 KeySequenceHelper::ShortcutTypes KeySequenceHelper::checkAgainstShortcutTypes()
101 {
102  return d->checkAgainstShortcutTypes;
103 }
104 
105 void KeySequenceHelper::setCheckAgainstShortcutTypes(KeySequenceHelper::ShortcutTypes types)
106 {
107  if (d->checkAgainstShortcutTypes != types) {
108  d->checkAgainstShortcutTypes = types;
109  }
110  Q_EMIT checkAgainstShortcutTypesChanged();
111 }
112 
113 bool KeySequenceHelperPrivate::conflictWithGlobalShortcuts(const QKeySequence &keySequence)
114 {
115 #ifdef Q_OS_WIN
116  //on windows F12 is reserved by the debugger at all times, so we can't use it for a global shortcut
117  if (KeySequenceHelper::GlobalShortcuts && keySequence.toString().contains(QLatin1String("F12"))) {
118  QString title = i18n("Reserved Shortcut");
119  QString message = i18n("The F12 key is reserved on Windows, so cannot be used for a global shortcut.\n"
120  "Please choose another one.");
121 
122  KMessageBox::sorry(nullptr, message, title);
123  return false;
124  }
125 #endif
126 
127  if (!(checkAgainstShortcutTypes & KeySequenceHelper::GlobalShortcuts)) {
128  return false;
129  }
130 
131  // Global shortcuts are on key+modifier shortcuts. They can clash with
132  // each of the keys of a multi key shortcut.
134  for (int i = 0; i < keySequence.count(); ++i) {
135  QKeySequence tmp(keySequence[i]);
136 
139  }
140  }
141 
142  if (!others.isEmpty()
143  && !KGlobalAccel::promptStealShortcutSystemwide(nullptr, others, keySequence)) {
144  return true;
145  }
146 
147  // The user approved stealing the shortcut. We have to steal
148  // it immediately because KAction::setGlobalShortcut() refuses
149  // to set a global shortcut that is already used. There is no
150  // error it just silently fails. So be nice because this is
151  // most likely the first action that is done in the slot
152  // listening to keySequenceChanged().
153  for (int i = 0; i < keySequence.count(); ++i) {
155  }
156  return false;
157 }
158 
159 bool KeySequenceHelperPrivate::conflictWithStandardShortcuts(const QKeySequence &keySequence)
160 {
161  if (!checkAgainstStandardShortcuts()) {
162  return false;
163  }
164 
166  if (ssc != KStandardShortcut::AccelNone && !stealStandardShortcut(ssc, keySequence)) {
167  return true;
168  }
169  return false;
170 }
171 
172 bool KeySequenceHelperPrivate::stealStandardShortcut(KStandardShortcut::StandardShortcut std, const QKeySequence &seq)
173 {
174  QString title = i18n("Conflict with Standard Application Shortcut");
175  QString message = i18n("The '%1' key combination is also used for the standard action "
176  "\"%2\" that some applications use.\n"
177  "Do you really want to use it as a global shortcut as well?",
179 
180  if (KMessageBox::warningContinueCancel(nullptr, message, title, KGuiItem(i18n("Reassign"))) != KMessageBox::Continue) {
181  return false;
182  }
183  return true;
184 }
185 
186 
187 bool KeySequenceHelper::keySequenceIsEmpty(const QKeySequence &keySequence)
188 {
189  return keySequence.isEmpty();
190 }
191 
192 QString KeySequenceHelper::keySequenceNativeText(const QKeySequence &keySequence)
193 {
194  return keySequence.toString(QKeySequence::NativeText);
195 }
196 
197 QWindow* KeySequenceHelper::renderWindow(QQuickWindow *quickWindow)
198 {
199  QWindow *renderWindow = QQuickRenderControl::renderWindowFor(quickWindow);
200  auto window = renderWindow ? renderWindow : quickWindow;
201  // If we have CppOwnership, set it explicitely to prevent the engine taking ownership of the window
202  // and crashing on teardown
205  }
206  return window;
207 }
KCOREADDONS_EXPORT void message(KMessage::MessageType messageType, const QString &text, const QString &caption=QString())
KJOBWIDGETS_EXPORT QWidget * window(KJob *job)
int count() const const
void setObjectOwnership(QObject *object, QQmlEngine::ObjectOwnership ownership)
QWindow * renderWindowFor(QQuickWindow *win, QPoint *offset)
StandardShortcut find(const QKeySequence &keySeq)
ButtonCode warningContinueCancel(QWidget *parent, const QString &text, const QString &caption=QString(), const KGuiItem &buttonContinue=KStandardGuiItem::cont(), const KGuiItem &buttonCancel=KStandardGuiItem::cancel(), const QString &dontAskAgainName=QString(), Options options=Notify)
QString label(StandardShortcut id)
bool isEmpty() const const
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
QQmlEngine::ObjectOwnership objectOwnership(QObject *object)
QString i18n(const char *text, const TYPE &arg...)
static QList< KGlobalShortcutInfo > getGlobalShortcutsByKey(const QKeySequence &seq)
QString toString(QKeySequence::SequenceFormat format) const const
static bool promptStealShortcutSystemwide(QWidget *parent, const QList< KGlobalShortcutInfo > &shortcuts, const QKeySequence &seq)
static void stealShortcutSystemwide(const QKeySequence &seq)
static bool isGlobalShortcutAvailable(const QKeySequence &seq, const QString &component=QString())
void sorry(QWidget *parent, const QString &text, const QString &caption=QString(), Options options=Notify)
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Mon Jan 25 2021 22:44:28 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.