diff options
Diffstat (limited to 'src/quick/util/qquickshortcut.cpp')
-rw-r--r-- | src/quick/util/qquickshortcut.cpp | 160 |
1 files changed, 85 insertions, 75 deletions
diff --git a/src/quick/util/qquickshortcut.cpp b/src/quick/util/qquickshortcut.cpp index 730a14369e..a6a0972d87 100644 --- a/src/quick/util/qquickshortcut.cpp +++ b/src/quick/util/qquickshortcut.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQuick 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) 2016 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 "qquickshortcut_p.h" @@ -44,6 +8,7 @@ #include <QtQuick/qquickrendercontrol.h> #include <QtQuick/private/qtquickglobal_p.h> #include <QtGui/private/qguiapplication_p.h> +#include <QtQml/qqmlinfo.h> /*! \qmltype Shortcut @@ -53,8 +18,9 @@ \ingroup qtquick-input \brief Provides keyboard shortcuts. - The Shortcut type provides a way of handling keyboard shortcuts. The shortcut can - be set to one of the \l{QKeySequence::StandardKey}{standard keyboard shortcuts}, + The Shortcut type lets you handle keyboard shortcuts. The shortcut can + be set to one of the + \l{QKeySequence::StandardKey}{standard keyboard shortcuts}, or it can be described with a string containing a sequence of up to four key presses that are needed to \l{Shortcut::activated}{activate} the shortcut. @@ -65,7 +31,7 @@ property int currentIndex Shortcut { - sequence: StandardKey.NextChild + sequences: [StandardKey.NextChild] onActivated: view.currentIndex++ } } @@ -80,16 +46,12 @@ /*! \qmlsignal QtQuick::Shortcut::activated() This signal is emitted when the shortcut is activated. - - The corresponding handler is \c onActivated. */ /*! \qmlsignal QtQuick::Shortcut::activatedAmbiguously() This signal is emitted when the shortcut is activated ambigously, meaning that it matches the start of more than one shortcut. - - The corresponding handler is \c onActivatedAmbiguously. */ static bool qQuickShortcutContextMatcher(QObject *obj, Qt::ShortcutContext context) @@ -115,12 +77,12 @@ typedef bool (*ContextMatcher)(QObject *, Qt::ShortcutContext); Q_GLOBAL_STATIC_WITH_ARGS(ContextMatcher, ctxMatcher, (qQuickShortcutContextMatcher)) -Q_QUICK_PRIVATE_EXPORT ContextMatcher qt_quick_shortcut_context_matcher() +Q_QUICK_EXPORT ContextMatcher qt_quick_shortcut_context_matcher() { return *ctxMatcher(); } -Q_QUICK_PRIVATE_EXPORT void qt_quick_set_shortcut_context_matcher(ContextMatcher matcher) +Q_QUICK_EXPORT void qt_quick_set_shortcut_context_matcher(ContextMatcher matcher) { if (!ctxMatcher.isDestroyed()) *ctxMatcher() = matcher; @@ -128,13 +90,35 @@ Q_QUICK_PRIVATE_EXPORT void qt_quick_set_shortcut_context_matcher(ContextMatcher QT_BEGIN_NAMESPACE -static QKeySequence valueToKeySequence(const QVariant &value) +static QKeySequence valueToKeySequence(const QVariant &value, const QQuickShortcut *const shortcut) { - if (value.type() == QVariant::Int) - return QKeySequence(static_cast<QKeySequence::StandardKey>(value.toInt())); + if (value.userType() == QMetaType::Int) { + const QVector<QKeySequence> s = + QKeySequence::keyBindings(static_cast<QKeySequence::StandardKey>(value.toInt())); + if (s.size() > 1) { + const QString templateString = QString::fromUtf16( + u"Shortcut: Only binding to one of multiple key bindings associated with %1. " + u"Use 'sequences: [ <key> ]' to bind to all of them."); + qmlWarning(shortcut) + << templateString.arg(static_cast<QKeySequence::StandardKey>(value.toInt())); + } + return s.size() > 0 ? s[0] : QKeySequence {}; + } + return QKeySequence::fromString(value.toString()); } +static QList<QKeySequence> valueToKeySequences(const QVariant &value) +{ + if (value.userType() == QMetaType::Int) { + return QKeySequence::keyBindings(static_cast<QKeySequence::StandardKey>(value.toInt())); + } else { + QList<QKeySequence> result; + result.push_back(QKeySequence::fromString(value.toString())); + return result; + } +} + QQuickShortcut::QQuickShortcut(QObject *parent) : QObject(parent), m_enabled(true), m_completed(false), m_autorepeat(true), m_context(Qt::WindowShortcut) { @@ -164,6 +148,10 @@ QQuickShortcut::~QQuickShortcut() } \endqml + \note Given that standard keys can resolve to one shortcut on some + platforms, but multiple shortcuts on other platforms, we recommend always + using \l{Shortcut::}{sequences} for standard keys. + \sa sequences */ QVariant QQuickShortcut::sequence() const @@ -176,7 +164,7 @@ void QQuickShortcut::setSequence(const QVariant &value) if (value == m_shortcut.userValue) return; - QKeySequence keySequence = valueToKeySequence(value); + QKeySequence keySequence = valueToKeySequence(value, this); ungrabShortcut(m_shortcut); m_shortcut.userValue = value; @@ -211,28 +199,42 @@ QVariantList QQuickShortcut::sequences() const void QQuickShortcut::setSequences(const QVariantList &values) { - QVector<Shortcut> remainder = m_shortcuts.mid(values.count()); - m_shortcuts.resize(values.count()); - - bool changed = !remainder.isEmpty(); - for (int i = 0; i < values.count(); ++i) { - QVariant value = values.at(i); - Shortcut& shortcut = m_shortcuts[i]; - if (value == shortcut.userValue) - continue; - - QKeySequence keySequence = valueToKeySequence(value); - - ungrabShortcut(shortcut); - shortcut.userValue = value; - shortcut.keySequence = keySequence; - grabShortcut(shortcut, m_context); + // convert QVariantList to QVector<QKeySequence> + QVector<Shortcut> requestedShortcuts; + for (const QVariant &v : values) { + const QVector<QKeySequence> list = valueToKeySequences(v); + for (const QKeySequence &s : list) { + Shortcut sc; + sc.userValue = v; + sc.keySequence = s; + requestedShortcuts.push_back(sc); + } + } - changed = true; + // if nothing has changed, just return: + if (m_shortcuts.size() == requestedShortcuts.size()) { + bool changed = false; + for (int i = 0; i < requestedShortcuts.size(); ++i) { + const Shortcut &requestedShortcut = requestedShortcuts[i]; + const Shortcut &shortcut = m_shortcuts[i]; + if (!(requestedShortcut.userValue == shortcut.userValue + && requestedShortcut.keySequence == shortcut.keySequence)) { + changed = true; + break; + } + } + if (!changed) { + return; + } } - if (changed) - emit sequencesChanged(); + for (Shortcut &s : m_shortcuts) + ungrabShortcut(s); + m_shortcuts = requestedShortcuts; + for (Shortcut &s : m_shortcuts) + grabShortcut(s, m_context); + + emit sequencesChanged(); } /*! @@ -322,10 +324,11 @@ void QQuickShortcut::setAutoRepeat(bool repeat) This property holds the \l{Qt::ShortcutContext}{shortcut context}. Supported values are: - \list - \li \c Qt.WindowShortcut (default) - The shortcut is active when its parent item is in an active top-level window. - \li \c Qt.ApplicationShortcut - The shortcut is active when one of the application's windows are active. - \endlist + + \value Qt.WindowShortcut + (default) The shortcut is active when its parent item is in an active top-level window. + \value Qt.ApplicationShortcut + The shortcut is active when one of the application's windows are active. \qml Shortcut { @@ -346,8 +349,15 @@ void QQuickShortcut::setContext(Qt::ShortcutContext context) return; ungrabShortcut(m_shortcut); + for (auto &s : m_shortcuts) + ungrabShortcut(s); + m_context = context; + grabShortcut(m_shortcut, context); + for (auto &s : m_shortcuts) + grabShortcut(s, context); + emit contextChanged(); } @@ -369,7 +379,7 @@ bool QQuickShortcut::event(QEvent *event) QShortcutEvent *se = static_cast<QShortcutEvent *>(event); bool match = m_shortcut.matches(se); int i = 0; - while (!match && i < m_shortcuts.count()) + while (!match && i < m_shortcuts.size()) match |= m_shortcuts.at(i++).matches(se); if (match) { if (se->isAmbiguous()) |