diff options
Diffstat (limited to 'src/gui/kernel/qshortcut.cpp')
-rw-r--r-- | src/gui/kernel/qshortcut.cpp | 279 |
1 files changed, 188 insertions, 91 deletions
diff --git a/src/gui/kernel/qshortcut.cpp b/src/gui/kernel/qshortcut.cpp index c4305d5a7f..3f6822cb03 100644 --- a/src/gui/kernel/qshortcut.cpp +++ b/src/gui/kernel/qshortcut.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2019 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qshortcut.h" #include "qshortcut_p.h" @@ -132,7 +96,7 @@ QT_BEGIN_NAMESPACE \sa activated() */ -static bool simpleContextMatcher(QObject *object, Qt::ShortcutContext context) +bool QShortcutPrivate::simpleContextMatcher(QObject *object, Qt::ShortcutContext context) { auto guiShortcut = qobject_cast<QShortcut *>(object); if (QGuiApplication::applicationState() != Qt::ApplicationActive || guiShortcut == nullptr) @@ -163,15 +127,23 @@ void QShortcutPrivate::redoGrab(QShortcutMap &map) return; } - if (sc_id) - map.removeShortcut(sc_id, q); - if (sc_sequence.isEmpty()) + for (int id : std::as_const(sc_ids)) + map.removeShortcut(id, q); + + sc_ids.clear(); + if (sc_sequences.isEmpty()) return; - sc_id = map.addShortcut(q, sc_sequence, sc_context, contextMatcher()); - if (!sc_enabled) - map.setShortcutEnabled(false, sc_id, q); - if (!sc_autorepeat) - map.setShortcutAutoRepeat(false, sc_id, q); + sc_ids.reserve(sc_sequences.size()); + for (const auto &keySequence : std::as_const(sc_sequences)) { + if (keySequence.isEmpty()) + continue; + int id = map.addShortcut(q, keySequence, sc_context, contextMatcher()); + sc_ids.append(id); + if (!sc_enabled) + map.setShortcutEnabled(false, id, q); + if (!sc_autorepeat) + map.setShortcutAutoRepeat(false, id, q); + } } QShortcutPrivate *QGuiApplicationPrivate::createShortcutPrivate() const @@ -210,7 +182,34 @@ QShortcut::QShortcut(const QKeySequence &key, QObject *parent, { Q_D(QShortcut); d->sc_context = context; - d->sc_sequence = key; + if (!key.isEmpty()) { + d->sc_sequences = { key }; + d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap); + } + if (member) + connect(this, SIGNAL(activated()), parent, member); + if (ambiguousMember) + connect(this, SIGNAL(activatedAmbiguously()), parent, ambiguousMember); +} + +/*! + \since 6.0 + Constructs a QShortcut object for the \a parent, which should be a + QWindow or a QWidget. + + The shortcut operates on its parent, listening for \l{QShortcutEvent}s that + match the \a standardKey. Depending on the ambiguity of the event, the + shortcut will call the \a member function, or the \a ambiguousMember function, + if the key press was in the shortcut's \a context. +*/ +QShortcut::QShortcut(QKeySequence::StandardKey standardKey, QObject *parent, + const char *member, const char *ambiguousMember, + Qt::ShortcutContext context) + : QShortcut(parent) +{ + Q_D(QShortcut); + d->sc_context = context; + d->sc_sequences = QKeySequence::keyBindings(standardKey); d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap); if (member) connect(this, SIGNAL(activated()), parent, member); @@ -220,10 +219,7 @@ QShortcut::QShortcut(const QKeySequence &key, QObject *parent, /*! - \fn template<typename Functor> - QShortcut(const QKeySequence &key, QObject *parent, - Functor functor, - Qt::ShortcutContext shortcutContext = Qt::WindowShortcut); + \fn template<typename Functor> QShortcut::QShortcut(const QKeySequence &key, QObject *parent, Functor functor, Qt::ShortcutContext shortcutContext = Qt::WindowShortcut) \since 5.15 \overload @@ -231,10 +227,7 @@ QShortcut::QShortcut(const QKeySequence &key, QObject *parent, \l{QShortcut::activated()}{activated()} signal to the \a functor. */ /*! - \fn template<typename Functor> - QShortcut(const QKeySequence &key, QObject *parent, - const QObject *context, Functor functor, - Qt::ShortcutContext shortcutContext = Qt::WindowShortcut); + \fn template<typename Functor> QShortcut::QShortcut(const QKeySequence &key, QObject *parent, const QObject *context, Functor functor, Qt::ShortcutContext shortcutContext = Qt::WindowShortcut) \since 5.15 \overload @@ -246,46 +239,94 @@ QShortcut::QShortcut(const QKeySequence &key, QObject *parent, If the \a context object is destroyed, the \a functor will not be called. */ /*! - \fn template<typename Functor, typename FunctorAmbiguous> - QShortcut(const QKeySequence &key, QObject *parent, - const QObject *context1, Functor functor, - FunctorAmbiguous functorAmbiguous, - Qt::ShortcutContext shortcutContext = Qt::WindowShortcut); + \fn template<typename Functor, typename FunctorAmbiguous> QShortcut::QShortcut(const QKeySequence &key, QObject *parent, const QObject *context, Functor functor, FunctorAmbiguous functorAmbiguous, Qt::ShortcutContext shortcutContext = Qt::WindowShortcut) \since 5.15 \overload This is a QShortcut convenience constructor which connects the shortcut's \l{QShortcut::activated()}{activated()} signal to the \a functor and \l{QShortcut::activatedAmbiguously()}{activatedAmbiguously()} - signal to the \a FunctorAmbiguous. + signal to the \a functorAmbiguous. - The \a functor and \a FunctorAmbiguous can be a pointer to a member + The \a functor and \a functorAmbiguous can be a pointer to a member function of the \a context object. If the \a context object is destroyed, the \a functor and - \a FunctorAmbiguous will not be called. + \a functorAmbiguous will not be called. */ /*! - \fn template<typename Functor, typename FunctorAmbiguous> - QShortcut(const QKeySequence &key, QObject *parent, - const QObject *context1, Functor functor, - const QObject *context2, FunctorAmbiguous functorAmbiguous, - Qt::ShortcutContext shortcutContext = Qt::WindowShortcut); + \fn template<typename Functor, typename FunctorAmbiguous> QShortcut::QShortcut(const QKeySequence &key, QObject *parent, const QObject *context1, Functor functor, const QObject *context2, FunctorAmbiguous functorAmbiguous, Qt::ShortcutContext shortcutContext = Qt::WindowShortcut) \since 5.15 \overload This is a QShortcut convenience constructor which connects the shortcut's \l{QShortcut::activated()}{activated()} signal to the \a functor and \l{QShortcut::activatedAmbiguously()}{activatedAmbiguously()} - signal to the \a FunctorAmbiguous. + signal to the \a functorAmbiguous. + + The \a functor can be a pointer to a member function of the + \a context1 object. + The \a functorAmbiguous can be a pointer to a member function of the + \a context2 object. + + If the \a context1 object is destroyed, the \a functor will not be called. + If the \a context2 object is destroyed, the \a functorAmbiguous + will not be called. +*/ + +/*! + \fn template<typename Functor> QShortcut::QShortcut(QKeySequence::StandardKey key, QObject *parent, Functor functor, Qt::ShortcutContext shortcutContext = Qt::WindowShortcut) + \since 6.0 + \overload + + This is a QShortcut convenience constructor which connects the shortcut's + \l{QShortcut::activated()}{activated()} signal to the \a functor. +*/ +/*! + \fn template<typename Functor> QShortcut::QShortcut(QKeySequence::StandardKey key, QObject *parent, const QObject *context, Functor functor, Qt::ShortcutContext shortcutContext = Qt::WindowShortcut) + \since 6.0 + \overload + + This is a QShortcut convenience constructor which connects the shortcut's + \l{QShortcut::activated()}{activated()} signal to the \a functor. + + The \a functor can be a pointer to a member function of the \a context object. + + If the \a context object is destroyed, the \a functor will not be called. +*/ +/*! + \fn template<typename Functor, typename FunctorAmbiguous> QShortcut::QShortcut(QKeySequence::StandardKey key, QObject *parent, const QObject *context, Functor functor, FunctorAmbiguous functorAmbiguous, Qt::ShortcutContext shortcutContext = Qt::WindowShortcut) + \since 6.0 + \overload + + This is a QShortcut convenience constructor which connects the shortcut's + \l{QShortcut::activated()}{activated()} signal to the \a functor and + \l{QShortcut::activatedAmbiguously()}{activatedAmbiguously()} + signal to the \a functorAmbiguous. + + The \a functor and \a functorAmbiguous can be a pointer to a member + function of the \a context object. + + If the \a context object is destroyed, the \a functor and + \a functorAmbiguous will not be called. +*/ +/*! + \fn template<typename Functor, typename FunctorAmbiguous> QShortcut::QShortcut(QKeySequence::StandardKey key, QObject *parent, const QObject *context1, Functor functor, const QObject *context2, FunctorAmbiguous functorAmbiguous, Qt::ShortcutContext shortcutContext = Qt::WindowShortcut) + \since 6.0 + \overload + + This is a QShortcut convenience constructor which connects the shortcut's + \l{QShortcut::activated()}{activated()} signal to the \a functor and + \l{QShortcut::activatedAmbiguously()}{activatedAmbiguously()} + signal to the \a functorAmbiguous. The \a functor can be a pointer to a member function of the \a context1 object. - The \a FunctorAmbiguous can be a pointer to a member function of the + The \a functorAmbiguous can be a pointer to a member function of the \a context2 object. If the \a context1 object is destroyed, the \a functor will not be called. - If the \a context2 object is destroyed, the \a FunctorAmbiguous + If the \a context2 object is destroyed, the \a functorAmbiguous will not be called. */ @@ -295,13 +336,15 @@ QShortcut::QShortcut(const QKeySequence &key, QObject *parent, QShortcut::~QShortcut() { Q_D(QShortcut); - if (qApp) - QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(d->sc_id, this); + if (qApp) { + for (int id : std::as_const(d->sc_ids)) + QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(id, this); + } } /*! \property QShortcut::key - \brief the shortcut's key sequence + \brief the shortcut's primary key sequence This is a key sequence with an optional combination of Shift, Ctrl, and Alt. The key sequence may be supplied in a number of ways: @@ -312,18 +355,61 @@ QShortcut::~QShortcut() */ void QShortcut::setKey(const QKeySequence &key) { + if (key.isEmpty()) + setKeys({}); + else + setKeys({ key }); +} + +QKeySequence QShortcut::key() const +{ + Q_D(const QShortcut); + if (d->sc_sequences.isEmpty()) + return QKeySequence(); + return d->sc_sequences.first(); +} + +/*! + Sets \a keys as the list of key sequences that trigger the + shortcut. + + \since 6.0 + + \sa key, keys() +*/ +void QShortcut::setKeys(const QList<QKeySequence> &keys) +{ Q_D(QShortcut); - if (d->sc_sequence == key) + if (d->sc_sequences == keys) return; - QAPP_CHECK("setKey"); - d->sc_sequence = key; + QAPP_CHECK("setKeys"); + d->sc_sequences = keys; d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap); } -QKeySequence QShortcut::key() const +/*! + Sets the triggers to those matching the standard key \a key. + + \since 6.0 + + \sa key, keys() +*/ +void QShortcut::setKeys(QKeySequence::StandardKey key) +{ + setKeys(QKeySequence::keyBindings(key)); +} + +/*! + Returns the list of key sequences which trigger this + shortcut. + + \since 6.0 + \sa key, setKeys() +*/ +QList<QKeySequence> QShortcut::keys() const { Q_D(const QShortcut); - return d->sc_sequence; + return d->sc_sequences; } /*! @@ -348,7 +434,8 @@ void QShortcut::setEnabled(bool enable) return; QAPP_CHECK("setEnabled"); d->sc_enabled = enable; - QGuiApplicationPrivate::instance()->shortcutMap.setShortcutEnabled(enable, d->sc_id, this); + for (int id : d->sc_ids) + QGuiApplicationPrivate::instance()->shortcutMap.setShortcutEnabled(enable, id, this); } bool QShortcut::isEnabled() const @@ -401,7 +488,8 @@ void QShortcut::setAutoRepeat(bool on) return; QAPP_CHECK("setAutoRepeat"); d->sc_autorepeat = on; - QGuiApplicationPrivate::instance()->shortcutMap.setShortcutAutoRepeat(on, d->sc_id, this); + for (int id : d->sc_ids) + QGuiApplicationPrivate::instance()->shortcutMap.setShortcutAutoRepeat(on, id, this); } bool QShortcut::autoRepeat() const @@ -412,8 +500,7 @@ bool QShortcut::autoRepeat() const /*! - \property QShortcut::whatsThis - \brief the shortcut's "What's This?" help text + Sets the shortcut's "What's This?" help \a text. The text will be shown when a widget application is in "What's This?" mode and the user types the shortcut key() sequence. @@ -421,9 +508,9 @@ bool QShortcut::autoRepeat() const To set "What's This?" help on a menu item (with or without a shortcut key), set the help on the item's action. - By default, this property contains an empty string. + By default, the help text is an empty string. - This property has no effect in applications that don't use + This function has no effect in applications that don't use widgets. \sa QWhatsThis::inWhatsThisMode(), QAction::setWhatsThis() @@ -434,23 +521,33 @@ void QShortcut::setWhatsThis(const QString &text) d->sc_whatsthis = text; } +/*! + Returns the shortcut's "What's This?" help text. + + \sa setWhatsThis() +*/ QString QShortcut::whatsThis() const { Q_D(const QShortcut); return d->sc_whatsthis; } - +#if QT_DEPRECATED_SINCE(6,0) /*! - Returns the shortcut's ID. + Returns the primary key binding's ID. + + \deprecated \sa QShortcutEvent::shortcutId() */ int QShortcut::id() const { Q_D(const QShortcut); - return d->sc_id; + if (d->sc_ids.isEmpty()) + return 0; + return d->sc_ids.first(); } +#endif /*! \fn QWidget *QShortcut::parentWidget() const @@ -466,8 +563,8 @@ bool QShortcut::event(QEvent *e) Q_D(QShortcut); if (d->sc_enabled && e->type() == QEvent::Shortcut) { auto se = static_cast<QShortcutEvent *>(e); - if (se->shortcutId() == d->sc_id && se->key() == d->sc_sequence - && !d->handleWhatsThis()) { + if (!d->handleWhatsThis()) { + Q_ASSERT_X(d->sc_ids.contains(se->shortcutId()), "QShortcut::event", "Received shortcut event from wrong shortcut"); if (se->isAmbiguous()) emit activatedAmbiguously(); else |