Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qshortcutmap.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5#include "private/qobject_p.h"
6#include "qkeysequence.h"
7#include "qdebug.h"
8#include "qevent.h"
9#include "qlist.h"
11#include "qwindow.h"
12#include <private/qkeymapper_p.h>
13#include <QtCore/qloggingcategory.h>
14#include <QtCore/qscopeguard.h>
15
16#include <algorithm>
17
19
20Q_STATIC_LOGGING_CATEGORY(lcShortcutMap, "qt.gui.shortcutmap")
21
22/* \internal
23 Entry data for QShortcutMap
24 Contains:
25 Keysequence for entry
26 Pointer to parent owning the sequence
27*/
28
30{
32 : keySequence(0), context(Qt::WindowShortcut), enabled(false), autorepeat(1), id(0), owner(nullptr), contextMatcher(nullptr)
33 {}
34
35 QShortcutEntry(const QKeySequence &k)
36 : keySequence(k), context(Qt::WindowShortcut), enabled(false), autorepeat(1), id(0), owner(nullptr), contextMatcher(nullptr)
37 {}
38
39 QShortcutEntry(QObject *o, const QKeySequence &k, Qt::ShortcutContext c, int i, bool a, QShortcutMap::ContextMatcher m)
41 {}
42
43 bool correctContext() const { return contextMatcher(owner, context); }
44
45 bool operator<(const QShortcutEntry &f) const
46 { return keySequence < f.keySequence; }
47
48 QKeySequence keySequence;
50 bool enabled : 1;
51 bool autorepeat : 1;
52 signed int id;
53 QObject *owner;
55};
57
58#ifdef Dump_QShortcutMap
59/*! \internal
60 QDebug operator<< for easy debug output of the shortcut entries.
61*/
62static QDebug &operator<<(QDebug &dbg, const QShortcutEntry *se)
63{
64 QDebugStateSaver saver(dbg);
65 if (!se)
66 return dbg << "QShortcutEntry(0x0)";
67 dbg.nospace()
68 << "QShortcutEntry(" << se->keyseq
69 << "), id(" << se->id << "), enabled(" << se->enabled << "), autorepeat(" << se->autorepeat
70 << "), owner(" << se->owner << ')';
71 return dbg;
72}
73#endif // Dump_QShortcutMap
74
75/* \internal
76 Private data for QShortcutMap
77*/
79{
80 Q_DECLARE_PUBLIC(QShortcutMap)
81
82public:
89 QShortcutMap *q_ptr; // Private's parent
90
91 QList<QShortcutEntry> shortcuts; // All shortcuts!
92
93 int currentId; // Global shortcut ID number
94 int ambigCount; // Index of last enabled ambiguous dispatch
96 QList<QKeySequence> currentSequences; // Sequence for the current state
97 QList<QKeySequence> newEntries;
98 QKeySequence prevSequence; // Sequence for the previous identical match
99 QList<const QShortcutEntry*> identicals; // Last identical matches
100};
101
102
103/*! \internal
104 QShortcutMap constructor.
105*/
106QShortcutMap::QShortcutMap()
107 : d_ptr(new QShortcutMapPrivate(this))
108{
109 resetState();
110}
111
112/*! \internal
113 QShortcutMap destructor.
114*/
115QShortcutMap::~QShortcutMap()
116{
117}
118
119/*! \internal
120 Adds a shortcut to the global map.
121 Returns the id of the newly added shortcut.
122*/
123int QShortcutMap::addShortcut(QObject *owner, const QKeySequence &keySequence, Qt::ShortcutContext context, ContextMatcher matcher)
124{
125 Q_ASSERT_X(owner, "QShortcutMap::addShortcut", "All shortcuts need an owner");
126 Q_ASSERT_X(!keySequence.isEmpty(), "QShortcutMap::addShortcut", "Cannot add keyless shortcuts to map");
127 Q_D(QShortcutMap);
128
129 QShortcutEntry newEntry(owner, keySequence, context, --(d->currentId), true, matcher);
130 const auto it = std::upper_bound(d->shortcuts.begin(), d->shortcuts.end(), newEntry);
131 d->shortcuts.insert(it, newEntry); // Insert sorted
132 qCDebug(lcShortcutMap).nospace()
133 << "QShortcutMap::addShortcut(" << owner << ", "
134 << keySequence << ", " << context << ") added shortcut with ID " << d->currentId;
135 return d->currentId;
136}
137
138/*! \internal
139 Removes a shortcut from the global map.
140 If \a owner is \nullptr, all entries in the map with the key sequence specified
141 is removed. If \a key is null, all sequences for \a owner is removed from
142 the map. If \a id is 0, any identical \a key sequences owned by \a owner
143 are removed.
144 Returns the number of sequences removed from the map.
145*/
146
147int QShortcutMap::removeShortcut(int id, QObject *owner, const QKeySequence &keySequence)
148{
149 Q_D(QShortcutMap);
150 int itemsRemoved = 0;
151 bool allOwners = (owner == nullptr);
152 bool allKeys = keySequence.isEmpty();
153 bool allIds = id == 0;
154
155 auto debug = qScopeGuard([&](){
156 qCDebug(lcShortcutMap).nospace()
157 << "QShortcutMap::removeShortcut(" << id << ", " << owner << ", "
158 << keySequence << ") removed " << itemsRemoved << " shortcuts(s)";
159 });
160
161 // Special case, remove everything
162 if (allOwners && allKeys && allIds) {
163 itemsRemoved = d->shortcuts.size();
164 d->shortcuts.clear();
165 return itemsRemoved;
166 }
167
168 int i = d->shortcuts.size()-1;
169 while (i>=0)
170 {
171 const QShortcutEntry &entry = d->shortcuts.at(i);
172 int entryId = entry.id;
173 if ((allOwners || entry.owner == owner)
174 && (allIds || entry.id == id)
175 && (allKeys || entry.keySequence == keySequence)) {
176 d->shortcuts.removeAt(i);
177 ++itemsRemoved;
178 }
179 if (id == entryId)
180 return itemsRemoved;
181 --i;
182 }
183 return itemsRemoved;
184}
185
186/*! \internal
187 Changes the enable state of a shortcut to \a enable.
188 If \a owner is \nullptr, all entries in the map with the key sequence specified
189 is removed. If \a key is null, all sequences for \a owner is removed from
190 the map. If \a id is 0, any identical \a key sequences owned by \a owner
191 are changed.
192 Returns the number of sequences which are matched in the map.
193*/
194int QShortcutMap::setShortcutEnabled(bool enable, int id, QObject *owner, const QKeySequence &keySequence)
195{
196 Q_D(QShortcutMap);
197 int itemsChanged = 0;
198 bool allOwners = (owner == nullptr);
199 bool allKeys = keySequence.isEmpty();
200 bool allIds = id == 0;
201
202 int i = d->shortcuts.size()-1;
203 while (i>=0)
204 {
205 const QShortcutEntry &entry = d->shortcuts.at(i);
206 if ((allOwners || entry.owner == owner)
207 && (allIds || entry.id == id)
208 && (allKeys || entry.keySequence == keySequence)) {
209 d->shortcuts[i].enabled = enable;
210 ++itemsChanged;
211 }
212 if (id == entry.id)
213 return itemsChanged;
214 --i;
215 }
216 qCDebug(lcShortcutMap).nospace()
217 << "QShortcutMap::setShortcutEnabled(" << enable << ", " << id << ", "
218 << owner << ", " << keySequence << ") = " << itemsChanged;
219 return itemsChanged;
220}
221
222/*! \internal
223 Changes the auto repeat state of a shortcut to \a enable.
224 If \a owner is \nullptr, all entries in the map with the key sequence specified
225 is removed. If \a key is null, all sequences for \a owner is removed from
226 the map. If \a id is 0, any identical \a key sequences owned by \a owner
227 are changed.
228 Returns the number of sequences which are matched in the map.
229*/
230int QShortcutMap::setShortcutAutoRepeat(bool on, int id, QObject *owner, const QKeySequence &keySequence)
231{
232 Q_D(QShortcutMap);
233 int itemsChanged = 0;
234 bool allOwners = (owner == nullptr);
235 bool allKeys = keySequence.isEmpty();
236 bool allIds = id == 0;
237
238 int i = d->shortcuts.size()-1;
239 while (i>=0)
240 {
241 QShortcutEntry entry = d->shortcuts.at(i);
242 if ((allOwners || entry.owner == owner)
243 && (allIds || entry.id == id)
244 && (allKeys || entry.keySequence == keySequence)) {
245 d->shortcuts[i].autorepeat = on;
246 ++itemsChanged;
247 }
248 if (id == entry.id)
249 return itemsChanged;
250 --i;
251 }
252 qCDebug(lcShortcutMap).nospace()
253 << "QShortcutMap::setShortcutAutoRepeat(" << on << ", " << id << ", "
254 << owner << ", " << keySequence << ") = " << itemsChanged;
255 return itemsChanged;
256}
257
258/*! \internal
259 Resets the state of the statemachine to NoMatch
260*/
261void QShortcutMap::resetState()
262{
263 Q_D(QShortcutMap);
264 d->currentState = QKeySequence::NoMatch;
265 clearSequence(d->currentSequences);
266}
267
268/*! \internal
269 Returns the current state of the statemachine
270*/
271QKeySequence::SequenceMatch QShortcutMap::state()
272{
273 Q_D(QShortcutMap);
274 return d->currentState;
275}
276
277/*! \internal
278 Uses nextState(QKeyEvent) to check for a grabbed shortcut.
279
280 If so, it is dispatched using dispatchEvent().
281
282 Returns true if a shortcut handled the event.
283
284 \sa nextState, dispatchEvent
285*/
286bool QShortcutMap::tryShortcut(QKeyEvent *e)
287{
288 Q_D(QShortcutMap);
289
290 if (e->key() == Qt::Key_unknown)
291 return false;
292
293 QKeySequence::SequenceMatch previousState = state();
294
295 switch (nextState(e)) {
296 case QKeySequence::NoMatch:
297 // In the case of going from a partial match to no match we handled the
298 // event, since we already stated that we did for the partial match. But
299 // in the normal case of directly going to no match we say we didn't.
300 return previousState == QKeySequence::PartialMatch;
301 case QKeySequence::PartialMatch:
302 // For a partial match we don't know yet if we will handle the shortcut
303 // but we need to say we did, so that we get the follow-up key-presses.
304 return true;
305 case QKeySequence::ExactMatch: {
306 // Save number of identical matches before dispatching
307 // to keep QShortcutMap and tryShortcut reentrant.
308 const int identicalMatches = d->identicals.size();
309 resetState();
310 dispatchEvent(e);
311 // If there are no identicals we've only found disabled shortcuts, and
312 // shouldn't say that we handled the event.
313 return identicalMatches > 0;
314 }
315 }
316 Q_UNREACHABLE_RETURN(false);
317}
318
319/*! \internal
320 Returns the next state of the statemachine
321 If return value is SequenceMatch::ExactMatch, then a call to matches()
322 will return a QObjects* list of all matching objects for the last matching
323 sequence.
324*/
325QKeySequence::SequenceMatch QShortcutMap::nextState(QKeyEvent *e)
326{
327 Q_D(QShortcutMap);
328 // Modifiers can NOT be shortcuts...
329 if (e->key() >= Qt::Key_Shift &&
330 e->key() <= Qt::Key_ScrollLock)
331 return d->currentState;
332
333 QKeySequence::SequenceMatch result = QKeySequence::NoMatch;
334
335 // We start fresh each time..
336 d->identicals.clear();
337
338 result = find(e);
339 if (result == QKeySequence::NoMatch && (e->modifiers() & Qt::KeypadModifier)) {
340 // Try to find a match without keypad modifier
341 result = find(e, Qt::KeypadModifier);
342 }
343 if (result == QKeySequence::NoMatch && e->modifiers() & Qt::ShiftModifier) {
344 // If Shift + Key_Backtab, also try Shift + Qt::Key_Tab
345 if (e->key() == Qt::Key_Backtab) {
346 QKeyEvent pe = QKeyEvent(e->type(), Qt::Key_Tab, e->modifiers(), e->text());
347 result = find(&pe);
348 }
349 }
350
351 // Does the new state require us to clean up?
352 if (result == QKeySequence::NoMatch)
353 clearSequence(d->currentSequences);
354 d->currentState = result;
355
356 qCDebug(lcShortcutMap).nospace() << "QShortcutMap::nextState(" << e << ") = " << result;
357 return result;
358}
359
360
361/*! \internal
362 Determines if an enabled shortcut has a matching key sequence.
363*/
364bool QShortcutMap::hasShortcutForKeySequence(const QKeySequence &seq) const
365{
366 Q_D(const QShortcutMap);
367 QShortcutEntry entry(seq); // needed for searching
368 const auto itEnd = d->shortcuts.cend();
369 auto it = std::lower_bound(d->shortcuts.cbegin(), itEnd, entry);
370
371 for (;it != itEnd; ++it) {
372 if (entry.keySequence.matches(it->keySequence) == QKeySequence::ExactMatch
373 && (*it).correctContext() && (*it).enabled) {
374 return true;
375 }
376 }
377
378 //end of the loop: we didn't find anything
379 return false;
380}
381
382/*! \internal
383 Returns the next state of the statemachine, based
384 on the new key event \a e.
385 Matches are appended to the list of identicals,
386 which can be access through matches().
387 \sa matches
388*/
389QKeySequence::SequenceMatch QShortcutMap::find(QKeyEvent *e, int ignoredModifiers)
390{
391 Q_D(QShortcutMap);
392 if (!d->shortcuts.size())
393 return QKeySequence::NoMatch;
394
395 createNewSequences(e, d->newEntries, ignoredModifiers);
396 qCDebug(lcShortcutMap) << "Possible input sequences:" << d->newEntries;
397
398 // Should never happen
399 if (d->newEntries == d->currentSequences) {
400 Q_ASSERT_X(e->key() != Qt::Key_unknown || e->text().size(),
401 "QShortcutMap::find", "New sequence to find identical to previous");
402 return QKeySequence::NoMatch;
403 }
404
405 // Looking for new identicals, scrap old
406 d->identicals.clear();
407
408 bool partialFound = false;
409 bool identicalDisabledFound = false;
410 QList<QKeySequence> okEntries;
411 QKeySequence::SequenceMatch result = QKeySequence::NoMatch;
412 for (int i = d->newEntries.size()-1; i >= 0 ; --i) {
413 QShortcutEntry entry(d->newEntries.at(i)); // needed for searching
414 qCDebug(lcShortcutMap) << "Looking for shortcuts matching" << entry.keySequence;
415
416 QKeySequence::SequenceMatch bestMatchForEntry = QKeySequence::NoMatch;
417
418 const auto itEnd = d->shortcuts.constEnd();
419 auto it = std::lower_bound(d->shortcuts.constBegin(), itEnd, entry);
420 for (; it != itEnd; ++it) {
421 QKeySequence::SequenceMatch match = entry.keySequence.matches(it->keySequence);
422 qCDebug(lcShortcutMap) << " -" << match << "for shortcut" << it->keySequence;
423
424 // If we got a valid match, there might still be more keys to check against,
425 // but if we get no match, we know that there are no more possible matches.
426 if (match == QKeySequence::NoMatch)
427 break;
428
429 bestMatchForEntry = qMax(bestMatchForEntry, match);
430
431 if ((*it).correctContext()) {
432 if (match == QKeySequence::ExactMatch) {
433 if ((*it).enabled)
434 d->identicals.append(&*it);
435 else
436 identicalDisabledFound = true;
437 } else if (match == QKeySequence::PartialMatch) {
438 // We don't need partials, if we have identicals
439 if (d->identicals.size())
440 break;
441 // We only care about enabled partials, so we don't consume
442 // key events when all partials are disabled!
443 partialFound |= (*it).enabled;
444 }
445 } else {
446 qCDebug(lcShortcutMap) << " - But context was not correct";
447 }
448 }
449
450 // If the type of match improves (ergo, NoMatch->Partial, or Partial->Exact), clear the
451 // previous list. If this match is equal or better than the last match, append to the list
452 if (bestMatchForEntry > result) {
453 okEntries.clear();
454 qCDebug(lcShortcutMap) << "Found better match (" << d->newEntries << "), clearing key sequence list";
455 }
456 if (bestMatchForEntry && bestMatchForEntry >= result) {
457 okEntries << d->newEntries.at(i);
458 qCDebug(lcShortcutMap) << "Added ok key sequence" << d->newEntries;
459 }
460 }
461
462 if (d->identicals.size()) {
463 result = QKeySequence::ExactMatch;
464 } else if (partialFound) {
465 result = QKeySequence::PartialMatch;
466 } else if (identicalDisabledFound) {
467 result = QKeySequence::ExactMatch;
468 } else {
469 clearSequence(d->currentSequences);
470 result = QKeySequence::NoMatch;
471 }
472 if (result != QKeySequence::NoMatch)
473 d->currentSequences = okEntries;
474 qCDebug(lcShortcutMap) << "Returning shortcut match == " << result;
475 return result;
476}
477
478/*! \internal
479 Clears \a seq to an empty QKeySequence.
480 Same as doing (the slower)
481 \snippet code/src_gui_kernel_qshortcutmap.cpp 0
482*/
483void QShortcutMap::clearSequence(QList<QKeySequence> &ksl)
484{
485 ksl.clear();
486 d_func()->newEntries.clear();
487}
488
489/*! \internal
490 Alters \a seq to the new sequence state, based on the
491 current sequence state, and the new key event \a e.
492*/
493void QShortcutMap::createNewSequences(QKeyEvent *e, QList<QKeySequence> &ksl, int ignoredModifiers)
494{
495 Q_D(QShortcutMap);
496 QList<QKeyCombination> possibleKeys = QKeyMapper::possibleKeys(e);
497 qCDebug(lcShortcutMap) << "Creating new sequences for" << e
498 << "with ignoredModifiers=" << Qt::KeyboardModifiers(ignoredModifiers);
499 int pkTotal = possibleKeys.size();
500 if (!pkTotal)
501 return;
502
503 int ssActual = d->currentSequences.size();
504 int ssTotal = qMax(1, ssActual);
505 // Resize to possible permutations of the current sequence(s).
506 ksl.resize(pkTotal * ssTotal);
507
508 int index = ssActual ? d->currentSequences.at(0).count() : 0;
509 for (int pkNum = 0; pkNum < pkTotal; ++pkNum) {
510 for (int ssNum = 0; ssNum < ssTotal; ++ssNum) {
511 int i = (pkNum * ssTotal) + ssNum;
512 QKeySequence &curKsl = ksl[i];
513 if (ssActual) {
514 const QKeySequence &curSeq = d->currentSequences.at(ssNum);
515 curKsl.setKey(curSeq[0], 0);
516 curKsl.setKey(curSeq[1], 1);
517 curKsl.setKey(curSeq[2], 2);
518 curKsl.setKey(curSeq[3], 3);
519 } else {
520 curKsl.setKey(QKeyCombination::fromCombined(0), 0);
521 curKsl.setKey(QKeyCombination::fromCombined(0), 1);
522 curKsl.setKey(QKeyCombination::fromCombined(0), 2);
523 curKsl.setKey(QKeyCombination::fromCombined(0), 3);
524 }
525 const int key = possibleKeys.at(pkNum).toCombined();
526 curKsl.setKey(QKeyCombination::fromCombined(key & ~ignoredModifiers), index);
527 }
528 }
529}
530
531/*! \internal
532 Converts keyboard button states into modifier states
533*/
534int QShortcutMap::translateModifiers(Qt::KeyboardModifiers modifiers)
535{
536 int result = 0;
537 if (modifiers & Qt::ShiftModifier)
538 result |= Qt::SHIFT;
539 if (modifiers & Qt::ControlModifier)
540 result |= Qt::CTRL;
541 if (modifiers & Qt::MetaModifier)
542 result |= Qt::META;
543 if (modifiers & Qt::AltModifier)
544 result |= Qt::ALT;
545 return result;
546}
547
548/*! \internal
549 Returns the list of QShortcutEntry's matching the last Identical state.
550*/
551QList<const QShortcutEntry*> QShortcutMap::matches() const
552{
553 Q_D(const QShortcutMap);
554 return d->identicals;
555}
556
557/*! \internal
558 Dispatches QShortcutEvents to widgets who grabbed the matched key sequence.
559*/
560void QShortcutMap::dispatchEvent(QKeyEvent *e)
561{
562 Q_D(QShortcutMap);
563 if (!d->identicals.size())
564 return;
565
566 const QKeySequence &curKey = d->identicals.at(0)->keySequence;
567 if (d->prevSequence != curKey) {
568 d->ambigCount = 0;
569 d->prevSequence = curKey;
570 }
571 // Find next
572 const QShortcutEntry *current = nullptr, *next = nullptr;
573 int i = 0, enabledShortcuts = 0;
574 QList<const QShortcutEntry*> ambiguousShortcuts;
575 while(i < d->identicals.size()) {
576 current = d->identicals.at(i);
577 if (current->enabled || !next){
578 ++enabledShortcuts;
579 if (lcShortcutMap().isDebugEnabled())
580 ambiguousShortcuts.append(current);
581 if (enabledShortcuts > d->ambigCount + 1)
582 break;
583 next = current;
584 }
585 ++i;
586 }
587 d->ambigCount = (d->identicals.size() == i ? 0 : d->ambigCount + 1);
588 // Don't trigger shortcut if we're autorepeating and the shortcut is
589 // grabbed with not accepting autorepeats.
590 if (!next || (e->isAutoRepeat() && !next->autorepeat))
591 return;
592 // Dispatch next enabled
593 if (lcShortcutMap().isDebugEnabled()) {
594 if (ambiguousShortcuts.size() > 1) {
595 qCDebug(lcShortcutMap) << "The following shortcuts are about to be activated ambiguously:";
596 for (const QShortcutEntry *entry : std::as_const(ambiguousShortcuts))
597 qCDebug(lcShortcutMap).nospace() << "- " << entry->keySequence << " (belonging to " << entry->owner << ")";
598 }
599
600 qCDebug(lcShortcutMap).nospace()
601 << "QShortcutMap::dispatchEvent(): Sending QShortcutEvent(\""
602 << next->keySequence.toString() << "\", " << next->id << ", "
603 << static_cast<bool>(enabledShortcuts>1) << ") to object(" << next->owner << ')';
604 }
605 QShortcutEvent se(next->keySequence, next->id, enabledShortcuts > 1);
606 QCoreApplication::sendEvent(const_cast<QObject *>(next->owner), &se);
607}
608
609QList<QKeySequence> QShortcutMap::keySequences(bool getAll) const
610{
611 Q_D(const QShortcutMap);
612 QList<QKeySequence> keys;
613 for (auto sequence : d->shortcuts) {
614 bool addSequence = false;
615 if (sequence.enabled) {
616 if (getAll || sequence.context == Qt::ApplicationShortcut ||
617 sequence.owner == QGuiApplication::focusObject()) {
618 addSequence = true;
619 } else {
620 QObject *possibleWindow = sequence.owner;
621 while (possibleWindow) {
622 if (qobject_cast<QWindow *>(possibleWindow))
623 break;
624 possibleWindow = possibleWindow->parent();
625 }
626 if (possibleWindow == QGuiApplication::focusWindow()) {
627 if (sequence.context == Qt::WindowShortcut) {
628 addSequence = true;
629 } else if (sequence.context == Qt::WidgetWithChildrenShortcut) {
630 QObject *possibleWidget = QGuiApplication::focusObject();
631 while (possibleWidget->parent()) {
632 possibleWidget = possibleWidget->parent();
633 if (possibleWidget == sequence.owner) {
634 addSequence = true;
635 break;
636 }
637 }
638 }
639 }
640 }
641 if (addSequence)
642 keys << sequence.keySequence;
643 }
644 }
645 return keys;
646
647}
648
649/* \internal
650 QShortcutMap dump function, only available when DEBUG_QSHORTCUTMAP is
651 defined.
652*/
653#if defined(Dump_QShortcutMap)
654void QShortcutMap::dumpMap() const
655{
656 Q_D(const QShortcutMap);
657 for (int i = 0; i < d->shortcuts.size(); ++i)
658 qDebug().nospace() << &(d->shortcuts.at(i));
659}
660#endif
661
662QT_END_NAMESPACE
Definition qlist.h:80
QList< const QShortcutEntry * > identicals
QKeySequence prevSequence
QList< QKeySequence > newEntries
QList< QShortcutEntry > shortcuts
QList< QKeySequence > currentSequences
QKeySequence::SequenceMatch currentState
Q_STATIC_LOGGING_CATEGORY(lcAccessibilityCore, "qt.accessibility.core")
Q_DECLARE_TYPEINFO(QShortcutEntry, Q_RELOCATABLE_TYPE)
QShortcutEntry(QObject *o, const QKeySequence &k, Qt::ShortcutContext c, int i, bool a, QShortcutMap::ContextMatcher m)
bool correctContext() const
QShortcutEntry(const QKeySequence &k)
Qt::ShortcutContext context
QKeySequence keySequence
bool operator<(const QShortcutEntry &f) const