diff --git a/src/widgets/graphicsview/qgraphicswidget.cpp b/src/widgets/graphicsview/qgraphicswidget.cpp index 8beb006788..e1fbdd4aa8 100644 --- a/src/widgets/graphicsview/qgraphicswidget.cpp +++ b/src/widgets/graphicsview/qgraphicswidget.cpp @@ -1898,7 +1898,7 @@ int QGraphicsWidget::grabShortcut(const QKeySequence &sequence, Qt::ShortcutCont if (sequence.isEmpty()) return 0; // ### setAttribute(Qt::WA_GrabbedShortcut); - return qApp->d_func()->shortcutMap.addShortcut(this, sequence, context); + return qApp->d_func()->shortcutMap.addShortcut(this, sequence, context, qWidgetShortcutContextMatcher); } /*! diff --git a/src/widgets/kernel/qaction.cpp b/src/widgets/kernel/qaction.cpp index 61be508d39..22162895f7 100644 --- a/src/widgets/kernel/qaction.cpp +++ b/src/widgets/kernel/qaction.cpp @@ -139,7 +139,7 @@ void QActionPrivate::redoGrab(QShortcutMap &map) map.removeShortcut(shortcutId, q); if (shortcut.isEmpty()) return; - shortcutId = map.addShortcut(q, shortcut, shortcutContext); + shortcutId = map.addShortcut(q, shortcut, shortcutContext, qWidgetShortcutContextMatcher); if (!enabled) map.setShortcutEnabled(false, shortcutId, q); if (!autorepeat) @@ -159,7 +159,7 @@ void QActionPrivate::redoGrabAlternate(QShortcutMap &map) for(int i = 0; i < alternateShortcuts.count(); ++i) { const QKeySequence& alternate = alternateShortcuts.at(i); if (!alternate.isEmpty()) - alternateShortcutIds.append(map.addShortcut(q, alternate, shortcutContext)); + alternateShortcutIds.append(map.addShortcut(q, alternate, shortcutContext, qWidgetShortcutContextMatcher)); else alternateShortcutIds.append(0); } diff --git a/src/widgets/kernel/qaction.h b/src/widgets/kernel/qaction.h index 193328dbdd..5c163c2314 100644 --- a/src/widgets/kernel/qaction.h +++ b/src/widgets/kernel/qaction.h @@ -214,7 +214,6 @@ private: friend class QMenu; friend class QMenuPrivate; friend class QMenuBar; - friend class QShortcutMap; friend class QToolButton; #ifdef Q_OS_MAC friend void qt_mac_clear_status_text(QAction *action); diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 3012eab777..de4ae0a5d3 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -10713,7 +10713,7 @@ int QWidget::grabShortcut(const QKeySequence &key, Qt::ShortcutContext context) if (key.isEmpty()) return 0; setAttribute(Qt::WA_GrabbedShortcut); - return qApp->d_func()->shortcutMap.addShortcut(this, key, context); + return qApp->d_func()->shortcutMap.addShortcut(this, key, context, qWidgetShortcutContextMatcher); } /*! diff --git a/src/widgets/kernel/qwidget.h b/src/widgets/kernel/qwidget.h index a8722e9482..fadb330277 100644 --- a/src/widgets/kernel/qwidget.h +++ b/src/widgets/kernel/qwidget.h @@ -750,7 +750,6 @@ private: friend class QX11PaintEngine; friend class QWin32PaintEngine; friend class QShortcutPrivate; - friend class QShortcutMap; friend class QWindowSurface; friend class QGraphicsProxyWidget; friend class QGraphicsProxyWidgetPrivate; diff --git a/src/widgets/to_be_moved/qshortcut.cpp b/src/widgets/to_be_moved/qshortcut.cpp index 041bde30b1..f66c87dd13 100644 --- a/src/widgets/to_be_moved/qshortcut.cpp +++ b/src/widgets/to_be_moved/qshortcut.cpp @@ -172,7 +172,7 @@ void QShortcutPrivate::redoGrab(QShortcutMap &map) map.removeShortcut(sc_id, q); if (sc_sequence.isEmpty()) return; - sc_id = map.addShortcut(q, sc_sequence, sc_context); + sc_id = map.addShortcut(q, sc_sequence, sc_context, qWidgetShortcutContextMatcher); if (!sc_enabled) map.setShortcutEnabled(false, sc_id, q); if (!sc_autorepeat) diff --git a/src/widgets/to_be_moved/qshortcutmap.cpp b/src/widgets/to_be_moved/qshortcutmap.cpp index 394c730d82..547daaf132 100644 --- a/src/widgets/to_be_moved/qshortcutmap.cpp +++ b/src/widgets/to_be_moved/qshortcutmap.cpp @@ -70,23 +70,22 @@ QT_BEGIN_NAMESPACE Keysequence for entry Pointer to parent owning the sequence */ + struct QShortcutEntry { QShortcutEntry() - : keyseq(0), context(Qt::WindowShortcut), enabled(false), autorepeat(1), id(0), owner(0) + : keyseq(0), context(Qt::WindowShortcut), enabled(false), autorepeat(1), id(0), owner(0), contextMatcher(0) {} QShortcutEntry(const QKeySequence &k) - : keyseq(k), context(Qt::WindowShortcut), enabled(false), autorepeat(1), id(0), owner(0) + : keyseq(k), context(Qt::WindowShortcut), enabled(false), autorepeat(1), id(0), owner(0), contextMatcher(0) {} - QShortcutEntry(QObject *o, const QKeySequence &k, Qt::ShortcutContext c, int i) - : keyseq(k), context(c), enabled(true), autorepeat(1), id(i), owner(o) + QShortcutEntry(QObject *o, const QKeySequence &k, Qt::ShortcutContext c, int i, bool a, QShortcutMap::ContextMatcher m) + : keyseq(k), context(c), enabled(true), autorepeat(a), id(i), owner(o), contextMatcher(m) {} - QShortcutEntry(QObject *o, const QKeySequence &k, Qt::ShortcutContext c, int i, bool a) - : keyseq(k), context(c), enabled(true), autorepeat(a), id(i), owner(o) - {} + bool correctContext() const { return contextMatcher(owner, context); } bool operator<(const QShortcutEntry &f) const { return keyseq < f.keyseq; } @@ -97,6 +96,7 @@ struct QShortcutEntry bool autorepeat : 1; signed int id; QObject *owner; + QShortcutMap::ContextMatcher contextMatcher; }; #if 0 //ndef QT_NO_DEBUG_STREAM @@ -162,13 +162,13 @@ QShortcutMap::~QShortcutMap() Adds a shortcut to the global map. Returns the id of the newly added shortcut. */ -int QShortcutMap::addShortcut(QObject *owner, const QKeySequence &key, Qt::ShortcutContext context) +int QShortcutMap::addShortcut(QObject *owner, const QKeySequence &key, Qt::ShortcutContext context, ContextMatcher matcher) { Q_ASSERT_X(owner, "QShortcutMap::addShortcut", "All shortcuts need an owner"); Q_ASSERT_X(!key.isEmpty(), "QShortcutMap::addShortcut", "Cannot add keyless shortcuts to map"); Q_D(QShortcutMap); - QShortcutEntry newEntry(owner, key, context, --(d->currentId), true); + QShortcutEntry newEntry(owner, key, context, --(d->currentId), true, matcher); QList::iterator it = qUpperBound(d->sequences.begin(), d->sequences.end(), newEntry); d->sequences.insert(it, newEntry); // Insert sorted #if defined(DEBUG_QSHORTCUTMAP) @@ -425,7 +425,7 @@ bool QShortcutMap::hasShortcutForKeySequence(const QKeySequence &seq) const QList::ConstIterator it = qLowerBound(d->sequences.constBegin(), itEnd, entry); for (;it != itEnd; ++it) { - if (matches(entry.keyseq, (*it).keyseq) == QKeySequence::ExactMatch && correctContext(*it) && (*it).enabled) { + if (matches(entry.keyseq, (*it).keyseq) == QKeySequence::ExactMatch && (*it).correctContext() && (*it).enabled) { return true; } } @@ -479,7 +479,7 @@ QKeySequence::SequenceMatch QShortcutMap::find(QKeyEvent *e) break; tempRes = matches(entry.keyseq, (*it).keyseq); oneKSResult = qMax(oneKSResult, tempRes); - if (tempRes != QKeySequence::NoMatch && correctContext(*it)) { + if (tempRes != QKeySequence::NoMatch && (*it).correctContext()) { if (tempRes == QKeySequence::ExactMatch) { if ((*it).enabled) d->identicals.append(&*it); @@ -618,12 +618,23 @@ QKeySequence::SequenceMatch QShortcutMap::matches(const QKeySequence &seq1, return match; } + +static bool correctWidgetContext(Qt::ShortcutContext context, QWidget *w, QWidget *active_window); +#ifndef QT_NO_GRAPHICSVIEW +static bool correctGraphicsWidgetContext(Qt::ShortcutContext context, QGraphicsWidget *w, QWidget *active_window); +#endif +#ifndef QT_NO_ACTION +static bool correctActionContext(Qt::ShortcutContext context, QAction *a, QWidget *active_window); +#endif + + /*! \internal Returns true if the widget \a w is a logical sub window of the current top-level widget. */ -bool QShortcutMap::correctContext(const QShortcutEntry &item) const { - Q_ASSERT_X(item.owner, "QShortcutMap", "Shortcut has no owner. Illegal map state!"); +bool qWidgetShortcutContextMatcher(QObject *object, Qt::ShortcutContext context) +{ + Q_ASSERT_X(object, "QShortcutMap", "Shortcut has no owner. Illegal map state!"); QWidget *active_window = QApplication::activeWindow(); @@ -635,23 +646,31 @@ bool QShortcutMap::correctContext(const QShortcutEntry &item) const { if (!active_window) return false; + #ifndef QT_NO_ACTION - if (QAction *a = qobject_cast(item.owner)) - return correctContext(item.context, a, active_window); + if (QAction *a = qobject_cast(object)) + return correctActionContext(context, a, active_window); #endif + #ifndef QT_NO_GRAPHICSVIEW - if (QGraphicsWidget *gw = qobject_cast(item.owner)) - return correctGraphicsWidgetContext(item.context, gw, active_window); + if (QGraphicsWidget *gw = qobject_cast(object)) + return correctGraphicsWidgetContext(context, gw, active_window); #endif - QWidget *w = qobject_cast(item.owner); + + QWidget *w = qobject_cast(object); if (!w) { - QShortcut *s = qobject_cast(item.owner); - w = s->parentWidget(); + QShortcut *s = qobject_cast(object); + if (s) + w = s->parentWidget(); } - return correctWidgetContext(item.context, w, active_window); + + if (!w) + return false; + + return correctWidgetContext(context, w, active_window); } -bool QShortcutMap::correctWidgetContext(Qt::ShortcutContext context, QWidget *w, QWidget *active_window) const +static bool correctWidgetContext(Qt::ShortcutContext context, QWidget *w, QWidget *active_window) { bool visible = w->isVisible(); #ifdef Q_WS_MAC @@ -678,7 +697,7 @@ bool QShortcutMap::correctWidgetContext(Qt::ShortcutContext context, QWidget *w, // Below is Qt::WindowShortcut context QWidget *tlw = w->window(); #ifndef QT_NO_GRAPHICSVIEW - if (QWExtra *topData = tlw->d_func()->extra) { + if (QWExtra *topData = static_cast(QObjectPrivate::get(tlw))->extra) { if (topData->proxyWidget) { bool res = correctGraphicsWidgetContext(context, (QGraphicsWidget *)topData->proxyWidget, active_window); return res; @@ -714,7 +733,7 @@ bool QShortcutMap::correctWidgetContext(Qt::ShortcutContext context, QWidget *w, } #ifndef QT_NO_GRAPHICSVIEW -bool QShortcutMap::correctGraphicsWidgetContext(Qt::ShortcutContext context, QGraphicsWidget *w, QWidget *active_window) const +static bool correctGraphicsWidgetContext(Qt::ShortcutContext context, QGraphicsWidget *w, QWidget *active_window) { bool visible = w->isVisible(); #ifdef Q_WS_MAC @@ -774,9 +793,9 @@ bool QShortcutMap::correctGraphicsWidgetContext(Qt::ShortcutContext context, QGr #endif #ifndef QT_NO_ACTION -bool QShortcutMap::correctContext(Qt::ShortcutContext context, QAction *a, QWidget *active_window) const +static bool correctActionContext(Qt::ShortcutContext context, QAction *a, QWidget *active_window) { - const QList &widgets = a->d_func()->widgets; + const QList &widgets = static_cast(QObjectPrivate::get(a))->widgets; #if defined(DEBUG_QSHORTCUTMAP) if (widgets.isEmpty()) qDebug() << a << "not connected to any widgets; won't trigger"; @@ -786,7 +805,7 @@ bool QShortcutMap::correctContext(Qt::ShortcutContext context, QAction *a, QWidg #ifndef QT_NO_MENU if (QMenu *menu = qobject_cast(w)) { QAction *a = menu->menuAction(); - if (correctContext(context, a, active_window)) + if (correctActionContext(context, a, active_window)) return true; } else #endif @@ -795,7 +814,7 @@ bool QShortcutMap::correctContext(Qt::ShortcutContext context, QAction *a, QWidg } #ifndef QT_NO_GRAPHICSVIEW - const QList &graphicsWidgets = a->d_func()->graphicsWidgets; + const QList &graphicsWidgets = static_cast(QObjectPrivate::get(a))->graphicsWidgets; #if defined(DEBUG_QSHORTCUTMAP) if (graphicsWidgets.isEmpty()) qDebug() << a << "not connected to any widgets; won't trigger"; diff --git a/src/widgets/to_be_moved/qshortcutmap_p.h b/src/widgets/to_be_moved/qshortcutmap_p.h index 0090cea8e9..1cc0fd6421 100644 --- a/src/widgets/to_be_moved/qshortcutmap_p.h +++ b/src/widgets/to_be_moved/qshortcutmap_p.h @@ -72,6 +72,8 @@ class QWidget; class QAction; class QObject; +bool qWidgetShortcutContextMatcher(QObject *object, Qt::ShortcutContext context); + class QShortcutMap { Q_DECLARE_PRIVATE(QShortcutMap) @@ -79,7 +81,9 @@ public: QShortcutMap(); ~QShortcutMap(); - int addShortcut(QObject *owner, const QKeySequence &key, Qt::ShortcutContext context); + typedef bool (*ContextMatcher)(QObject *object, Qt::ShortcutContext context); + + int addShortcut(QObject *owner, const QKeySequence &key, Qt::ShortcutContext context, ContextMatcher matcher); int removeShortcut(int id, QObject *owner, const QKeySequence &key = QKeySequence()); int setShortcutEnabled(bool enable, int id, QObject *owner, const QKeySequence &key = QKeySequence()); int setShortcutAutoRepeat(bool on, int id, QObject *owner, const QKeySequence &key = QKeySequence()); @@ -98,13 +102,6 @@ public: private: - bool correctWidgetContext(Qt::ShortcutContext context, QWidget *w, QWidget *active_window) const; -#ifndef QT_NO_GRAPHICSVIEW - bool correctGraphicsWidgetContext(Qt::ShortcutContext context, QGraphicsWidget *w, QWidget *active_window) const; -#endif -#ifndef QT_NO_ACTION - bool correctContext(Qt::ShortcutContext context,QAction *a, QWidget *active_window) const; -#endif QScopedPointer d_ptr; QKeySequence::SequenceMatch find(QKeyEvent *e);