Qt 4.8
qshortcutmap.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
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 Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qshortcutmap_p.h"
43 #include "private/qobject_p.h"
44 #include "qkeysequence.h"
45 #include "qgraphicsscene.h"
46 #include "qgraphicsview.h"
47 #include "qdebug.h"
48 #include "qevent.h"
49 #include "qwidget.h"
50 #include "qapplication.h"
51 #include "qvector.h"
52 #include "qmenu.h"
53 #include "qmenubar.h"
54 #include "qshortcut.h"
55 #include "qapplication_p.h"
56 #include <private/qaction_p.h>
57 #include <private/qkeymapper_p.h>
58 #include <private/qwidget_p.h>
59 
60 #ifndef QT_NO_SHORTCUT
61 
63 
64 // To enable verbose output uncomment below
65 //#define DEBUG_QSHORTCUTMAP
66 
67 /* \internal
68  Entry data for QShortcutMap
69  Contains:
70  Keysequence for entry
71  Pointer to parent owning the sequence
72 */
74 {
76  : keyseq(0), context(Qt::WindowShortcut), enabled(false), autorepeat(1), id(0), owner(0)
77  {}
78 
80  : keyseq(k), context(Qt::WindowShortcut), enabled(false), autorepeat(1), id(0), owner(0)
81  {}
82 
84  : keyseq(k), context(c), enabled(true), autorepeat(1), id(i), owner(o)
85  {}
86 
88  : keyseq(k), context(c), enabled(true), autorepeat(a), id(i), owner(o)
89  {}
90 
91  bool operator<(const QShortcutEntry &f) const
92  { return keyseq < f.keyseq; }
93 
96  bool enabled : 1;
97  bool autorepeat : 1;
98  signed int id;
100 };
101 
102 #if 0 //ndef QT_NO_DEBUG_STREAM
103 
109 static QDebug &operator<<(QDebug &dbg, const QShortcutEntry *se) {
110  if (!se)
111  return dbg << "QShortcutEntry(0x0)";
112  dbg.nospace()
113  << "QShortcutEntry(" << se->keyseq
114  << "), id(" << se->id << "), enabled(" << se->enabled << "), autorepeat(" << se->autorepeat
115  << "), owner(" << se->owner << ')';
116  return dbg.space();
117 }
118 #endif // QT_NO_DEBUGSTREAM
119 
120 /* \internal
121  Private data for QShortcutMap
122 */
124 {
126 
127 public:
129  : q_ptr(parent), currentId(0), ambigCount(0), currentState(QKeySequence::NoMatch)
130  {
131  identicals.reserve(10);
132  currentSequences.reserve(10);
133  }
134  QShortcutMap *q_ptr; // Private's parent
135 
136  QList<QShortcutEntry> sequences; // All sequences!
137 
138  int currentId; // Global shortcut ID number
139  int ambigCount; // Index of last enabled ambiguous dispatch
141  QVector<QKeySequence> currentSequences; // Sequence for the current state
143  QKeySequence prevSequence; // Sequence for the previous identical match
144  QVector<const QShortcutEntry*> identicals; // Last identical matches
145 };
146 
147 
155  : d_ptr(new QShortcutMapPrivate(this))
156 {
157  resetState();
158 }
159 
167 {
168 }
169 
178 {
179  Q_ASSERT_X(owner, "QShortcutMap::addShortcut", "All shortcuts need an owner");
180  Q_ASSERT_X(!key.isEmpty(), "QShortcutMap::addShortcut", "Cannot add keyless shortcuts to map");
181  Q_D(QShortcutMap);
182 
183  QShortcutEntry newEntry(owner, key, context, --(d->currentId), true);
184  QList<QShortcutEntry>::iterator it = qUpperBound(d->sequences.begin(), d->sequences.end(), newEntry);
185  d->sequences.insert(it, newEntry); // Insert sorted
186 #if defined(DEBUG_QSHORTCUTMAP)
187  qDebug().nospace()
188  << "QShortcutMap::addShortcut(" << owner << ", "
189  << key << ", " << context << ") = " << d->currentId;
190 #endif
191  return d->currentId;
192 }
193 
207 {
208  Q_D(QShortcutMap);
209  int itemsRemoved = 0;
210  bool allOwners = (owner == 0);
211  bool allKeys = key.isEmpty();
212  bool allIds = id == 0;
213 
214  // Special case, remove everything
215  if (allOwners && allKeys && id == 0) {
216  itemsRemoved = d->sequences.size();
217  d->sequences.clear();
218  return itemsRemoved;
219  }
220 
221  int i = d->sequences.size()-1;
222  while (i>=0)
223  {
224  const QShortcutEntry &entry = d->sequences.at(i);
225  int entryId = entry.id;
226  if ((allOwners || entry.owner == owner)
227  && (allIds || entry.id == id)
228  && (allKeys || entry.keyseq == key)) {
229  d->sequences.removeAt(i);
230  ++itemsRemoved;
231  }
232  if (id == entryId)
233  return itemsRemoved;
234  --i;
235  }
236 #if defined(DEBUG_QSHORTCUTMAP)
237  qDebug().nospace()
238  << "QShortcutMap::removeShortcut(" << id << ", " << owner << ", "
239  << key << ") = " << itemsRemoved;
240 #endif
241  return itemsRemoved;
242 }
243 
256 {
257  Q_D(QShortcutMap);
258  int itemsChanged = 0;
259  bool allOwners = (owner == 0);
260  bool allKeys = key.isEmpty();
261  bool allIds = id == 0;
262 
263  int i = d->sequences.size()-1;
264  while (i>=0)
265  {
266  QShortcutEntry entry = d->sequences.at(i);
267  if ((allOwners || entry.owner == owner)
268  && (allIds || entry.id == id)
269  && (allKeys || entry.keyseq == key)) {
270  d->sequences[i].enabled = enable;
271  ++itemsChanged;
272  }
273  if (id == entry.id)
274  return itemsChanged;
275  --i;
276  }
277 #if defined(DEBUG_QSHORTCUTMAP)
278  qDebug().nospace()
279  << "QShortcutMap::setShortcutEnabled(" << enable << ", " << id << ", "
280  << owner << ", " << key << ") = " << itemsChanged;
281 #endif
282  return itemsChanged;
283 }
284 
297 {
298  Q_D(QShortcutMap);
299  int itemsChanged = 0;
300  bool allOwners = (owner == 0);
301  bool allKeys = key.isEmpty();
302  bool allIds = id == 0;
303 
304  int i = d->sequences.size()-1;
305  while (i>=0)
306  {
307  QShortcutEntry entry = d->sequences.at(i);
308  if ((allOwners || entry.owner == owner)
309  && (allIds || entry.id == id)
310  && (allKeys || entry.keyseq == key)) {
311  d->sequences[i].autorepeat = on;
312  ++itemsChanged;
313  }
314  if (id == entry.id)
315  return itemsChanged;
316  --i;
317  }
318 #if defined(DEBUG_QSHORTCUTMAP)
319  qDebug().nospace()
320  << "QShortcutMap::setShortcutAutoRepeat(" << on << ", " << id << ", "
321  << owner << ", " << key << ") = " << itemsChanged;
322 #endif
323  return itemsChanged;
324 }
325 
330 {
331  Q_D(QShortcutMap);
332  d->currentState = QKeySequence::NoMatch;
333  clearSequence(d->currentSequences);
334 }
335 
340 {
341  Q_D(QShortcutMap);
342  return d->currentState;
343 }
344 
355 {
356  Q_D(QShortcutMap);
357 
358  if (e->key() == Qt::Key_unknown)
359  return false;
360 
361  bool wasAccepted = e->isAccepted();
362  bool wasSpontaneous = e->spont;
363  if (d->currentState == QKeySequence::NoMatch) {
364  ushort orgType = e->t;
366  e->ignore();
368  e->t = orgType;
369  e->spont = wasSpontaneous;
370  if (e->isAccepted()) {
371  if (!wasAccepted)
372  e->ignore();
373  return false;
374  }
375  }
376 
378  bool stateWasAccepted = e->isAccepted();
379  if (wasAccepted)
380  e->accept();
381  else
382  e->ignore();
383 
384  int identicalMatches = d->identicals.count();
385 
386  switch(result) {
388  return stateWasAccepted;
390  resetState();
391  dispatchEvent(e);
392  default:
393  break;
394  }
395  // If nextState is QKeySequence::ExactMatch && identicals.count == 0
396  // we've only found disabled shortcuts
397  return identicalMatches > 0 || result == QKeySequence::PartialMatch;
398 }
399 
407 {
408  Q_D(QShortcutMap);
409  // Modifiers can NOT be shortcuts...
410  if (e->key() >= Qt::Key_Shift &&
411  e->key() <= Qt::Key_Alt)
412  return d->currentState;
413 
415 
416  // We start fresh each time..
417  d->identicals.resize(0);
418 
419  result = find(e);
420  if (result == QKeySequence::NoMatch && (e->modifiers() & Qt::KeypadModifier)) {
421  // Try to find a match without keypad modifier
422  QKeyEvent event = *e;
424  result = find(&event);
425  }
426  if (result == QKeySequence::NoMatch && e->modifiers() & Qt::ShiftModifier) {
427  // If Shift + Key_Backtab, also try Shift + Qt::Key_Tab
428  if (e->key() == Qt::Key_Backtab) {
429  QKeyEvent pe = QKeyEvent(e->type(), Qt::Key_Tab, e->modifiers(), e->text());
430  result = find(&pe);
431  }
432  }
433 
434  // Should we eat this key press?
435  if (d->currentState == QKeySequence::PartialMatch
436  || (d->currentState == QKeySequence::ExactMatch && d->identicals.count()))
437  e->accept();
438  // Does the new state require us to clean up?
439  if (result == QKeySequence::NoMatch)
440  clearSequence(d->currentSequences);
441  d->currentState = result;
442 
443 #if defined(DEBUG_QSHORTCUTMAP)
444  qDebug().nospace() << "QShortcutMap::nextState(" << e << ") = " << result;
445 #endif
446  return result;
447 }
448 
449 
457 {
458  Q_D(const QShortcutMap);
459  QShortcutEntry entry(seq); // needed for searching
460  QList<QShortcutEntry>::ConstIterator itEnd = d->sequences.constEnd();
461  QList<QShortcutEntry>::ConstIterator it = qLowerBound(d->sequences.constBegin(), itEnd, entry);
462 
463  for (;it != itEnd; ++it) {
464  if (matches(entry.keyseq, (*it).keyseq) == QKeySequence::ExactMatch && correctContext(*it) && (*it).enabled) {
465  return true;
466  }
467  }
468 
469  //end of the loop: we didn't find anything
470  return false;
471 }
472 
484 {
485  Q_D(QShortcutMap);
486  if (!d->sequences.count())
487  return QKeySequence::NoMatch;
488 
489  createNewSequences(e, d->newEntries);
490 #if defined(DEBUG_QSHORTCUTMAP)
491  qDebug() << "Possible shortcut key sequences:" << d->newEntries;
492 #endif
493 
494  // Should never happen
495  if (d->newEntries == d->currentSequences) {
496  Q_ASSERT_X(e->key() != Qt::Key_unknown || e->text().length(),
497  "QShortcutMap::find", "New sequence to find identical to previous");
498  return QKeySequence::NoMatch;
499  }
500 
501  // Looking for new identicals, scrap old
502  d->identicals.resize(0);
503 
504  bool partialFound = false;
505  bool identicalDisabledFound = false;
506  QVector<QKeySequence> okEntries;
507  int result = QKeySequence::NoMatch;
508  for (int i = d->newEntries.count()-1; i >= 0 ; --i) {
509  QShortcutEntry entry(d->newEntries.at(i)); // needed for searching
510  QList<QShortcutEntry>::ConstIterator itEnd = d->sequences.constEnd();
512  qLowerBound(d->sequences.constBegin(), itEnd, entry);
513 
514  int oneKSResult = QKeySequence::NoMatch;
515  int tempRes = QKeySequence::NoMatch;
516  do {
517  if (it == itEnd)
518  break;
519  tempRes = matches(entry.keyseq, (*it).keyseq);
520  oneKSResult = qMax(oneKSResult, tempRes);
521  if (tempRes != QKeySequence::NoMatch && correctContext(*it)) {
522  if (tempRes == QKeySequence::ExactMatch) {
523  if ((*it).enabled)
524  d->identicals.append(&*it);
525  else
526  identicalDisabledFound = true;
527  } else if (tempRes == QKeySequence::PartialMatch) {
528  // We don't need partials, if we have identicals
529  if (d->identicals.size())
530  break;
531  // We only care about enabled partials, so we don't consume
532  // key events when all partials are disabled!
533  partialFound |= (*it).enabled;
534  }
535  }
536  ++it;
537  // If we got a valid match on this run, there might still be more keys to check against,
538  // so we'll loop once more. If we get NoMatch, there's guaranteed no more possible
539  // matches in the shortcutmap.
540  } while (tempRes != QKeySequence::NoMatch);
541 
542  // If the type of match improves (ergo, NoMatch->Partial, or Partial->Exact), clear the
543  // previous list. If this match is equal or better than the last match, append to the list
544  if (oneKSResult > result) {
545  okEntries.clear();
546 #if defined(DEBUG_QSHORTCUTMAP)
547  qDebug() << "Found better match (" << d->newEntries << "), clearing key sequence list";
548 #endif
549  }
550  if (oneKSResult && oneKSResult >= result) {
551  okEntries << d->newEntries.at(i);
552 #if defined(DEBUG_QSHORTCUTMAP)
553  qDebug() << "Added ok key sequence" << d->newEntries;
554 #endif
555  }
556  }
557 
558  if (d->identicals.size()) {
559  result = QKeySequence::ExactMatch;
560  } else if (partialFound) {
562  } else if (identicalDisabledFound) {
563  result = QKeySequence::ExactMatch;
564  } else {
565  clearSequence(d->currentSequences);
566  result = QKeySequence::NoMatch;
567  }
568  if (result != QKeySequence::NoMatch)
569  d->currentSequences = okEntries;
570 #if defined(DEBUG_QSHORTCUTMAP)
571  qDebug() << "Returning shortcut match == " << result;
572 #endif
573  return QKeySequence::SequenceMatch(result);
574 }
575 
585 {
586  ksl.clear();
587  d_func()->newEntries.clear();
588 }
589 
598 {
599  Q_D(QShortcutMap);
600  QList<int> possibleKeys = QKeyMapper::possibleKeys(e);
601  int pkTotal = possibleKeys.count();
602  if (!pkTotal)
603  return;
604 
605  int ssActual = d->currentSequences.count();
606  int ssTotal = qMax(1, ssActual);
607  // Resize to possible permutations of the current sequence(s).
608  ksl.resize(pkTotal * ssTotal);
609 
610  int index = ssActual ? d->currentSequences.at(0).count() : 0;
611  for (int pkNum = 0; pkNum < pkTotal; ++pkNum) {
612  for (int ssNum = 0; ssNum < ssTotal; ++ssNum) {
613  int i = (pkNum * ssTotal) + ssNum;
614  QKeySequence &curKsl = ksl[i];
615  if (ssActual) {
616  const QKeySequence &curSeq = d->currentSequences.at(ssNum);
617  curKsl.setKey(curSeq[0], 0);
618  curKsl.setKey(curSeq[1], 1);
619  curKsl.setKey(curSeq[2], 2);
620  curKsl.setKey(curSeq[3], 3);
621  } else {
622  curKsl.setKey(0, 0);
623  curKsl.setKey(0, 1);
624  curKsl.setKey(0, 2);
625  curKsl.setKey(0, 3);
626  }
627  curKsl.setKey(possibleKeys.at(pkNum), index);
628  }
629  }
630 }
631 
641  const QKeySequence &seq2) const
642 {
643  uint userN = seq1.count(),
644  seqN = seq2.count();
645 
646  if (userN > seqN)
647  return QKeySequence::NoMatch;
648 
649  // If equal in length, we have a potential ExactMatch sequence,
650  // else we already know it can only be partial.
651  QKeySequence::SequenceMatch match = (userN == seqN
654 
655  for (uint i = 0; i < userN; ++i) {
656  int userKey = seq1[i],
657  sequenceKey = seq2[i];
658  if ((userKey & Qt::Key_unknown) == Qt::Key_hyphen)
659  userKey = (userKey & Qt::KeyboardModifierMask) | Qt::Key_Minus;
660  if ((sequenceKey & Qt::Key_unknown) == Qt::Key_hyphen)
661  sequenceKey = (sequenceKey & Qt::KeyboardModifierMask) | Qt::Key_Minus;
662  if (userKey != sequenceKey)
663  return QKeySequence::NoMatch;
664  }
665  return match;
666 }
667 
676  Q_ASSERT_X(item.owner, "QShortcutMap", "Shortcut has no owner. Illegal map state!");
677 
678  QWidget *active_window = QApplication::activeWindow();
679 
680  // popups do not become the active window,
681  // so we fake it here to get the correct context
682  // for the shortcut system.
684  active_window = QApplication::activePopupWidget();
685 
686  if (!active_window)
687  return false;
688 #ifndef QT_NO_ACTION
689  if (QAction *a = qobject_cast<QAction *>(item.owner))
690  return correctContext(item.context, a, active_window);
691 #endif
692 #ifndef QT_NO_GRAPHICSVIEW
693  if (QGraphicsWidget *gw = qobject_cast<QGraphicsWidget *>(item.owner))
694  return correctGraphicsWidgetContext(item.context, gw, active_window);
695 #endif
696  QWidget *w = qobject_cast<QWidget *>(item.owner);
697  if (!w) {
698  QShortcut *s = qobject_cast<QShortcut *>(item.owner);
699  w = s->parentWidget();
700  }
701  return correctWidgetContext(item.context, w, active_window);
702 }
703 
705 {
706  bool visible = w->isVisible();
707 #ifdef Q_WS_MAC
708  if (!qApp->testAttribute(Qt::AA_DontUseNativeMenuBar) && qobject_cast<QMenuBar *>(w))
709  visible = true;
710 #endif
711 
712  if (!visible || !w->isEnabled())
713  return false;
714 
715  if (context == Qt::ApplicationShortcut)
716  return QApplicationPrivate::tryModalHelper(w, 0); // true, unless w is shadowed by a modal dialog
717 
718  if (context == Qt::WidgetShortcut)
719  return w == QApplication::focusWidget();
720 
721  if (context == Qt::WidgetWithChildrenShortcut) {
722  const QWidget *tw = QApplication::focusWidget();
723  while (tw && tw != w && (tw->windowType() == Qt::Widget || tw->windowType() == Qt::Popup))
724  tw = tw->parentWidget();
725  return tw == w;
726  }
727 
728  // Below is Qt::WindowShortcut context
729  QWidget *tlw = w->window();
730 #ifndef QT_NO_GRAPHICSVIEW
731  if (QWExtra *topData = tlw->d_func()->extra) {
732  if (topData->proxyWidget) {
733  bool res = correctGraphicsWidgetContext(context, (QGraphicsWidget *)topData->proxyWidget, active_window);
734  return res;
735  }
736  }
737 #endif
738 
739  /* if a floating tool window is active, keep shortcuts on the
740  * parent working */
741  if (active_window != tlw && active_window && active_window->windowType() == Qt::Tool && active_window->parentWidget()) {
742  active_window = active_window->parentWidget()->window();
743  }
744 
745  if (active_window != tlw)
746  return false;
747 
748  /* if we live in a MDI subwindow, ignore the event if we are
749  not the active document window */
750  const QWidget* sw = w;
751  while (sw && !(sw->windowType() == Qt::SubWindow) && !sw->isWindow())
752  sw = sw->parentWidget();
753  if (sw && (sw->windowType() == Qt::SubWindow)) {
754  QWidget *focus_widget = QApplication::focusWidget();
755  while (focus_widget && focus_widget != sw)
756  focus_widget = focus_widget->parentWidget();
757  return sw == focus_widget;
758  }
759 
760 #if defined(DEBUG_QSHORTCUTMAP)
761  qDebug().nospace() << "..true [Pass-through]";
762 #endif
763  return true;
764 }
765 
766 #ifndef QT_NO_GRAPHICSVIEW
768 {
769  bool visible = w->isVisible();
770 #ifdef Q_WS_MAC
771  if (!qApp->testAttribute(Qt::AA_DontUseNativeMenuBar) && qobject_cast<QMenuBar *>(w))
772  visible = true;
773 #endif
774 
775  if (!visible || !w->isEnabled() || !w->scene())
776  return false;
777 
778  if (context == Qt::ApplicationShortcut) {
779  // Applicationwide shortcuts are always reachable unless their owner
780  // is shadowed by modality. In QGV there's no modality concept, but we
781  // must still check if all views are shadowed.
782  QList<QGraphicsView *> views = w->scene()->views();
783  for (int i = 0; i < views.size(); ++i) {
784  if (QApplicationPrivate::tryModalHelper(views.at(i), 0))
785  return true;
786  }
787  return false;
788  }
789 
790  if (context == Qt::WidgetShortcut)
791  return static_cast<QGraphicsItem *>(w) == w->scene()->focusItem();
792 
793  if (context == Qt::WidgetWithChildrenShortcut) {
794  const QGraphicsItem *ti = w->scene()->focusItem();
795  if (ti && ti->isWidget()) {
796  const QGraphicsWidget *tw = static_cast<const QGraphicsWidget *>(ti);
797  while (tw && tw != w && (tw->windowType() == Qt::Widget || tw->windowType() == Qt::Popup))
798  tw = tw->parentWidget();
799  return tw == w;
800  }
801  return false;
802  }
803 
804  // Below is Qt::WindowShortcut context
805 
806  // Find the active view (if any).
807  QList<QGraphicsView *> views = w->scene()->views();
808  QGraphicsView *activeView = 0;
809  for (int i = 0; i < views.size(); ++i) {
810  QGraphicsView *view = views.at(i);
811  if (view->window() == active_window) {
812  activeView = view;
813  break;
814  }
815  }
816  if (!activeView)
817  return false;
818 
819  // The shortcut is reachable if owned by a windowless widget, or if the
820  // widget's window is the same as the focus item's window.
821  QGraphicsWidget *a = w->scene()->activeWindow();
822  return !w->window() || a == w->window();
823 }
824 #endif
825 
826 #ifndef QT_NO_ACTION
827 bool QShortcutMap::correctContext(Qt::ShortcutContext context, QAction *a, QWidget *active_window) const
828 {
829  const QList<QWidget *> &widgets = a->d_func()->widgets;
830 #if defined(DEBUG_QSHORTCUTMAP)
831  if (widgets.isEmpty())
832  qDebug() << a << "not connected to any widgets; won't trigger";
833 #endif
834  for (int i = 0; i < widgets.size(); ++i) {
835  QWidget *w = widgets.at(i);
836 #ifndef QT_NO_MENU
837  if (QMenu *menu = qobject_cast<QMenu *>(w)) {
838  QAction *a = menu->menuAction();
839  if (correctContext(context, a, active_window))
840  return true;
841  } else
842 #endif
843  if (correctWidgetContext(context, w, active_window))
844  return true;
845  }
846 
847 #ifndef QT_NO_GRAPHICSVIEW
848  const QList<QGraphicsWidget *> &graphicsWidgets = a->d_func()->graphicsWidgets;
849 #if defined(DEBUG_QSHORTCUTMAP)
850  if (graphicsWidgets.isEmpty())
851  qDebug() << a << "not connected to any widgets; won't trigger";
852 #endif
853  for (int i = 0; i < graphicsWidgets.size(); ++i) {
854  QGraphicsWidget *w = graphicsWidgets.at(i);
855  if (correctGraphicsWidgetContext(context, w, active_window))
856  return true;
857  }
858 #endif
859  return false;
860 }
861 #endif // QT_NO_ACTION
862 
866 int QShortcutMap::translateModifiers(Qt::KeyboardModifiers modifiers)
867 {
868  int result = 0;
869  if (modifiers & Qt::ShiftModifier)
870  result |= Qt::SHIFT;
871  if (modifiers & Qt::ControlModifier)
872  result |= Qt::CTRL;
873  if (modifiers & Qt::MetaModifier)
874  result |= Qt::META;
875  if (modifiers & Qt::AltModifier)
876  result |= Qt::ALT;
877  return result;
878 }
879 
887 {
888  Q_D(const QShortcutMap);
889  return d->identicals;
890 }
891 
899 {
900  Q_D(QShortcutMap);
901  if (!d->identicals.size())
902  return;
903 
904  const QKeySequence &curKey = d->identicals.at(0)->keyseq;
905  if (d->prevSequence != curKey) {
906  d->ambigCount = 0;
907  d->prevSequence = curKey;
908  }
909  // Find next
910  const QShortcutEntry *current = 0, *next = 0;
911  int i = 0, enabledShortcuts = 0;
912  while(i < d->identicals.size()) {
913  current = d->identicals.at(i);
914  if (current->enabled || !next){
915  ++enabledShortcuts;
916  if (enabledShortcuts > d->ambigCount + 1)
917  break;
918  next = current;
919  }
920  ++i;
921  }
922  d->ambigCount = (d->identicals.size() == i ? 0 : d->ambigCount + 1);
923  // Don't trigger shortcut if we're autorepeating and the shortcut is
924  // grabbed with not accepting autorepeats.
925  if (!next || (e->isAutoRepeat() && !next->autorepeat))
926  return;
927  // Dispatch next enabled
928 #if defined(DEBUG_QSHORTCUTMAP)
929  qDebug().nospace()
930  << "QShortcutMap::dispatchEvent(): Sending QShortcutEvent(\""
931  << (QString)next->keyseq << "\", " << next->id << ", "
932  << (bool)(enabledShortcuts>1) << ") to object(" << next->owner << ')';
933 #endif
934  QShortcutEvent se(next->keyseq, next->id, enabledShortcuts>1);
935  QApplication::sendEvent(const_cast<QObject *>(next->owner), &se);
936 }
937 
938 /* \internal
939  QShortcutMap dump function, only available when DEBUG_QSHORTCUTMAP is
940  defined.
941 */
942 #if defined(Dump_QShortcutMap)
943 void QShortcutMap::dumpMap() const
944 {
945  Q_D(const QShortcutMap);
946  for (int i = 0; i < d->sequences.size(); ++i)
947  qDebug().nospace() << &(d->sequences.at(i));
948 }
949 #endif
950 
952 
953 #endif // QT_NO_SHORTCUT
T qobject_cast(QObject *object)
Definition: qobject.h:375
The QDebug class provides an output stream for debugging information.
Definition: qdebug.h:62
static void allKeys(HKEY parentHandle, const QString &rSubKey, NameSet *result)
double d
Definition: qnumeric_p.h:62
QGraphicsWidget * activeWindow() const
Returns the current active window, or 0 if no window is currently active.
QWidget * parentWidget() const
Returns the parent of this widget, or 0 if it does not have any parent widget.
Definition: qwidget.h:1035
Q_OUTOFLINE_TEMPLATE RandomAccessIterator qUpperBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value)
Definition: qalgorithms.h:262
The QKeyEvent class describes a key event.
Definition: qevent.h:224
unsigned char c[8]
Definition: qnumeric_p.h:62
QGraphicsWidget * parentWidget() const
Returns a pointer to the item&#39;s parent widget.
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
int setShortcutEnabled(bool enable, int id, QObject *owner, const QKeySequence &key=QKeySequence())
Changes the enable state of a shortcut to enable.
EventRef event
ushort t
Definition: qcoreevent.h:316
void dispatchEvent(QKeyEvent *e)
Dispatches QShortcutEvents to widgets who grabbed the matched key sequence.
bool correctWidgetContext(Qt::ShortcutContext context, QWidget *w, QWidget *active_window) const
QVector< const QShortcutEntry * > identicals
#define it(className, varName)
bool isWindow() const
Returns true if the widget is an independent window, otherwise returns false.
Definition: qwidget.h:945
bool isVisible() const
Definition: qwidget.h:1005
QDebug & nospace()
Clears the stream&#39;s internal flag that records whether the last character was a space and returns a r...
Definition: qdebug.h:92
QShortcutEntry(QObject *o, const QKeySequence &k, Qt::ShortcutContext c, int i, bool a)
int length() const
Returns the number of characters in this string.
Definition: qstring.h:696
static QWidget * activeWindow()
Returns the application top-level window that has the keyboard input focus, or 0 if no application wi...
The QGraphicsItem class is the base class for all graphical items in a QGraphicsScene.
Definition: qgraphicsitem.h:89
bool isVisible() const
Returns true if the item is visible; otherwise, false is returned.
void setKey(int key, int index)
KeySequences should never be modified, but rather just created.
The QWidget class is the base class of all user interface objects.
Definition: qwidget.h:150
The QShortcutEvent class provides an event which is generated when the user presses a key combination...
Definition: qevent.h:675
static bool match(const uchar *found, const char *target, uint len)
QKeySequence keyseq
bool hasShortcutForKeySequence(const QKeySequence &seq) const
Determines if an enabled shortcut has a matcing key sequence.
long ASN1_INTEGER_get ASN1_INTEGER * a
int count(const T &t) const
Returns the number of occurrences of value in the list.
Definition: qlist.h:891
QShortcutMap()
QShortcutMap constructor.
QKeySequence::SequenceMatch currentState
Qt::ShortcutContext context
The QString class provides a Unicode character string.
Definition: qstring.h:83
static QWidget * owner
QList< QShortcutEntry > sequences
bool isEnabled() const
Returns true if the item is enabled; otherwise, false is returned.
The QObject class is the base class of all Qt objects.
Definition: qobject.h:111
signed int id
#define Q_D(Class)
Definition: qglobal.h:2482
Qt::WindowType windowType() const
Returns the widgets window type.
Q_DECL_CONSTEXPR const T & qMax(const T &a, const T &b)
Definition: qglobal.h:1217
bool isEmpty() const
Returns true if the list contains no items; otherwise returns false.
Definition: qlist.h:152
void resize(int size)
Sets the size of the vector to size.
Definition: qvector.h:342
The QShortcut class is used to create keyboard shortcuts.
Definition: qshortcut.h:57
Q_CORE_EXPORT void qDebug(const char *,...)
Qt::KeyboardModifiers modifiers() const
Returns the keyboard modifier flags that existed immediately after the event occurred.
Definition: qevent.cpp:999
static QList< int > possibleKeys(QKeyEvent *e)
Definition: qkeymapper.cpp:74
int key() const
Returns the code of the key that was pressed or released.
Definition: qevent.h:231
QVector< const QShortcutEntry * > matches() const
Returns the vector of QShortcutEntry&#39;s matching the last Identical state.
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
bool isAccepted() const
Definition: qcoreevent.h:307
QGraphicsItem * focusItem() const
When the scene is active, this functions returns the scene&#39;s current focus item, or 0 if no item curr...
QList< QGraphicsView * > views() const
Returns a list of all the views that display this scene.
void clear()
Removes all the elements from the vector and releases the memory used by the vector.
Definition: qvector.h:347
#define qApp
QKeySequence::SequenceMatch nextState(QKeyEvent *e)
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
unsigned int uint
Definition: qglobal.h:996
void createNewSequences(QKeyEvent *e, QVector< QKeySequence > &ksl)
Alters seq to the new sequence state, based on the current sequence state, and the new key event e...
static bool sendEvent(QObject *receiver, QEvent *event)
Sends event event directly to receiver receiver, using the notify() function.
QShortcutMapPrivate(QShortcutMap *parent)
bool operator<(const QShortcutEntry &f) const
QVector< QKeySequence > currentSequences
bool isEmpty() const
Returns true if the key sequence is empty; otherwise returns false.
bool isEnabled() const
Definition: qwidget.h:948
QKeySequence::SequenceMatch find(QKeyEvent *e)
Returns the next state of the statemachine, based on the new key event e.
~QShortcutMap()
QShortcutMap destructor.
QKeySequence prevSequence
Q_OUTOFLINE_TEMPLATE RandomAccessIterator qLowerBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value)
Definition: qalgorithms.h:227
int setShortcutAutoRepeat(bool on, int id, QObject *owner, const QKeySequence &key=QKeySequence())
Changes the auto repeat state of a shortcut to enable.
static bool tryModalHelper(QWidget *widget, QWidget **rettop=0)
#define Q_ASSERT_X(cond, where, what)
Definition: qglobal.h:1837
int translateModifiers(Qt::KeyboardModifiers modifiers)
#define Q_DECLARE_PUBLIC(Class)
Definition: qglobal.h:2477
bool tryShortcutEvent(QObject *o, QKeyEvent *e)
Uses ShortcutOverride event to see if any widgets want to override the event.
The QMenuBar class provides a horizontal menu bar.
Definition: qmenubar.h:62
static QWidget * activePopupWidget()
Returns the active popup widget.
The QKeySequence class encapsulates a key sequence as used by shortcuts.
Definition: qkeysequence.h:72
The QMenu class provides a menu widget for use in menu bars, context menus, and other popup menus...
Definition: qmenu.h:72
QString text() const
Returns the Unicode text that this key generated.
Definition: qevent.h:236
unsigned short ushort
Definition: qglobal.h:995
QKeySequence::SequenceMatch state()
int key
void clearSequence(QVector< QKeySequence > &ksl)
Clears seq to an empty QKeySequence.
int size() const
Returns the number of items in the list.
Definition: qlist.h:137
QGraphicsWidget * window() const
Returns the item&#39;s window, or 0 if this item does not have a window.
int removeShortcut(int id, QObject *owner, const QKeySequence &key=QKeySequence())
Removes a shortcut from the global map.
Definition: qnamespace.h:54
bool isWidget() const
Returns true if this item is a widget (i.
bool isAutoRepeat() const
Returns true if this event comes from an auto-repeating key; returns false if it comes from an initia...
Definition: qevent.h:237
uint count() const
Returns the number of keys in the key sequence.
quint16 index
bool correctContext(Qt::ShortcutContext context, QAction *a, QWidget *active_window) const
QWidget * window() const
Returns the window for this widget, i.e.
Definition: qwidget.cpp:4492
bool correctGraphicsWidgetContext(Qt::ShortcutContext context, QGraphicsWidget *w, QWidget *active_window) const
The QGraphicsView class provides a widget for displaying the contents of a QGraphicsScene.
Definition: qgraphicsview.h:64
QDataStream & operator<<(QDataStream &s, const QAxBase &c)
Definition: qaxbase.h:203
int addShortcut(QObject *owner, const QKeySequence &key, Qt::ShortcutContext context)
Adds a shortcut to the global map.
void ignore()
Clears the accept flag parameter of the event object, the equivalent of calling setAccepted(false).
Definition: qcoreevent.h:310
void accept()
Sets the accept flag of the event object, the equivalent of calling setAccepted(true).
Definition: qcoreevent.h:309
Qt::WindowType windowType() const
Returns the window type of this widget.
Definition: qwidget.h:937
QGraphicsScene * scene() const
Returns the current scene for the item, or 0 if the item is not stored in a scene.
ShortcutContext
Definition: qnamespace.h:1478
void setModifiers(Qt::KeyboardModifiers amodifiers)
Sets the keyboard modifiers flags for this event.
Definition: qevent.h:80
QShortcutEntry(QObject *o, const QKeySequence &k, Qt::ShortcutContext c, int i)
QShortcutEntry(const QKeySequence &k)
QObject * owner
QDebug & space()
Writes a space character to the debug stream and returns a reference to the stream.
Definition: qdebug.h:91
Type type() const
Returns the event type.
Definition: qcoreevent.h:303
static QWidget * focusWidget()
Returns the application widget that has the keyboard input focus, or 0 if no widget in this applicati...
QVector< QKeySequence > newEntries
The QAction class provides an abstract user interface action that can be inserted into widgets...
Definition: qaction.h:64
QWidget * parentWidget() const
Returns the shortcut&#39;s parent widget.
Definition: qshortcut.h:90
QShortcutMap * q_ptr
The QGraphicsWidget class is the base class for all widget items in a QGraphicsScene.