qshortcutmap.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/gui/kernel/qshortcutmap.cpp
Source codeSwitch to Preprocessed file
LineSourceCount
1/****************************************************************************-
2**-
3** Copyright (C) 2016 The Qt Company Ltd.-
4** Contact: https://www.qt.io/licensing/-
5**-
6** This file is part of the QtGui module of the Qt Toolkit.-
7**-
8** $QT_BEGIN_LICENSE:LGPL$-
9** Commercial License Usage-
10** Licensees holding valid commercial Qt licenses may use this file in-
11** accordance with the commercial license agreement provided with the-
12** Software or, alternatively, in accordance with the terms contained in-
13** a written agreement between you and The Qt Company. For licensing terms-
14** and conditions see https://www.qt.io/terms-conditions. For further-
15** information use the contact form at https://www.qt.io/contact-us.-
16**-
17** GNU Lesser General Public License Usage-
18** Alternatively, this file may be used under the terms of the GNU Lesser-
19** General Public License version 3 as published by the Free Software-
20** Foundation and appearing in the file LICENSE.LGPL3 included in the-
21** packaging of this file. Please review the following information to-
22** ensure the GNU Lesser General Public License version 3 requirements-
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.-
24**-
25** GNU General Public License Usage-
26** Alternatively, this file may be used under the terms of the GNU-
27** General Public License version 2.0 or (at your option) the GNU General-
28** Public license version 3 or any later version approved by the KDE Free-
29** Qt Foundation. The licenses are as published by the Free Software-
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3-
31** included in the packaging of this file. Please review the following-
32** information to ensure the GNU General Public License requirements will-
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and-
34** https://www.gnu.org/licenses/gpl-3.0.html.-
35**-
36** $QT_END_LICENSE$-
37**-
38****************************************************************************/-
39-
40#include "qshortcutmap_p.h"-
41#include "private/qobject_p.h"-
42#include "qkeysequence.h"-
43#include "qdebug.h"-
44#include "qevent.h"-
45#include "qvector.h"-
46#include "qcoreapplication.h"-
47#include <private/qkeymapper_p.h>-
48-
49#include <algorithm>-
50-
51#ifndef QT_NO_SHORTCUT-
52-
53QT_BEGIN_NAMESPACE-
54-
55// To enable verbose output uncomment below-
56//#define DEBUG_QSHORTCUTMAP-
57-
58/* \internal-
59 Entry data for QShortcutMap-
60 Contains:-
61 Keysequence for entry-
62 Pointer to parent owning the sequence-
63*/-
64-
65struct QShortcutEntry-
66{-
67 QShortcutEntry()-
68 : keyseq(0), context(Qt::WindowShortcut), enabled(false), autorepeat(1), id(0), owner(0), contextMatcher(0)-
69 {}
never executed: end of block
0
70-
71 QShortcutEntry(const QKeySequence &k)-
72 : keyseq(k), context(Qt::WindowShortcut), enabled(false), autorepeat(1), id(0), owner(0), contextMatcher(0)-
73 {}
never executed: end of block
0
74-
75 QShortcutEntry(QObject *o, const QKeySequence &k, Qt::ShortcutContext c, int i, bool a, QShortcutMap::ContextMatcher m)-
76 : keyseq(k), context(c), enabled(true), autorepeat(a), id(i), owner(o), contextMatcher(m)-
77 {}
never executed: end of block
0
78-
79 bool correctContext() const { return contextMatcher(owner, context); }
never executed: return contextMatcher(owner, context);
0
80-
81 bool operator<(const QShortcutEntry &f) const-
82 { return keyseq < f.keyseq; }
never executed: return keyseq < f.keyseq;
0
83-
84 QKeySequence keyseq;-
85 Qt::ShortcutContext context;-
86 bool enabled : 1;-
87 bool autorepeat : 1;-
88 signed int id;-
89 QObject *owner;-
90 QShortcutMap::ContextMatcher contextMatcher;-
91};-
92Q_DECLARE_TYPEINFO(QShortcutEntry, Q_MOVABLE_TYPE);-
93-
94#ifdef Dump_QShortcutMap-
95/*! \internal-
96 QDebug operator<< for easy debug output of the shortcut entries.-
97*/-
98static QDebug &operator<<(QDebug &dbg, const QShortcutEntry *se)-
99{-
100 QDebugStateSaver saver(dbg);-
101 if (!se)-
102 return dbg << "QShortcutEntry(0x0)";-
103 dbg.nospace()-
104 << "QShortcutEntry(" << se->keyseq-
105 << "), id(" << se->id << "), enabled(" << se->enabled << "), autorepeat(" << se->autorepeat-
106 << "), owner(" << se->owner << ')';-
107 return dbg;-
108}-
109#endif // Dump_QShortcutMap-
110-
111/* \internal-
112 Private data for QShortcutMap-
113*/-
114class QShortcutMapPrivate-
115{-
116 Q_DECLARE_PUBLIC(QShortcutMap)-
117-
118public:-
119 QShortcutMapPrivate(QShortcutMap* parent)-
120 : q_ptr(parent), currentId(0), ambigCount(0), currentState(QKeySequence::NoMatch)-
121 {-
122 identicals.reserve(10);-
123 currentSequences.reserve(10);-
124 }
never executed: end of block
0
125 QShortcutMap *q_ptr; // Private's parent-
126-
127 QVector<QShortcutEntry> sequences; // All sequences!-
128-
129 int currentId; // Global shortcut ID number-
130 int ambigCount; // Index of last enabled ambiguous dispatch-
131 QKeySequence::SequenceMatch currentState;-
132 QVector<QKeySequence> currentSequences; // Sequence for the current state-
133 QVector<QKeySequence> newEntries;-
134 QKeySequence prevSequence; // Sequence for the previous identical match-
135 QVector<const QShortcutEntry*> identicals; // Last identical matches-
136};-
137-
138-
139/*! \internal-
140 QShortcutMap constructor.-
141*/-
142QShortcutMap::QShortcutMap()-
143 : d_ptr(new QShortcutMapPrivate(this))-
144{-
145 resetState();-
146}
never executed: end of block
0
147-
148/*! \internal-
149 QShortcutMap destructor.-
150*/-
151QShortcutMap::~QShortcutMap()-
152{-
153}-
154-
155/*! \internal-
156 Adds a shortcut to the global map.-
157 Returns the id of the newly added shortcut.-
158*/-
159int QShortcutMap::addShortcut(QObject *owner, const QKeySequence &key, Qt::ShortcutContext context, ContextMatcher matcher)-
160{-
161 Q_ASSERT_X(owner, "QShortcutMap::addShortcut", "All shortcuts need an owner");-
162 Q_ASSERT_X(!key.isEmpty(), "QShortcutMap::addShortcut", "Cannot add keyless shortcuts to map");-
163 Q_D(QShortcutMap);-
164-
165 QShortcutEntry newEntry(owner, key, context, --(d->currentId), true, matcher);-
166 const auto it = std::upper_bound(d->sequences.begin(), d->sequences.end(), newEntry);-
167 d->sequences.insert(it, newEntry); // Insert sorted-
168#if defined(DEBUG_QSHORTCUTMAP)-
169 qDebug().nospace()-
170 << "QShortcutMap::addShortcut(" << owner << ", "-
171 << key << ", " << context << ") = " << d->currentId;-
172#endif-
173 return d->currentId;
never executed: return d->currentId;
0
174}-
175-
176/*! \internal-
177 Removes a shortcut from the global map.-
178 If \a owner is 0, all entries in the map with the key sequence specified-
179 is removed. If \a key is null, all sequences for \a owner is removed from-
180 the map. If \a id is 0, any identical \a key sequences owned by \a owner-
181 are removed.-
182 Returns the number of sequences removed from the map.-
183*/-
184-
185int QShortcutMap::removeShortcut(int id, QObject *owner, const QKeySequence &key)-
186{-
187 Q_D(QShortcutMap);-
188 int itemsRemoved = 0;-
189 bool allOwners = (owner == 0);-
190 bool allKeys = key.isEmpty();-
191 bool allIds = id == 0;-
192-
193 // Special case, remove everything-
194 if (allOwners && allKeys && allIds) {
allOwnersDescription
TRUEnever evaluated
FALSEnever evaluated
allKeysDescription
TRUEnever evaluated
FALSEnever evaluated
allIdsDescription
TRUEnever evaluated
FALSEnever evaluated
0
195 itemsRemoved = d->sequences.size();-
196 d->sequences.clear();-
197 return itemsRemoved;
never executed: return itemsRemoved;
0
198 }-
199-
200 int i = d->sequences.size()-1;-
201 while (i>=0)
i>=0Description
TRUEnever evaluated
FALSEnever evaluated
0
202 {-
203 const QShortcutEntry &entry = d->sequences.at(i);-
204 int entryId = entry.id;-
205 if ((allOwners || entry.owner == owner)
allOwnersDescription
TRUEnever evaluated
FALSEnever evaluated
entry.owner == ownerDescription
TRUEnever evaluated
FALSEnever evaluated
0
206 && (allIds || entry.id == id)
allIdsDescription
TRUEnever evaluated
FALSEnever evaluated
entry.id == idDescription
TRUEnever evaluated
FALSEnever evaluated
0
207 && (allKeys || entry.keyseq == key)) {
allKeysDescription
TRUEnever evaluated
FALSEnever evaluated
entry.keyseq == keyDescription
TRUEnever evaluated
FALSEnever evaluated
0
208 d->sequences.removeAt(i);-
209 ++itemsRemoved;-
210 }
never executed: end of block
0
211 if (id == entryId)
id == entryIdDescription
TRUEnever evaluated
FALSEnever evaluated
0
212 return itemsRemoved;
never executed: return itemsRemoved;
0
213 --i;-
214 }
never executed: end of block
0
215#if defined(DEBUG_QSHORTCUTMAP)-
216 qDebug().nospace()-
217 << "QShortcutMap::removeShortcut(" << id << ", " << owner << ", "-
218 << key << ") = " << itemsRemoved;-
219#endif-
220 return itemsRemoved;
never executed: return itemsRemoved;
0
221}-
222-
223/*! \internal-
224 Changes the enable state of a shortcut to \a enable.-
225 If \a owner is 0, all entries in the map with the key sequence specified-
226 is removed. If \a key is null, all sequences for \a owner is removed from-
227 the map. If \a id is 0, any identical \a key sequences owned by \a owner-
228 are changed.-
229 Returns the number of sequences which are matched in the map.-
230*/-
231int QShortcutMap::setShortcutEnabled(bool enable, int id, QObject *owner, const QKeySequence &key)-
232{-
233 Q_D(QShortcutMap);-
234 int itemsChanged = 0;-
235 bool allOwners = (owner == 0);-
236 bool allKeys = key.isEmpty();-
237 bool allIds = id == 0;-
238-
239 int i = d->sequences.size()-1;-
240 while (i>=0)
i>=0Description
TRUEnever evaluated
FALSEnever evaluated
0
241 {-
242 QShortcutEntry entry = d->sequences.at(i);-
243 if ((allOwners || entry.owner == owner)
allOwnersDescription
TRUEnever evaluated
FALSEnever evaluated
entry.owner == ownerDescription
TRUEnever evaluated
FALSEnever evaluated
0
244 && (allIds || entry.id == id)
allIdsDescription
TRUEnever evaluated
FALSEnever evaluated
entry.id == idDescription
TRUEnever evaluated
FALSEnever evaluated
0
245 && (allKeys || entry.keyseq == key)) {
allKeysDescription
TRUEnever evaluated
FALSEnever evaluated
entry.keyseq == keyDescription
TRUEnever evaluated
FALSEnever evaluated
0
246 d->sequences[i].enabled = enable;-
247 ++itemsChanged;-
248 }
never executed: end of block
0
249 if (id == entry.id)
id == entry.idDescription
TRUEnever evaluated
FALSEnever evaluated
0
250 return itemsChanged;
never executed: return itemsChanged;
0
251 --i;-
252 }
never executed: end of block
0
253#if defined(DEBUG_QSHORTCUTMAP)-
254 qDebug().nospace()-
255 << "QShortcutMap::setShortcutEnabled(" << enable << ", " << id << ", "-
256 << owner << ", " << key << ") = " << itemsChanged;-
257#endif-
258 return itemsChanged;
never executed: return itemsChanged;
0
259}-
260-
261/*! \internal-
262 Changes the auto repeat state of a shortcut to \a enable.-
263 If \a owner is 0, all entries in the map with the key sequence specified-
264 is removed. If \a key is null, all sequences for \a owner is removed from-
265 the map. If \a id is 0, any identical \a key sequences owned by \a owner-
266 are changed.-
267 Returns the number of sequences which are matched in the map.-
268*/-
269int QShortcutMap::setShortcutAutoRepeat(bool on, int id, QObject *owner, const QKeySequence &key)-
270{-
271 Q_D(QShortcutMap);-
272 int itemsChanged = 0;-
273 bool allOwners = (owner == 0);-
274 bool allKeys = key.isEmpty();-
275 bool allIds = id == 0;-
276-
277 int i = d->sequences.size()-1;-
278 while (i>=0)
i>=0Description
TRUEnever evaluated
FALSEnever evaluated
0
279 {-
280 QShortcutEntry entry = d->sequences.at(i);-
281 if ((allOwners || entry.owner == owner)
allOwnersDescription
TRUEnever evaluated
FALSEnever evaluated
entry.owner == ownerDescription
TRUEnever evaluated
FALSEnever evaluated
0
282 && (allIds || entry.id == id)
allIdsDescription
TRUEnever evaluated
FALSEnever evaluated
entry.id == idDescription
TRUEnever evaluated
FALSEnever evaluated
0
283 && (allKeys || entry.keyseq == key)) {
allKeysDescription
TRUEnever evaluated
FALSEnever evaluated
entry.keyseq == keyDescription
TRUEnever evaluated
FALSEnever evaluated
0
284 d->sequences[i].autorepeat = on;-
285 ++itemsChanged;-
286 }
never executed: end of block
0
287 if (id == entry.id)
id == entry.idDescription
TRUEnever evaluated
FALSEnever evaluated
0
288 return itemsChanged;
never executed: return itemsChanged;
0
289 --i;-
290 }
never executed: end of block
0
291#if defined(DEBUG_QSHORTCUTMAP)-
292 qDebug().nospace()-
293 << "QShortcutMap::setShortcutAutoRepeat(" << on << ", " << id << ", "-
294 << owner << ", " << key << ") = " << itemsChanged;-
295#endif-
296 return itemsChanged;
never executed: return itemsChanged;
0
297}-
298-
299/*! \internal-
300 Resets the state of the statemachine to NoMatch-
301*/-
302void QShortcutMap::resetState()-
303{-
304 Q_D(QShortcutMap);-
305 d->currentState = QKeySequence::NoMatch;-
306 clearSequence(d->currentSequences);-
307}
never executed: end of block
0
308-
309/*! \internal-
310 Returns the current state of the statemachine-
311*/-
312QKeySequence::SequenceMatch QShortcutMap::state()-
313{-
314 Q_D(QShortcutMap);-
315 return d->currentState;
never executed: return d->currentState;
0
316}-
317-
318/*! \internal-
319 Uses nextState(QKeyEvent) to check for a grabbed shortcut.-
320-
321 If so, it is dispatched using dispatchEvent().-
322-
323 Returns true if a shortcut handled the event.-
324-
325 \sa nextState, dispatchEvent-
326*/-
327bool QShortcutMap::tryShortcut(QKeyEvent *e)-
328{-
329 Q_D(QShortcutMap);-
330-
331 if (e->key() == Qt::Key_unknown)
e->key() == Qt::Key_unknownDescription
TRUEnever evaluated
FALSEnever evaluated
0
332 return false;
never executed: return false;
0
333-
334 QKeySequence::SequenceMatch previousState = state();-
335-
336 switch (nextState(e)) {-
337 case QKeySequence::NoMatch:
never executed: case QKeySequence::NoMatch:
0
338 // In the case of going from a partial match to no match we handled the-
339 // event, since we already stated that we did for the partial match. But-
340 // in the normal case of directly going to no match we say we didn't.-
341 return previousState == QKeySequence::PartialMatch;
never executed: return previousState == QKeySequence::PartialMatch;
0
342 case QKeySequence::PartialMatch:
never executed: case QKeySequence::PartialMatch:
0
343 // For a partial match we don't know yet if we will handle the shortcut-
344 // but we need to say we did, so that we get the follow-up key-presses.-
345 return true;
never executed: return true;
0
346 case QKeySequence::ExactMatch: {
never executed: case QKeySequence::ExactMatch:
0
347 // Save number of identical matches before dispatching-
348 // to keep QShortcutMap and tryShortcut reentrant.-
349 const int identicalMatches = d->identicals.count();-
350 resetState();-
351 dispatchEvent(e);-
352 // If there are no identicals we've only found disabled shortcuts, and-
353 // shouldn't say that we handled the event.-
354 return identicalMatches > 0;
never executed: return identicalMatches > 0;
0
355 }-
356 }-
357 Q_UNREACHABLE();-
358 return false;
never executed: return false;
0
359}-
360-
361/*! \internal-
362 Returns the next state of the statemachine-
363 If return value is SequenceMatch::ExactMatch, then a call to matches()-
364 will return a QObjects* list of all matching objects for the last matching-
365 sequence.-
366*/-
367QKeySequence::SequenceMatch QShortcutMap::nextState(QKeyEvent *e)-
368{-
369 Q_D(QShortcutMap);-
370 // Modifiers can NOT be shortcuts...-
371 if (e->key() >= Qt::Key_Shift &&
e->key() >= Qt::Key_ShiftDescription
TRUEnever evaluated
FALSEnever evaluated
0
372 e->key() <= Qt::Key_Alt)
e->key() <= Qt::Key_AltDescription
TRUEnever evaluated
FALSEnever evaluated
0
373 return d->currentState;
never executed: return d->currentState;
0
374-
375 QKeySequence::SequenceMatch result = QKeySequence::NoMatch;-
376-
377 // We start fresh each time..-
378 d->identicals.clear();-
379-
380 result = find(e);-
381 if (result == QKeySequence::NoMatch && (e->modifiers() & Qt::KeypadModifier)) {
result == QKey...uence::NoMatchDescription
TRUEnever evaluated
FALSEnever evaluated
(e->modifiers(...eypadModifier)Description
TRUEnever evaluated
FALSEnever evaluated
0
382 // Try to find a match without keypad modifier-
383 result = find(e, Qt::KeypadModifier);-
384 }
never executed: end of block
0
385 if (result == QKeySequence::NoMatch && e->modifiers() & Qt::ShiftModifier) {
result == QKey...uence::NoMatchDescription
TRUEnever evaluated
FALSEnever evaluated
e->modifiers()...:ShiftModifierDescription
TRUEnever evaluated
FALSEnever evaluated
0
386 // If Shift + Key_Backtab, also try Shift + Qt::Key_Tab-
387 if (e->key() == Qt::Key_Backtab) {
e->key() == Qt::Key_BacktabDescription
TRUEnever evaluated
FALSEnever evaluated
0
388 QKeyEvent pe = QKeyEvent(e->type(), Qt::Key_Tab, e->modifiers(), e->text());-
389 result = find(&pe);-
390 }
never executed: end of block
0
391 }
never executed: end of block
0
392-
393 // Does the new state require us to clean up?-
394 if (result == QKeySequence::NoMatch)
result == QKey...uence::NoMatchDescription
TRUEnever evaluated
FALSEnever evaluated
0
395 clearSequence(d->currentSequences);
never executed: clearSequence(d->currentSequences);
0
396 d->currentState = result;-
397-
398#if defined(DEBUG_QSHORTCUTMAP)-
399 qDebug().nospace() << "QShortcutMap::nextState(" << e << ") = " << result;-
400#endif-
401 return result;
never executed: return result;
0
402}-
403-
404-
405/*! \internal-
406 Determines if an enabled shortcut has a matcing key sequence.-
407*/-
408bool QShortcutMap::hasShortcutForKeySequence(const QKeySequence &seq) const-
409{-
410 Q_D(const QShortcutMap);-
411 QShortcutEntry entry(seq); // needed for searching-
412 const auto itEnd = d->sequences.cend();-
413 auto it = std::lower_bound(d->sequences.cbegin(), itEnd, entry);-
414-
415 for (;it != itEnd; ++it) {
it != itEndDescription
TRUEnever evaluated
FALSEnever evaluated
0
416 if (matches(entry.keyseq, (*it).keyseq) == QKeySequence::ExactMatch && (*it).correctContext() && (*it).enabled) {
matches(entry....ce::ExactMatchDescription
TRUEnever evaluated
FALSEnever evaluated
(*it).correctContext()Description
TRUEnever evaluated
FALSEnever evaluated
(*it).enabledDescription
TRUEnever evaluated
FALSEnever evaluated
0
417 return true;
never executed: return true;
0
418 }-
419 }
never executed: end of block
0
420-
421 //end of the loop: we didn't find anything-
422 return false;
never executed: return false;
0
423}-
424-
425/*! \internal-
426 Returns the next state of the statemachine, based-
427 on the new key event \a e.-
428 Matches are appended to the vector of identicals,-
429 which can be access through matches().-
430 \sa matches-
431*/-
432QKeySequence::SequenceMatch QShortcutMap::find(QKeyEvent *e, int ignoredModifiers)-
433{-
434 Q_D(QShortcutMap);-
435 if (!d->sequences.count())
!d->sequences.count()Description
TRUEnever evaluated
FALSEnever evaluated
0
436 return QKeySequence::NoMatch;
never executed: return QKeySequence::NoMatch;
0
437-
438 createNewSequences(e, d->newEntries, ignoredModifiers);-
439#if defined(DEBUG_QSHORTCUTMAP)-
440 qDebug() << "Possible shortcut key sequences:" << d->newEntries;-
441#endif-
442-
443 // Should never happen-
444 if (d->newEntries == d->currentSequences) {
d->newEntries ...rrentSequencesDescription
TRUEnever evaluated
FALSEnever evaluated
0
445 Q_ASSERT_X(e->key() != Qt::Key_unknown || e->text().length(),-
446 "QShortcutMap::find", "New sequence to find identical to previous");-
447 return QKeySequence::NoMatch;
never executed: return QKeySequence::NoMatch;
0
448 }-
449-
450 // Looking for new identicals, scrap old-
451 d->identicals.clear();-
452-
453 bool partialFound = false;-
454 bool identicalDisabledFound = false;-
455 QVector<QKeySequence> okEntries;-
456 int result = QKeySequence::NoMatch;-
457 for (int i = d->newEntries.count()-1; i >= 0 ; --i) {
i >= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
458 QShortcutEntry entry(d->newEntries.at(i)); // needed for searching-
459 const auto itEnd = d->sequences.constEnd();-
460 auto it = std::lower_bound(d->sequences.constBegin(), itEnd, entry);-
461-
462 int oneKSResult = QKeySequence::NoMatch;-
463 int tempRes = QKeySequence::NoMatch;-
464 do {-
465 if (it == itEnd)
it == itEndDescription
TRUEnever evaluated
FALSEnever evaluated
0
466 break;
never executed: break;
0
467 tempRes = matches(entry.keyseq, (*it).keyseq);-
468 oneKSResult = qMax(oneKSResult, tempRes);-
469 if (tempRes != QKeySequence::NoMatch && (*it).correctContext()) {
tempRes != QKe...uence::NoMatchDescription
TRUEnever evaluated
FALSEnever evaluated
(*it).correctContext()Description
TRUEnever evaluated
FALSEnever evaluated
0
470 if (tempRes == QKeySequence::ExactMatch) {
tempRes == QKe...ce::ExactMatchDescription
TRUEnever evaluated
FALSEnever evaluated
0
471 if ((*it).enabled)
(*it).enabledDescription
TRUEnever evaluated
FALSEnever evaluated
0
472 d->identicals.append(&*it);
never executed: d->identicals.append(&*it);
0
473 else-
474 identicalDisabledFound = true;
never executed: identicalDisabledFound = true;
0
475 } else if (tempRes == QKeySequence::PartialMatch) {
tempRes == QKe...::PartialMatchDescription
TRUEnever evaluated
FALSEnever evaluated
0
476 // We don't need partials, if we have identicals-
477 if (d->identicals.size())
d->identicals.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
478 break;
never executed: break;
0
479 // We only care about enabled partials, so we don't consume-
480 // key events when all partials are disabled!-
481 partialFound |= (*it).enabled;-
482 }
never executed: end of block
0
483 }
never executed: end of block
0
484 ++it;-
485 // If we got a valid match on this run, there might still be more keys to check against,-
486 // so we'll loop once more. If we get NoMatch, there's guaranteed no more possible-
487 // matches in the shortcutmap.-
488 } while (tempRes != QKeySequence::NoMatch);
never executed: end of block
tempRes != QKe...uence::NoMatchDescription
TRUEnever evaluated
FALSEnever evaluated
0
489-
490 // If the type of match improves (ergo, NoMatch->Partial, or Partial->Exact), clear the-
491 // previous list. If this match is equal or better than the last match, append to the list-
492 if (oneKSResult > result) {
oneKSResult > resultDescription
TRUEnever evaluated
FALSEnever evaluated
0
493 okEntries.clear();-
494#if defined(DEBUG_QSHORTCUTMAP)-
495 qDebug() << "Found better match (" << d->newEntries << "), clearing key sequence list";-
496#endif-
497 }
never executed: end of block
0
498 if (oneKSResult && oneKSResult >= result) {
oneKSResultDescription
TRUEnever evaluated
FALSEnever evaluated
oneKSResult >= resultDescription
TRUEnever evaluated
FALSEnever evaluated
0
499 okEntries << d->newEntries.at(i);-
500#if defined(DEBUG_QSHORTCUTMAP)-
501 qDebug() << "Added ok key sequence" << d->newEntries;-
502#endif-
503 }
never executed: end of block
0
504 }
never executed: end of block
0
505-
506 if (d->identicals.size()) {
d->identicals.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
507 result = QKeySequence::ExactMatch;-
508 } else if (partialFound) {
never executed: end of block
partialFoundDescription
TRUEnever evaluated
FALSEnever evaluated
0
509 result = QKeySequence::PartialMatch;-
510 } else if (identicalDisabledFound) {
never executed: end of block
identicalDisabledFoundDescription
TRUEnever evaluated
FALSEnever evaluated
0
511 result = QKeySequence::ExactMatch;-
512 } else {
never executed: end of block
0
513 clearSequence(d->currentSequences);-
514 result = QKeySequence::NoMatch;-
515 }
never executed: end of block
0
516 if (result != QKeySequence::NoMatch)
result != QKey...uence::NoMatchDescription
TRUEnever evaluated
FALSEnever evaluated
0
517 d->currentSequences = okEntries;
never executed: d->currentSequences = okEntries;
0
518#if defined(DEBUG_QSHORTCUTMAP)-
519 qDebug() << "Returning shortcut match == " << result;-
520#endif-
521 return QKeySequence::SequenceMatch(result);
never executed: return QKeySequence::SequenceMatch(result);
0
522}-
523-
524/*! \internal-
525 Clears \a seq to an empty QKeySequence.-
526 Same as doing (the slower)-
527 \snippet code/src_gui_kernel_qshortcutmap.cpp 0-
528*/-
529void QShortcutMap::clearSequence(QVector<QKeySequence> &ksl)-
530{-
531 ksl.clear();-
532 d_func()->newEntries.clear();-
533}
never executed: end of block
0
534-
535/*! \internal-
536 Alters \a seq to the new sequence state, based on the-
537 current sequence state, and the new key event \a e.-
538*/-
539void QShortcutMap::createNewSequences(QKeyEvent *e, QVector<QKeySequence> &ksl, int ignoredModifiers)-
540{-
541 Q_D(QShortcutMap);-
542 QList<int> possibleKeys = QKeyMapper::possibleKeys(e);-
543 int pkTotal = possibleKeys.count();-
544 if (!pkTotal)
!pkTotalDescription
TRUEnever evaluated
FALSEnever evaluated
0
545 return;
never executed: return;
0
546-
547 int ssActual = d->currentSequences.count();-
548 int ssTotal = qMax(1, ssActual);-
549 // Resize to possible permutations of the current sequence(s).-
550 ksl.resize(pkTotal * ssTotal);-
551-
552 int index = ssActual ? d->currentSequences.at(0).count() : 0;
ssActualDescription
TRUEnever evaluated
FALSEnever evaluated
0
553 for (int pkNum = 0; pkNum < pkTotal; ++pkNum) {
pkNum < pkTotalDescription
TRUEnever evaluated
FALSEnever evaluated
0
554 for (int ssNum = 0; ssNum < ssTotal; ++ssNum) {
ssNum < ssTotalDescription
TRUEnever evaluated
FALSEnever evaluated
0
555 int i = (pkNum * ssTotal) + ssNum;-
556 QKeySequence &curKsl = ksl[i];-
557 if (ssActual) {
ssActualDescription
TRUEnever evaluated
FALSEnever evaluated
0
558 const QKeySequence &curSeq = d->currentSequences.at(ssNum);-
559 curKsl.setKey(curSeq[0], 0);-
560 curKsl.setKey(curSeq[1], 1);-
561 curKsl.setKey(curSeq[2], 2);-
562 curKsl.setKey(curSeq[3], 3);-
563 } else {
never executed: end of block
0
564 curKsl.setKey(0, 0);-
565 curKsl.setKey(0, 1);-
566 curKsl.setKey(0, 2);-
567 curKsl.setKey(0, 3);-
568 }
never executed: end of block
0
569 curKsl.setKey(possibleKeys.at(pkNum) & ~ignoredModifiers, index);-
570 }
never executed: end of block
0
571 }
never executed: end of block
0
572}
never executed: end of block
0
573-
574/*! \internal-
575 Basically the same function as QKeySequence::matches(const QKeySequence &seq) const-
576 only that is specially handles Key_hyphen as Key_Minus, as people mix these up all the time and-
577 they conceptually the same.-
578*/-
579QKeySequence::SequenceMatch QShortcutMap::matches(const QKeySequence &seq1,-
580 const QKeySequence &seq2) const-
581{-
582 uint userN = seq1.count(),-
583 seqN = seq2.count();-
584-
585 if (userN > seqN)
userN > seqNDescription
TRUEnever evaluated
FALSEnever evaluated
0
586 return QKeySequence::NoMatch;
never executed: return QKeySequence::NoMatch;
0
587-
588 // If equal in length, we have a potential ExactMatch sequence,-
589 // else we already know it can only be partial.-
590 QKeySequence::SequenceMatch match = (userN == seqN
userN == seqNDescription
TRUEnever evaluated
FALSEnever evaluated
0
591 ? QKeySequence::ExactMatch-
592 : QKeySequence::PartialMatch);-
593-
594 for (uint i = 0; i < userN; ++i) {
i < userNDescription
TRUEnever evaluated
FALSEnever evaluated
0
595 int userKey = seq1[i],-
596 sequenceKey = seq2[i];-
597 if ((userKey & Qt::Key_unknown) == Qt::Key_hyphen)
(userKey & Qt:...Qt::Key_hyphenDescription
TRUEnever evaluated
FALSEnever evaluated
0
598 userKey = (userKey & Qt::KeyboardModifierMask) | Qt::Key_Minus;
never executed: userKey = (userKey & Qt::KeyboardModifierMask) | Qt::Key_Minus;
0
599 if ((sequenceKey & Qt::Key_unknown) == Qt::Key_hyphen)
(sequenceKey &...Qt::Key_hyphenDescription
TRUEnever evaluated
FALSEnever evaluated
0
600 sequenceKey = (sequenceKey & Qt::KeyboardModifierMask) | Qt::Key_Minus;
never executed: sequenceKey = (sequenceKey & Qt::KeyboardModifierMask) | Qt::Key_Minus;
0
601 if (userKey != sequenceKey)
userKey != sequenceKeyDescription
TRUEnever evaluated
FALSEnever evaluated
0
602 return QKeySequence::NoMatch;
never executed: return QKeySequence::NoMatch;
0
603 }
never executed: end of block
0
604 return match;
never executed: return match;
0
605}-
606-
607-
608/*! \internal-
609 Converts keyboard button states into modifier states-
610*/-
611int QShortcutMap::translateModifiers(Qt::KeyboardModifiers modifiers)-
612{-
613 int result = 0;-
614 if (modifiers & Qt::ShiftModifier)
modifiers & Qt::ShiftModifierDescription
TRUEnever evaluated
FALSEnever evaluated
0
615 result |= Qt::SHIFT;
never executed: result |= Qt::SHIFT;
0
616 if (modifiers & Qt::ControlModifier)
modifiers & Qt...ontrolModifierDescription
TRUEnever evaluated
FALSEnever evaluated
0
617 result |= Qt::CTRL;
never executed: result |= Qt::CTRL;
0
618 if (modifiers & Qt::MetaModifier)
modifiers & Qt::MetaModifierDescription
TRUEnever evaluated
FALSEnever evaluated
0
619 result |= Qt::META;
never executed: result |= Qt::META;
0
620 if (modifiers & Qt::AltModifier)
modifiers & Qt::AltModifierDescription
TRUEnever evaluated
FALSEnever evaluated
0
621 result |= Qt::ALT;
never executed: result |= Qt::ALT;
0
622 return result;
never executed: return result;
0
623}-
624-
625/*! \internal-
626 Returns the vector of QShortcutEntry's matching the last Identical state.-
627*/-
628QVector<const QShortcutEntry*> QShortcutMap::matches() const-
629{-
630 Q_D(const QShortcutMap);-
631 return d->identicals;
never executed: return d->identicals;
0
632}-
633-
634/*! \internal-
635 Dispatches QShortcutEvents to widgets who grabbed the matched key sequence.-
636*/-
637void QShortcutMap::dispatchEvent(QKeyEvent *e)-
638{-
639 Q_D(QShortcutMap);-
640 if (!d->identicals.size())
!d->identicals.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
641 return;
never executed: return;
0
642-
643 const QKeySequence &curKey = d->identicals.at(0)->keyseq;-
644 if (d->prevSequence != curKey) {
d->prevSequence != curKeyDescription
TRUEnever evaluated
FALSEnever evaluated
0
645 d->ambigCount = 0;-
646 d->prevSequence = curKey;-
647 }
never executed: end of block
0
648 // Find next-
649 const QShortcutEntry *current = 0, *next = 0;-
650 int i = 0, enabledShortcuts = 0;-
651 while(i < d->identicals.size()) {
i < d->identicals.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
652 current = d->identicals.at(i);-
653 if (current->enabled || !next){
current->enabledDescription
TRUEnever evaluated
FALSEnever evaluated
!nextDescription
TRUEnever evaluated
FALSEnever evaluated
0
654 ++enabledShortcuts;-
655 if (enabledShortcuts > d->ambigCount + 1)
enabledShortcu...ambigCount + 1Description
TRUEnever evaluated
FALSEnever evaluated
0
656 break;
never executed: break;
0
657 next = current;-
658 }
never executed: end of block
0
659 ++i;-
660 }
never executed: end of block
0
661 d->ambigCount = (d->identicals.size() == i ? 0 : d->ambigCount + 1);
d->identicals.size() == iDescription
TRUEnever evaluated
FALSEnever evaluated
0
662 // Don't trigger shortcut if we're autorepeating and the shortcut is-
663 // grabbed with not accepting autorepeats.-
664 if (!next || (e->isAutoRepeat() && !next->autorepeat))
!nextDescription
TRUEnever evaluated
FALSEnever evaluated
e->isAutoRepeat()Description
TRUEnever evaluated
FALSEnever evaluated
!next->autorepeatDescription
TRUEnever evaluated
FALSEnever evaluated
0
665 return;
never executed: return;
0
666 // Dispatch next enabled-
667#if defined(DEBUG_QSHORTCUTMAP)-
668 qDebug().nospace()-
669 << "QShortcutMap::dispatchEvent(): Sending QShortcutEvent(\""-
670 << next->keyseq.toString() << "\", " << next->id << ", "-
671 << (bool)(enabledShortcuts>1) << ") to object(" << next->owner << ')';-
672#endif-
673 QShortcutEvent se(next->keyseq, next->id, enabledShortcuts>1);-
674 QCoreApplication::sendEvent(const_cast<QObject *>(next->owner), &se);-
675}
never executed: end of block
0
676-
677/* \internal-
678 QShortcutMap dump function, only available when DEBUG_QSHORTCUTMAP is-
679 defined.-
680*/-
681#if defined(Dump_QShortcutMap)-
682void QShortcutMap::dumpMap() const-
683{-
684 Q_D(const QShortcutMap);-
685 for (int i = 0; i < d->sequences.size(); ++i)-
686 qDebug().nospace() << &(d->sequences.at(i));-
687}-
688#endif-
689-
690QT_END_NAMESPACE-
691-
692#endif // QT_NO_SHORTCUT-
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9