From fddc75e862032163af36d2282051758647b62d15 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Thu, 1 Jan 2015 19:51:44 +0100 Subject: Introduce Shortcut [ChangeLog][QtQuick] Added a Shortcut utility type for catching keyboard shortcuts Change-Id: I4af631bfa7987f0d809b1f5af499f1d9688a1e04 Reviewed-by: Caroline Chao Reviewed-by: Alan Alpert Reviewed-by: Shawn Rutledge --- src/quick/util/qquickshortcut.cpp | 283 ++++++++++++++++++++++++++++++++++++ src/quick/util/qquickshortcut_p.h | 109 ++++++++++++++ src/quick/util/qquickutilmodule.cpp | 3 + src/quick/util/util.pri | 6 +- 4 files changed, 399 insertions(+), 2 deletions(-) create mode 100644 src/quick/util/qquickshortcut.cpp create mode 100644 src/quick/util/qquickshortcut_p.h (limited to 'src') diff --git a/src/quick/util/qquickshortcut.cpp b/src/quick/util/qquickshortcut.cpp new file mode 100644 index 0000000000..cd7d265ed0 --- /dev/null +++ b/src/quick/util/qquickshortcut.cpp @@ -0,0 +1,283 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickshortcut_p.h" + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +/*! + \qmltype Shortcut + \instantiates QQuickShortcut + \inqmlmodule QtQuick + \since 5.5 + \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}, + 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. + + \qml + Item { + id: view + + property int currentIndex + + Shortcut { + sequence: StandardKey.NextChild + onActivated: view.currentIndex++ + } + } + \endqml + + \sa Keys +*/ + +/*! \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. +*/ + +QQuickShortcut::QQuickShortcut(QObject *parent) : QObject(parent), m_id(0), + m_enabled(true), m_completed(false), m_autorepeat(true), m_context(Qt::WindowShortcut) +{ +} + +QQuickShortcut::~QQuickShortcut() +{ + ungrabShortcut(); +} + +/*! + \qmlproperty keysequence QtQuick::Shortcut::sequence + + This property holds the shortcut's key sequence. The key sequence 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. + + The default value is an empty key sequence. + + \qml + Shortcut { + sequence: "Ctrl+E,Ctrl+W" + onActivated: edit.wrapMode = TextEdit.Wrap + } + \endqml +*/ +QVariant QQuickShortcut::sequence() const +{ + return m_sequence; +} + +void QQuickShortcut::setSequence(const QVariant &sequence) +{ + if (sequence == m_sequence) + return; + + QKeySequence shortcut; + if (sequence.type() == QVariant::Int) + shortcut = QKeySequence(static_cast(sequence.toInt())); + else + shortcut = QKeySequence::fromString(sequence.toString()); + + grabShortcut(shortcut, m_context); + + m_sequence = sequence; + m_shortcut = shortcut; + emit sequenceChanged(); +} + +/*! + \qmlproperty bool QtQuick::Shortcut::enabled + + This property holds whether the shortcut is enabled. + + The default value is \c true. +*/ +bool QQuickShortcut::isEnabled() const +{ + return m_enabled; +} + +void QQuickShortcut::setEnabled(bool enabled) +{ + if (enabled == m_enabled) + return; + + if (m_id) + QGuiApplicationPrivate::instance()->shortcutMap.setShortcutEnabled(enabled, m_id, this); + + m_enabled = enabled; + emit enabledChanged(); +} + +/*! + \qmlproperty bool QtQuick::Shortcut::autoRepeat + + This property holds whether the shortcut can auto repeat. + + The default value is \c true. +*/ +bool QQuickShortcut::autoRepeat() const +{ + return m_autorepeat; +} + +void QQuickShortcut::setAutoRepeat(bool repeat) +{ + if (repeat == m_autorepeat) + return; + + if (m_id) + QGuiApplicationPrivate::instance()->shortcutMap.setShortcutAutoRepeat(repeat, m_id, this); + + m_autorepeat = repeat; + emit autoRepeatChanged(); +} + +/*! + \qmlproperty enumeration QtQuick::Shortcut::context + + 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 + + \qml + Shortcut { + sequence: StandardKey.Quit + context: Qt.ApplicationShortcut + onActivated: Qt.quit() + } + \endqml +*/ +Qt::ShortcutContext QQuickShortcut::context() const +{ + return m_context; +} + +void QQuickShortcut::setContext(Qt::ShortcutContext context) +{ + if (context == m_context) + return; + + grabShortcut(m_shortcut, context); + + m_context = context; + emit contextChanged(); +} + +void QQuickShortcut::classBegin() +{ +} + +void QQuickShortcut::componentComplete() +{ + m_completed = true; + grabShortcut(m_shortcut, m_context); +} + +bool QQuickShortcut::event(QEvent *event) +{ + if (m_enabled && event->type() == QEvent::Shortcut) { + QShortcutEvent *se = static_cast(event); + if (se->shortcutId() == m_id && se->key() == m_shortcut){ + if (se->isAmbiguous()) + emit activatedAmbiguously(); + else + emit activated(); + return true; + } + } + return false; +} + +static bool qQuickShortcutContextMatcher(QObject *obj, Qt::ShortcutContext context) +{ + switch (context) { + case Qt::ApplicationShortcut: + return true; + case Qt::WindowShortcut: + while (obj && !obj->isWindowType()) { + obj = obj->parent(); + if (QQuickItem *item = qobject_cast(obj)) + obj = item->window(); + } + return obj && obj == QGuiApplication::focusWindow(); + default: + return false; + } +} + +void QQuickShortcut::grabShortcut(const QKeySequence &sequence, Qt::ShortcutContext context) +{ + ungrabShortcut(); + + if (m_completed && !sequence.isEmpty()) { + QGuiApplicationPrivate *pApp = QGuiApplicationPrivate::instance(); + m_id = pApp->shortcutMap.addShortcut(this, sequence, context, qQuickShortcutContextMatcher); + if (!m_enabled) + pApp->shortcutMap.setShortcutEnabled(false, m_id, this); + if (!m_autorepeat) + pApp->shortcutMap.setShortcutAutoRepeat(false, m_id, this); + } +} + +void QQuickShortcut::ungrabShortcut() +{ + if (m_id) { + QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(m_id, this); + m_id = 0; + } +} + +QT_END_NAMESPACE diff --git a/src/quick/util/qquickshortcut_p.h b/src/quick/util/qquickshortcut_p.h new file mode 100644 index 0000000000..d6ca02e00b --- /dev/null +++ b/src/quick/util/qquickshortcut_p.h @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKSHORTCUT_P_H +#define QQUICKSHORTCUT_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QQuickShortcut : public QObject, public QQmlParserStatus +{ + Q_OBJECT + Q_INTERFACES(QQmlParserStatus) + Q_PROPERTY(QVariant sequence READ sequence WRITE setSequence NOTIFY sequenceChanged FINAL) + Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged FINAL) + Q_PROPERTY(bool autoRepeat READ autoRepeat WRITE setAutoRepeat NOTIFY autoRepeatChanged FINAL) + Q_PROPERTY(Qt::ShortcutContext context READ context WRITE setContext NOTIFY contextChanged FINAL) + +public: + explicit QQuickShortcut(QObject *parent = Q_NULLPTR); + ~QQuickShortcut(); + + QVariant sequence() const; + void setSequence(const QVariant &sequence); + + bool isEnabled() const; + void setEnabled(bool enabled); + + bool autoRepeat() const; + void setAutoRepeat(bool repeat); + + Qt::ShortcutContext context() const; + void setContext(Qt::ShortcutContext context); + +Q_SIGNALS: + void sequenceChanged(); + void enabledChanged(); + void autoRepeatChanged(); + void contextChanged(); + + void activated(); + void activatedAmbiguously(); + +protected: + void classBegin() Q_DECL_OVERRIDE; + void componentComplete() Q_DECL_OVERRIDE; + bool event(QEvent *event) Q_DECL_OVERRIDE; + + void grabShortcut(const QKeySequence &sequence, Qt::ShortcutContext context); + void ungrabShortcut(); + +private: + int m_id; + bool m_enabled; + bool m_completed; + bool m_autorepeat; + QKeySequence m_shortcut; + Qt::ShortcutContext m_context; + QVariant m_sequence; +}; + +QT_END_NAMESPACE + +#endif // QQUICKSHORTCUT_P_H diff --git a/src/quick/util/qquickutilmodule.cpp b/src/quick/util/qquickutilmodule.cpp index 0b42c21e8b..3c4ba9d0d8 100644 --- a/src/quick/util/qquickutilmodule.cpp +++ b/src/quick/util/qquickutilmodule.cpp @@ -48,6 +48,7 @@ #include "qquicktextmetrics_p.h" #include "qquicktransition_p.h" #include "qquickanimator_p.h" +#include "qquickshortcut_p.h" #include #include #include @@ -103,4 +104,6 @@ void QQuickUtilModule::defineModule() qmlRegisterType("QtQuick", 2, 4, "FontMetrics"); qmlRegisterType("QtQuick", 2, 4, "TextMetrics"); + + qmlRegisterType("QtQuick", 2, 5, "Shortcut"); } diff --git a/src/quick/util/util.pri b/src/quick/util/util.pri index 76cf1996bc..0e0df4e751 100644 --- a/src/quick/util/util.pri +++ b/src/quick/util/util.pri @@ -28,7 +28,8 @@ SOURCES += \ $$PWD/qquickanimatorcontroller.cpp \ $$PWD/qquickprofiler.cpp \ $$PWD/qquickfontmetrics.cpp \ - $$PWD/qquicktextmetrics.cpp + $$PWD/qquicktextmetrics.cpp \ + $$PWD/qquickshortcut.cpp HEADERS += \ $$PWD/qquickapplication_p.h\ @@ -64,4 +65,5 @@ HEADERS += \ $$PWD/qquickanimatorcontroller_p.h \ $$PWD/qquickprofiler_p.h \ $$PWD/qquickfontmetrics_p.h \ - $$PWD/qquicktextmetrics_p.h + $$PWD/qquicktextmetrics_p.h \ + $$PWD/qquickshortcut_p.h -- cgit v1.2.3