5#include "private/qobject_p.h"
12#include <private/qkeymapper_p.h>
13#include <QtCore/qloggingcategory.h>
14#include <QtCore/qscopeguard.h>
46 {
return keySequence <
f.keySequence; }
58#ifdef Dump_QShortcutMap
66 return dbg <<
"QShortcutEntry(0x0)";
68 <<
"QShortcutEntry(" << se->keyseq
69 <<
"), id(" << se->id <<
"), enabled(" << se->enabled <<
"), autorepeat(" << se->autorepeat
70 <<
"), owner(" << se->owner <<
')';
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");
130 const auto it = std::upper_bound(
d->shortcuts.begin(),
d->shortcuts.end(), newEntry);
131 d->shortcuts.insert(
it, newEntry);
132 qCDebug(lcShortcutMap).nospace()
133 <<
"QShortcutMap::addShortcut(" << owner <<
", "
134 << keySequence <<
", " <<
context <<
") added shortcut with ID " <<
d->currentId;
150 int itemsRemoved = 0;
151 bool allOwners = (owner ==
nullptr);
153 bool allIds =
id == 0;
156 qCDebug(lcShortcutMap).nospace()
157 <<
"QShortcutMap::removeShortcut(" <<
id <<
", " << owner <<
", "
158 << keySequence <<
") removed " << itemsRemoved <<
" shortcuts(s)";
162 if (allOwners &&
allKeys && allIds) {
163 itemsRemoved =
d->shortcuts.size();
164 d->shortcuts.clear();
168 int i =
d->shortcuts.size()-1;
173 if ((allOwners ||
entry.owner == owner)
176 d->shortcuts.removeAt(
i);
197 int itemsChanged = 0;
198 bool allOwners = (owner ==
nullptr);
200 bool allIds =
id == 0;
202 int i =
d->shortcuts.size()-1;
206 if ((allOwners ||
entry.owner == owner)
216 qCDebug(lcShortcutMap).nospace()
217 <<
"QShortcutMap::setShortcutEnabled(" <<
enable <<
", " <<
id <<
", "
218 << owner <<
", " << keySequence <<
") = " << itemsChanged;
233 int itemsChanged = 0;
234 bool allOwners = (owner ==
nullptr);
236 bool allIds =
id == 0;
238 int i =
d->shortcuts.size()-1;
242 if ((allOwners ||
entry.owner == owner)
252 qCDebug(lcShortcutMap).nospace()
253 <<
"QShortcutMap::setShortcutAutoRepeat(" << on <<
", " <<
id <<
", "
254 << owner <<
", " << keySequence <<
") = " << itemsChanged;
261void QShortcutMap::resetState()
265 clearSequence(
d->currentSequences);
274 return d->currentState;
295 switch (nextState(e)) {
308 const int identicalMatches =
d->identicals.size();
313 return identicalMatches > 0;
316 Q_UNREACHABLE_RETURN(
false);
331 return d->currentState;
336 d->identicals.clear();
353 clearSequence(
d->currentSequences);
356 qCDebug(lcShortcutMap).nospace() <<
"QShortcutMap::nextState(" << e <<
") = " <<
result;
368 const auto itEnd =
d->shortcuts.cend();
369 auto it = std::lower_bound(
d->shortcuts.cbegin(), itEnd,
entry);
371 for (;
it != itEnd; ++
it) {
373 && (*it).correctContext() && (*it).enabled) {
392 if (!
d->shortcuts.size())
395 createNewSequences(e,
d->newEntries, ignoredModifiers);
396 qCDebug(lcShortcutMap) <<
"Possible input sequences:" <<
d->newEntries;
399 if (
d->newEntries ==
d->currentSequences) {
401 "QShortcutMap::find",
"New sequence to find identical to previous");
406 d->identicals.clear();
408 bool partialFound =
false;
409 bool identicalDisabledFound =
false;
410 QList<QKeySequence> okEntries;
412 for (
int i =
d->newEntries.size()-1;
i >= 0 ; --
i) {
414 qCDebug(lcShortcutMap) <<
"Looking for shortcuts matching" <<
entry.keySequence;
418 const auto itEnd =
d->shortcuts.constEnd();
419 auto it = std::lower_bound(
d->shortcuts.constBegin(), itEnd,
entry);
420 for (;
it != itEnd; ++
it) {
422 qCDebug(lcShortcutMap) <<
" -" <<
match <<
"for shortcut" <<
it->keySequence;
429 bestMatchForEntry =
qMax(bestMatchForEntry,
match);
431 if ((*it).correctContext()) {
434 d->identicals.append(&*
it);
436 identicalDisabledFound =
true;
439 if (
d->identicals.size())
443 partialFound |= (*it).enabled;
446 qCDebug(lcShortcutMap) <<
" - But context was not correct";
452 if (bestMatchForEntry >
result) {
454 qCDebug(lcShortcutMap) <<
"Found better match (" <<
d->newEntries <<
"), clearing key sequence list";
456 if (bestMatchForEntry && bestMatchForEntry >=
result) {
457 okEntries <<
d->newEntries.at(
i);
458 qCDebug(lcShortcutMap) <<
"Added ok key sequence" <<
d->newEntries;
462 if (
d->identicals.size()) {
464 }
else if (partialFound) {
466 }
else if (identicalDisabledFound) {
469 clearSequence(
d->currentSequences);
473 d->currentSequences = okEntries;
474 qCDebug(lcShortcutMap) <<
"Returning shortcut match == " <<
result;
483void QShortcutMap::clearSequence(QList<QKeySequence> &ksl)
486 d_func()->newEntries.clear();
493void QShortcutMap::createNewSequences(
QKeyEvent *e, QList<QKeySequence> &ksl,
int ignoredModifiers)
497 qCDebug(lcShortcutMap) <<
"Creating new sequences for" << e
498 <<
"with ignoredModifiers=" << Qt::KeyboardModifiers(ignoredModifiers);
499 int pkTotal = possibleKeys.size();
503 int ssActual =
d->currentSequences.size();
504 int ssTotal =
qMax(1, ssActual);
506 ksl.resize(pkTotal * ssTotal);
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;
515 curKsl.setKey(curSeq[0], 0);
516 curKsl.setKey(curSeq[1], 1);
517 curKsl.setKey(curSeq[2], 2);
518 curKsl.setKey(curSeq[3], 3);
525 const int key = possibleKeys.at(pkNum).toCombined();
534int QShortcutMap::translateModifiers(Qt::KeyboardModifiers
modifiers)
551QList<const QShortcutEntry*> QShortcutMap::matches()
const
554 return d->identicals;
560void QShortcutMap::dispatchEvent(
QKeyEvent *e)
563 if (!
d->identicals.size())
566 const QKeySequence &curKey =
d->identicals.at(0)->keySequence;
567 if (
d->prevSequence != curKey) {
569 d->prevSequence = curKey;
573 int i = 0, enabledShortcuts = 0;
574 QList<const QShortcutEntry*> ambiguousShortcuts;
575 while(i < d->identicals.size()) {
576 current =
d->identicals.at(
i);
579 if (lcShortcutMap().isDebugEnabled())
580 ambiguousShortcuts.append(current);
581 if (enabledShortcuts >
d->ambigCount + 1)
587 d->ambigCount = (
d->identicals.size() ==
i ? 0 :
d->ambigCount + 1);
593 if (lcShortcutMap().isDebugEnabled()) {
594 if (ambiguousShortcuts.size() > 1) {
595 qCDebug(lcShortcutMap) <<
"The following shortcuts are about to be activated ambiguously:";
597 qCDebug(lcShortcutMap).nospace() <<
"- " <<
entry->keySequence <<
" (belonging to " <<
entry->owner <<
")";
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 <<
')';
612 QList<QKeySequence>
keys;
613 for (
auto sequence :
d->shortcuts) {
614 bool addSequence =
false;
615 if (sequence.enabled) {
620 QObject *possibleWindow = sequence.owner;
621 while (possibleWindow) {
622 if (qobject_cast<QWindow *>(possibleWindow))
624 possibleWindow = possibleWindow->
parent();
631 while (possibleWidget->parent()) {
632 possibleWidget = possibleWidget->parent();
633 if (possibleWidget == sequence.owner) {
642 keys << sequence.keySequence;
653#if defined(Dump_QShortcutMap)
654void QShortcutMap::dumpMap()
const
657 for (
int i = 0;
i <
d->shortcuts.size(); ++
i)
658 qDebug().nospace() << &(
d->shortcuts.at(
i));
static bool sendEvent(QObject *receiver, QEvent *event)
Sends event event directly to receiver receiver, using the notify() function.
Type type() const
Returns the event type.
static QObject * focusObject()
Returns the QObject in currently active window that will be final receiver of events tied to focus,...
static QWindow * focusWindow()
Returns the QWindow that receives events tied to focus, such as key events.
static constexpr QKeyCombination fromCombined(int combined)
The QKeyEvent class describes a key event.
Qt::KeyboardModifiers modifiers() const
Returns the keyboard modifier flags that existed immediately after the event occurred.
QString text() const
Returns the Unicode text that this key generated.
bool isAutoRepeat() const
Returns true if this event comes from an auto-repeating key; returns false if it comes from an initia...
int key() const
Returns the code of the key that was pressed or released.
static QList< QKeyCombination > possibleKeys(const QKeyEvent *e)
The QKeySequence class encapsulates a key sequence as used by shortcuts.
SequenceMatch
\value NoMatch The key sequences are different; not even partially matching.
bool isEmpty() const
Returns true if the key sequence is empty; otherwise returns false.
void reserve(qsizetype size)
QObject * parent() const
Returns a pointer to the parent object.
The QShortcutEvent class provides an event which is generated when the user presses a key combination...
QList< QShortcutEntry > shortcuts
QList< QKeySequence > newEntries
QKeySequence prevSequence
QList< const QShortcutEntry * > identicals
QList< QKeySequence > currentSequences
QShortcutMapPrivate(QShortcutMap *parent)
QKeySequence::SequenceMatch currentState
bool hasShortcutForKeySequence(const QKeySequence &seq) const
int setShortcutEnabled(bool enable, int id, QObject *owner, const QKeySequence &key=QKeySequence())
int removeShortcut(int id, QObject *owner, const QKeySequence &key=QKeySequence())
int setShortcutAutoRepeat(bool on, int id, QObject *owner, const QKeySequence &key=QKeySequence())
int addShortcut(QObject *owner, const QKeySequence &key, Qt::ShortcutContext context, ContextMatcher matcher)
bool tryShortcut(QKeyEvent *e)
QList< QKeySequence > keySequences(bool getAll=false) const
QKeySequence::SequenceMatch state()
bool(* ContextMatcher)(QObject *object, Qt::ShortcutContext context)
qsizetype size() const noexcept
Returns the number of characters in this string.
EGLImageKHR int int EGLuint64KHR * modifiers
QSet< QString >::iterator it
Combined button and popup list for selecting options.
@ WidgetWithChildrenShortcut
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
constexpr const T & qMax(const T &a, const T &b)
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLenum GLsizei const GLuint GLboolean enabled
bool(* ContextMatcher)(QObject *, Qt::ShortcutContext)
#define Q_ASSERT_X(cond, x, msg)
QScopeGuard< typename std::decay< F >::type > qScopeGuard(F &&f)
[qScopeGuard]
static void allKeys(HKEY parentHandle, const QString &rSubKey, NameSet *result, REGSAM access=0)
static bool match(const uchar *found, uint foundLen, const char *target, uint targetLen)
#define Q_DECLARE_TYPEINFO(TYPE, FLAGS)
static const auto matcher
[0]
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
QShortcutMap::ContextMatcher contextMatcher
bool operator<(const QShortcutEntry &f) const