Extract QGuiShortcut
[ChangeLog][QtGui] Added QGuiShortcut and made the equivalent existing classes in Qt Widgets derive from them. This provides basic functionality for adding shortcut handling in QML. Fixes: QTBUG-79638 Task-number: QTBUG-76493 Change-Id: I5bbd2c8f192660e93c4690b9f894643275090e4d Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
This commit is contained in:
parent
5367f76e17
commit
89f1f14c5e
@ -169,10 +169,13 @@ qtConfig(opengl) {
|
||||
|
||||
qtConfig(shortcut) {
|
||||
HEADERS += \
|
||||
kernel/qguishortcut.h \
|
||||
kernel/qguishortcut_p.h \
|
||||
kernel/qshortcutmap_p.h \
|
||||
kernel/qkeysequence.h \
|
||||
kernel/qkeysequence_p.h
|
||||
SOURCES += \
|
||||
kernel/qguishortcut.cpp \
|
||||
kernel/qshortcutmap.cpp \
|
||||
kernel/qkeysequence.cpp
|
||||
}
|
||||
|
354
src/gui/kernel/qguishortcut.cpp
Normal file
354
src/gui/kernel/qguishortcut.cpp
Normal file
@ -0,0 +1,354 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** 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$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qguishortcut.h"
|
||||
#include "qguishortcut_p.h"
|
||||
|
||||
#include <qevent.h>
|
||||
#include <qguiapplication.h>
|
||||
#include <qwindow.h>
|
||||
#include <private/qguiapplication_p.h>
|
||||
#include <qpa/qplatformmenu.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
#define QAPP_CHECK(functionName) \
|
||||
if (Q_UNLIKELY(!qApp)) { \
|
||||
qWarning("QGuiShortcut: Initialize QGuiApplication before calling '" functionName "'."); \
|
||||
return; \
|
||||
}
|
||||
|
||||
/*!
|
||||
\class QGuiShortcut
|
||||
\brief The QGuiShortcut class is a base class for handling keyboard shortcuts.
|
||||
|
||||
\ingroup events
|
||||
\inmodule QtGui
|
||||
\since 6.0
|
||||
|
||||
The QGuiShortcut class is a base class for classes providing a way of
|
||||
connecting keyboard shortcuts to Qt's \l{signals and slots} mechanism,
|
||||
so that objects can be informed when a shortcut is executed. The shortcut
|
||||
can be set up to contain all the key presses necessary to
|
||||
describe a keyboard shortcut, including the states of modifier
|
||||
keys such as \uicontrol Shift, \uicontrol Ctrl, and \uicontrol Alt.
|
||||
|
||||
\target mnemonic
|
||||
|
||||
\sa QShortcutEvent, QKeySequence, QAction
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void QGuiShortcut::activated()
|
||||
|
||||
This signal is emitted when the user types the shortcut's key
|
||||
sequence.
|
||||
|
||||
\sa activatedAmbiguously()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void QGuiShortcut::activatedAmbiguously()
|
||||
|
||||
When a key sequence is being typed at the keyboard, it is said to
|
||||
be ambiguous as long as it matches the start of more than one
|
||||
shortcut.
|
||||
|
||||
When a shortcut's key sequence is completed,
|
||||
activatedAmbiguously() is emitted if the key sequence is still
|
||||
ambiguous (i.e., it is the start of one or more other shortcuts).
|
||||
The activated() signal is not emitted in this case.
|
||||
|
||||
\sa activated()
|
||||
*/
|
||||
|
||||
static bool simpleContextMatcher(QObject *object, Qt::ShortcutContext context)
|
||||
{
|
||||
auto guiShortcut = qobject_cast<QGuiShortcut *>(object);
|
||||
if (QGuiApplication::applicationState() != Qt::ApplicationActive || guiShortcut == nullptr)
|
||||
return false;
|
||||
if (context == Qt::ApplicationShortcut)
|
||||
return true;
|
||||
auto focusWindow = QGuiApplication::focusWindow();
|
||||
if (!focusWindow)
|
||||
return false;
|
||||
auto window = qobject_cast<const QWindow *>(guiShortcut->parent());
|
||||
if (!window)
|
||||
return false;
|
||||
if (focusWindow == window && focusWindow->isTopLevel())
|
||||
return context == Qt::WindowShortcut || context == Qt::WidgetWithChildrenShortcut;
|
||||
return focusWindow->isAncestorOf(window, QWindow::ExcludeTransients);
|
||||
}
|
||||
|
||||
QShortcutMap::ContextMatcher QGuiShortcutPrivate::contextMatcher() const
|
||||
{
|
||||
return simpleContextMatcher;
|
||||
}
|
||||
|
||||
void QGuiShortcutPrivate::redoGrab(QShortcutMap &map)
|
||||
{
|
||||
Q_Q(QGuiShortcut);
|
||||
if (Q_UNLIKELY(!parent)) {
|
||||
qWarning("QGuiShortcut: No window parent defined");
|
||||
return;
|
||||
}
|
||||
|
||||
if (sc_id)
|
||||
map.removeShortcut(sc_id, q);
|
||||
if (sc_sequence.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);
|
||||
}
|
||||
|
||||
/*!
|
||||
Constructs a QGuiShortcut object for the \a parent window. Since no
|
||||
shortcut key sequence is specified, the shortcut will not emit any
|
||||
signals.
|
||||
|
||||
\sa setKey()
|
||||
*/
|
||||
QGuiShortcut::QGuiShortcut(QWindow *parent)
|
||||
: QGuiShortcut(*new QGuiShortcutPrivate, parent)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Constructs a QGuiShortcut object for the \a parent window. The shortcut
|
||||
operates on its parent, listening for \l{QShortcutEvent}s that
|
||||
match the \a key sequence. 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.
|
||||
*/
|
||||
QGuiShortcut::QGuiShortcut(const QKeySequence &key, QWindow *parent,
|
||||
const char *member, const char *ambiguousMember,
|
||||
Qt::ShortcutContext context)
|
||||
: QGuiShortcut(*new QGuiShortcutPrivate, key, parent, member, ambiguousMember, context)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
QGuiShortcut::QGuiShortcut(QGuiShortcutPrivate &dd, QObject *parent)
|
||||
: QObject(dd, parent)
|
||||
{
|
||||
Q_ASSERT(parent != nullptr);
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
QGuiShortcut::QGuiShortcut(QGuiShortcutPrivate &dd,
|
||||
const QKeySequence &key, QObject *parent,
|
||||
const char *member, const char *ambiguousMember,
|
||||
Qt::ShortcutContext context)
|
||||
: QGuiShortcut(dd, parent)
|
||||
{
|
||||
QAPP_CHECK("QGuiShortcut");
|
||||
|
||||
Q_D(QGuiShortcut);
|
||||
d->sc_context = context;
|
||||
d->sc_sequence = key;
|
||||
d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap);
|
||||
if (member)
|
||||
connect(this, SIGNAL(activated()), parent, member);
|
||||
if (ambiguousMember)
|
||||
connect(this, SIGNAL(activatedAmbiguously()), parent, ambiguousMember);
|
||||
}
|
||||
|
||||
/*!
|
||||
Destroys the shortcut.
|
||||
*/
|
||||
QGuiShortcut::~QGuiShortcut()
|
||||
{
|
||||
Q_D(QGuiShortcut);
|
||||
if (qApp)
|
||||
QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(d->sc_id, this);
|
||||
}
|
||||
|
||||
/*!
|
||||
\property QGuiShortcut::key
|
||||
\brief the shortcut's 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:
|
||||
|
||||
\snippet code/src_gui_kernel_qshortcut.cpp 1
|
||||
|
||||
By default, this property contains an empty key sequence.
|
||||
*/
|
||||
void QGuiShortcut::setKey(const QKeySequence &key)
|
||||
{
|
||||
Q_D(QGuiShortcut);
|
||||
if (d->sc_sequence == key)
|
||||
return;
|
||||
QAPP_CHECK("setKey");
|
||||
d->sc_sequence = key;
|
||||
d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap);
|
||||
}
|
||||
|
||||
QKeySequence QGuiShortcut::key() const
|
||||
{
|
||||
Q_D(const QGuiShortcut);
|
||||
return d->sc_sequence;
|
||||
}
|
||||
|
||||
/*!
|
||||
\property QGuiShortcut::enabled
|
||||
\brief whether the shortcut is enabled
|
||||
|
||||
An enabled shortcut emits the activated() or activatedAmbiguously()
|
||||
signal when a QShortcutEvent occurs that matches the shortcut's
|
||||
key() sequence.
|
||||
|
||||
If the application is in \c WhatsThis mode the shortcut will not emit
|
||||
the signals, but will show the "What's This?" text instead.
|
||||
|
||||
By default, this property is \c true.
|
||||
|
||||
\sa whatsThis
|
||||
*/
|
||||
void QGuiShortcut::setEnabled(bool enable)
|
||||
{
|
||||
Q_D(QGuiShortcut);
|
||||
if (d->sc_enabled == enable)
|
||||
return;
|
||||
QAPP_CHECK("setEnabled");
|
||||
d->sc_enabled = enable;
|
||||
QGuiApplicationPrivate::instance()->shortcutMap.setShortcutEnabled(enable, d->sc_id, this);
|
||||
}
|
||||
|
||||
bool QGuiShortcut::isEnabled() const
|
||||
{
|
||||
Q_D(const QGuiShortcut);
|
||||
return d->sc_enabled;
|
||||
}
|
||||
|
||||
/*!
|
||||
\property QGuiShortcut::context
|
||||
\brief the context in which the shortcut is valid
|
||||
|
||||
A shortcut's context decides in which circumstances a shortcut is
|
||||
allowed to be triggered. The normal context is Qt::WindowShortcut,
|
||||
which allows the shortcut to trigger if the parent (the widget
|
||||
containing the shortcut) is a subwidget of the active top-level
|
||||
window.
|
||||
|
||||
By default, this property is set to Qt::WindowShortcut.
|
||||
*/
|
||||
void QGuiShortcut::setContext(Qt::ShortcutContext context)
|
||||
{
|
||||
Q_D(QGuiShortcut);
|
||||
if (d->sc_context == context)
|
||||
return;
|
||||
QAPP_CHECK("setContext");
|
||||
d->sc_context = context;
|
||||
d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap);
|
||||
}
|
||||
|
||||
Qt::ShortcutContext QGuiShortcut::context() const
|
||||
{
|
||||
Q_D(const QGuiShortcut);
|
||||
return d->sc_context;
|
||||
}
|
||||
|
||||
/*!
|
||||
\property QGuiShortcut::autoRepeat
|
||||
\brief whether the shortcut can auto repeat
|
||||
|
||||
If true, the shortcut will auto repeat when the keyboard shortcut
|
||||
combination is held down, provided that keyboard auto repeat is
|
||||
enabled on the system.
|
||||
The default value is true.
|
||||
*/
|
||||
void QGuiShortcut::setAutoRepeat(bool on)
|
||||
{
|
||||
Q_D(QGuiShortcut);
|
||||
if (d->sc_autorepeat == on)
|
||||
return;
|
||||
QAPP_CHECK("setAutoRepeat");
|
||||
d->sc_autorepeat = on;
|
||||
QGuiApplicationPrivate::instance()->shortcutMap.setShortcutAutoRepeat(on, d->sc_id, this);
|
||||
}
|
||||
|
||||
bool QGuiShortcut::autoRepeat() const
|
||||
{
|
||||
Q_D(const QGuiShortcut);
|
||||
return d->sc_autorepeat;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the shortcut's ID.
|
||||
|
||||
\sa QShortcutEvent::shortcutId()
|
||||
*/
|
||||
int QGuiShortcut::id() const
|
||||
{
|
||||
Q_D(const QGuiShortcut);
|
||||
return d->sc_id;
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
bool QGuiShortcut::event(QEvent *e)
|
||||
{
|
||||
Q_D(QGuiShortcut);
|
||||
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 (se->isAmbiguous())
|
||||
emit activatedAmbiguously();
|
||||
else
|
||||
emit activated();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return QObject::event(e);
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#include "moc_qguishortcut.cpp"
|
98
src/gui/kernel/qguishortcut.h
Normal file
98
src/gui/kernel/qguishortcut.h
Normal file
@ -0,0 +1,98 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** 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$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QGUISHORTCUT_H
|
||||
#define QGUISHORTCUT_H
|
||||
|
||||
#include <QtGui/qtguiglobal.h>
|
||||
#include <QtGui/qkeysequence.h>
|
||||
#include <QtCore/qobject.h>
|
||||
|
||||
QT_REQUIRE_CONFIG(shortcut);
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QGuiShortcutPrivate;
|
||||
class QWindow;
|
||||
|
||||
class Q_GUI_EXPORT QGuiShortcut : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DECLARE_PRIVATE(QGuiShortcut)
|
||||
Q_PROPERTY(QKeySequence key READ key WRITE setKey)
|
||||
Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)
|
||||
Q_PROPERTY(bool autoRepeat READ autoRepeat WRITE setAutoRepeat)
|
||||
Q_PROPERTY(Qt::ShortcutContext context READ context WRITE setContext)
|
||||
public:
|
||||
explicit QGuiShortcut(QWindow *parent);
|
||||
explicit QGuiShortcut(const QKeySequence& key, QWindow *parent,
|
||||
const char *member = nullptr, const char *ambiguousMember = nullptr,
|
||||
Qt::ShortcutContext context = Qt::WindowShortcut);
|
||||
~QGuiShortcut();
|
||||
|
||||
void setKey(const QKeySequence& key);
|
||||
QKeySequence key() const;
|
||||
|
||||
void setEnabled(bool enable);
|
||||
bool isEnabled() const;
|
||||
|
||||
void setContext(Qt::ShortcutContext context);
|
||||
Qt::ShortcutContext context() const;
|
||||
|
||||
void setAutoRepeat(bool on);
|
||||
bool autoRepeat() const;
|
||||
|
||||
int id() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void activated();
|
||||
void activatedAmbiguously();
|
||||
|
||||
protected:
|
||||
QGuiShortcut(QGuiShortcutPrivate &dd, QObject *parent);
|
||||
QGuiShortcut(QGuiShortcutPrivate &dd, const QKeySequence& key, QObject *parent,
|
||||
const char *member, const char *ambiguousMember,
|
||||
Qt::ShortcutContext context);
|
||||
|
||||
bool event(QEvent *e) override;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QGUISHORTCUT_H
|
92
src/gui/kernel/qguishortcut_p.h
Normal file
92
src/gui/kernel/qguishortcut_p.h
Normal file
@ -0,0 +1,92 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** 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$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QGUISHORTCUT_P_H
|
||||
#define QGUISHORTCUT_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 <QtGui/private/qtguiglobal_p.h>
|
||||
#include "qguishortcut.h"
|
||||
#include <QtGui/qkeysequence.h>
|
||||
|
||||
#include <QtCore/qstring.h>
|
||||
#include <QtCore/private/qobject_p.h>
|
||||
|
||||
#include <private/qshortcutmap_p.h>
|
||||
|
||||
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QShortcutMap;
|
||||
|
||||
/*
|
||||
\internal
|
||||
Private data accessed through d-pointer.
|
||||
*/
|
||||
class Q_GUI_EXPORT QGuiShortcutPrivate : public QObjectPrivate
|
||||
{
|
||||
Q_DECLARE_PUBLIC(QGuiShortcut)
|
||||
public:
|
||||
QGuiShortcutPrivate() = default;
|
||||
|
||||
virtual QShortcutMap::ContextMatcher contextMatcher() const;
|
||||
virtual bool handleWhatsThis() { return false; }
|
||||
|
||||
QKeySequence sc_sequence;
|
||||
Qt::ShortcutContext sc_context = Qt::WindowShortcut;
|
||||
bool sc_enabled = true;
|
||||
bool sc_autorepeat = true;
|
||||
int sc_id = 0;
|
||||
void redoGrab(QShortcutMap &map);
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QGUISHORTCUT_P_H
|
@ -52,6 +52,7 @@
|
||||
#endif
|
||||
#include <qapplication.h>
|
||||
#include <private/qapplication_p.h>
|
||||
#include "private/qguishortcut_p.h"
|
||||
#include <private/qshortcutmap_p.h>
|
||||
#if QT_CONFIG(action)
|
||||
# include <private/qaction_p.h>
|
||||
@ -61,13 +62,6 @@
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
#define QAPP_CHECK(functionName) \
|
||||
if (Q_UNLIKELY(!qApp)) { \
|
||||
qWarning("QShortcut: Initialize QApplication before calling '" functionName "'."); \
|
||||
return; \
|
||||
}
|
||||
|
||||
|
||||
static bool correctWidgetContext(Qt::ShortcutContext context, QWidget *w, QWidget *active_window);
|
||||
#if QT_CONFIG(graphicsview)
|
||||
static bool correctGraphicsWidgetContext(Qt::ShortcutContext context, QGraphicsWidget *w, QWidget *active_window);
|
||||
@ -396,65 +390,30 @@ static bool correctActionContext(Qt::ShortcutContext context, QAction *a, QWidge
|
||||
Returns the shortcut's parent widget.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void QShortcut::activated()
|
||||
|
||||
This signal is emitted when the user types the shortcut's key
|
||||
sequence.
|
||||
|
||||
\sa activatedAmbiguously()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void QShortcut::activatedAmbiguously()
|
||||
|
||||
When a key sequence is being typed at the keyboard, it is said to
|
||||
be ambiguous as long as it matches the start of more than one
|
||||
shortcut.
|
||||
|
||||
When a shortcut's key sequence is completed,
|
||||
activatedAmbiguously() is emitted if the key sequence is still
|
||||
ambiguous (i.e., it is the start of one or more other shortcuts).
|
||||
The activated() signal is not emitted in this case.
|
||||
|
||||
\sa activated()
|
||||
*/
|
||||
|
||||
/*
|
||||
\internal
|
||||
Private data accessed through d-pointer.
|
||||
*/
|
||||
class QShortcutPrivate : public QObjectPrivate
|
||||
class QShortcutPrivate : public QGuiShortcutPrivate
|
||||
{
|
||||
Q_DECLARE_PUBLIC(QShortcut)
|
||||
public:
|
||||
QShortcutPrivate() = default;
|
||||
QKeySequence sc_sequence;
|
||||
Qt::ShortcutContext sc_context = Qt::WindowShortcut;
|
||||
bool sc_enabled = true;
|
||||
bool sc_autorepeat = true;
|
||||
int sc_id = 0;
|
||||
|
||||
QShortcutMap::ContextMatcher contextMatcher() const override
|
||||
{ return qWidgetShortcutContextMatcher; }
|
||||
|
||||
bool handleWhatsThis() override;
|
||||
|
||||
QString sc_whatsthis;
|
||||
void redoGrab(QShortcutMap &map);
|
||||
};
|
||||
|
||||
void QShortcutPrivate::redoGrab(QShortcutMap &map)
|
||||
bool QShortcutPrivate::handleWhatsThis()
|
||||
{
|
||||
Q_Q(QShortcut);
|
||||
if (Q_UNLIKELY(!parent)) {
|
||||
qWarning("QShortcut: No widget parent defined");
|
||||
return;
|
||||
}
|
||||
|
||||
if (sc_id)
|
||||
map.removeShortcut(sc_id, q);
|
||||
if (sc_sequence.isEmpty())
|
||||
return;
|
||||
sc_id = map.addShortcut(q, sc_sequence, sc_context, qWidgetShortcutContextMatcher);
|
||||
if (!sc_enabled)
|
||||
map.setShortcutEnabled(false, sc_id, q);
|
||||
if (!sc_autorepeat)
|
||||
map.setShortcutAutoRepeat(false, sc_id, q);
|
||||
const bool result = QWhatsThis::inWhatsThisMode();
|
||||
if (result)
|
||||
QWhatsThis::showText(QCursor::pos(), sc_whatsthis);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -465,9 +424,8 @@ void QShortcutPrivate::redoGrab(QShortcutMap &map)
|
||||
\sa setKey()
|
||||
*/
|
||||
QShortcut::QShortcut(QWidget *parent)
|
||||
: QObject(*new QShortcutPrivate, parent)
|
||||
: QGuiShortcut(*new QShortcutPrivate, parent)
|
||||
{
|
||||
Q_ASSERT(parent != nullptr);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -481,114 +439,8 @@ QShortcut::QShortcut(QWidget *parent)
|
||||
QShortcut::QShortcut(const QKeySequence &key, QWidget *parent,
|
||||
const char *member, const char *ambiguousMember,
|
||||
Qt::ShortcutContext context)
|
||||
: QShortcut(parent)
|
||||
: QGuiShortcut(*new QShortcutPrivate, key, parent, member, ambiguousMember, context)
|
||||
{
|
||||
QAPP_CHECK("QShortcut");
|
||||
|
||||
Q_D(QShortcut);
|
||||
d->sc_context = context;
|
||||
d->sc_sequence = key;
|
||||
d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap);
|
||||
if (member)
|
||||
connect(this, SIGNAL(activated()), parent, member);
|
||||
if (ambiguousMember)
|
||||
connect(this, SIGNAL(activatedAmbiguously()), parent, ambiguousMember);
|
||||
}
|
||||
|
||||
/*!
|
||||
Destroys the shortcut.
|
||||
*/
|
||||
QShortcut::~QShortcut()
|
||||
{
|
||||
Q_D(QShortcut);
|
||||
if (qApp)
|
||||
QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(d->sc_id, this);
|
||||
}
|
||||
|
||||
/*!
|
||||
\property QShortcut::key
|
||||
\brief the shortcut's 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:
|
||||
|
||||
\snippet code/src_gui_kernel_qshortcut.cpp 1
|
||||
|
||||
By default, this property contains an empty key sequence.
|
||||
*/
|
||||
void QShortcut::setKey(const QKeySequence &key)
|
||||
{
|
||||
Q_D(QShortcut);
|
||||
if (d->sc_sequence == key)
|
||||
return;
|
||||
QAPP_CHECK("setKey");
|
||||
d->sc_sequence = key;
|
||||
d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap);
|
||||
}
|
||||
|
||||
QKeySequence QShortcut::key() const
|
||||
{
|
||||
Q_D(const QShortcut);
|
||||
return d->sc_sequence;
|
||||
}
|
||||
|
||||
/*!
|
||||
\property QShortcut::enabled
|
||||
\brief whether the shortcut is enabled
|
||||
|
||||
An enabled shortcut emits the activated() or activatedAmbiguously()
|
||||
signal when a QShortcutEvent occurs that matches the shortcut's
|
||||
key() sequence.
|
||||
|
||||
If the application is in \c WhatsThis mode the shortcut will not emit
|
||||
the signals, but will show the "What's This?" text instead.
|
||||
|
||||
By default, this property is \c true.
|
||||
|
||||
\sa whatsThis
|
||||
*/
|
||||
void QShortcut::setEnabled(bool enable)
|
||||
{
|
||||
Q_D(QShortcut);
|
||||
if (d->sc_enabled == enable)
|
||||
return;
|
||||
QAPP_CHECK("setEnabled");
|
||||
d->sc_enabled = enable;
|
||||
QGuiApplicationPrivate::instance()->shortcutMap.setShortcutEnabled(enable, d->sc_id, this);
|
||||
}
|
||||
|
||||
bool QShortcut::isEnabled() const
|
||||
{
|
||||
Q_D(const QShortcut);
|
||||
return d->sc_enabled;
|
||||
}
|
||||
|
||||
/*!
|
||||
\property QShortcut::context
|
||||
\brief the context in which the shortcut is valid
|
||||
|
||||
A shortcut's context decides in which circumstances a shortcut is
|
||||
allowed to be triggered. The normal context is Qt::WindowShortcut,
|
||||
which allows the shortcut to trigger if the parent (the widget
|
||||
containing the shortcut) is a subwidget of the active top-level
|
||||
window.
|
||||
|
||||
By default, this property is set to Qt::WindowShortcut.
|
||||
*/
|
||||
void QShortcut::setContext(Qt::ShortcutContext context)
|
||||
{
|
||||
Q_D(QShortcut);
|
||||
if(d->sc_context == context)
|
||||
return;
|
||||
QAPP_CHECK("setContext");
|
||||
d->sc_context = context;
|
||||
d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap);
|
||||
}
|
||||
|
||||
Qt::ShortcutContext QShortcut::context() const
|
||||
{
|
||||
Q_D(const QShortcut);
|
||||
return d->sc_context;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -618,66 +470,8 @@ QString QShortcut::whatsThis() const
|
||||
}
|
||||
|
||||
/*!
|
||||
\property QShortcut::autoRepeat
|
||||
\brief whether the shortcut can auto repeat
|
||||
\since 4.2
|
||||
|
||||
If true, the shortcut will auto repeat when the keyboard shortcut
|
||||
combination is held down, provided that keyboard auto repeat is
|
||||
enabled on the system.
|
||||
The default value is true.
|
||||
Destroys the shortcut.
|
||||
*/
|
||||
void QShortcut::setAutoRepeat(bool on)
|
||||
{
|
||||
Q_D(QShortcut);
|
||||
if (d->sc_autorepeat == on)
|
||||
return;
|
||||
QAPP_CHECK("setAutoRepeat");
|
||||
d->sc_autorepeat = on;
|
||||
QGuiApplicationPrivate::instance()->shortcutMap.setShortcutAutoRepeat(on, d->sc_id, this);
|
||||
}
|
||||
|
||||
bool QShortcut::autoRepeat() const
|
||||
{
|
||||
Q_D(const QShortcut);
|
||||
return d->sc_autorepeat;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the shortcut's ID.
|
||||
|
||||
\sa QShortcutEvent::shortcutId()
|
||||
*/
|
||||
int QShortcut::id() const
|
||||
{
|
||||
Q_D(const QShortcut);
|
||||
return d->sc_id;
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
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){
|
||||
#if QT_CONFIG(whatsthis)
|
||||
if (QWhatsThis::inWhatsThisMode()) {
|
||||
QWhatsThis::showText(QCursor::pos(), d->sc_whatsthis);
|
||||
} else
|
||||
#endif
|
||||
if (se->isAmbiguous())
|
||||
emit activatedAmbiguously();
|
||||
else
|
||||
emit activated();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return QObject::event(e);
|
||||
}
|
||||
QShortcut::~QShortcut() = default;
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#include "moc_qshortcut.cpp"
|
||||
|
@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Copyright (C) 2019 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtWidgets module of the Qt Toolkit.
|
||||
@ -42,55 +42,30 @@
|
||||
|
||||
#include <QtWidgets/qtwidgetsglobal.h>
|
||||
#include <QtWidgets/qwidget.h>
|
||||
#include <QtGui/qkeysequence.h>
|
||||
#include <QtGui/qguishortcut.h>
|
||||
|
||||
QT_REQUIRE_CONFIG(shortcut);
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QShortcutPrivate;
|
||||
class Q_WIDGETS_EXPORT QShortcut : public QObject
|
||||
class Q_WIDGETS_EXPORT QShortcut : public QGuiShortcut
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DECLARE_PRIVATE(QShortcut)
|
||||
Q_PROPERTY(QKeySequence key READ key WRITE setKey)
|
||||
Q_PROPERTY(QString whatsThis READ whatsThis WRITE setWhatsThis)
|
||||
Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)
|
||||
Q_PROPERTY(bool autoRepeat READ autoRepeat WRITE setAutoRepeat)
|
||||
Q_PROPERTY(Qt::ShortcutContext context READ context WRITE setContext)
|
||||
Q_DECLARE_PRIVATE(QShortcut)
|
||||
public:
|
||||
explicit QShortcut(QWidget *parent);
|
||||
QShortcut(const QKeySequence& key, QWidget *parent,
|
||||
const char *member = nullptr, const char *ambiguousMember = nullptr,
|
||||
Qt::ShortcutContext context = Qt::WindowShortcut);
|
||||
explicit QShortcut(const QKeySequence& key, QWidget *parent,
|
||||
const char *member = nullptr, const char *ambiguousMember = nullptr,
|
||||
Qt::ShortcutContext context = Qt::WindowShortcut);
|
||||
~QShortcut();
|
||||
|
||||
void setKey(const QKeySequence& key);
|
||||
QKeySequence key() const;
|
||||
|
||||
void setEnabled(bool enable);
|
||||
bool isEnabled() const;
|
||||
|
||||
void setContext(Qt::ShortcutContext context);
|
||||
Qt::ShortcutContext context() const;
|
||||
|
||||
void setWhatsThis(const QString &text);
|
||||
QString whatsThis() const;
|
||||
|
||||
void setAutoRepeat(bool on);
|
||||
bool autoRepeat() const;
|
||||
|
||||
int id() const;
|
||||
|
||||
inline QWidget *parentWidget() const
|
||||
{ return static_cast<QWidget *>(QObject::parent()); }
|
||||
|
||||
Q_SIGNALS:
|
||||
void activated();
|
||||
void activatedAmbiguously();
|
||||
|
||||
protected:
|
||||
bool event(QEvent *e) override;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -11,6 +11,7 @@ SUBDIRS=\
|
||||
qguieventdispatcher \
|
||||
qguieventloop \
|
||||
qguimetatype \
|
||||
qguishortcut \
|
||||
qguitimer \
|
||||
qguivariant \
|
||||
qhighdpiscaling \
|
||||
@ -33,6 +34,7 @@ win32:!winrt:qtHaveModule(network): SUBDIRS += noqteventloop
|
||||
|
||||
!qtConfig(shortcut): SUBDIRS -= \
|
||||
qkeysequence \
|
||||
qguishortcut \
|
||||
qguimetatype \
|
||||
qguivariant
|
||||
|
||||
|
4
tests/auto/gui/kernel/qguishortcut/qguishortcut.pro
Normal file
4
tests/auto/gui/kernel/qguishortcut/qguishortcut.pro
Normal file
@ -0,0 +1,4 @@
|
||||
CONFIG += testcase
|
||||
TARGET = tst_qguishortcut
|
||||
QT += testlib
|
||||
SOURCES += tst_qguishortcut.cpp
|
82
tests/auto/gui/kernel/qguishortcut/tst_qguishortcut.cpp
Normal file
82
tests/auto/gui/kernel/qguishortcut/tst_qguishortcut.cpp
Normal file
@ -0,0 +1,82 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2019 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the test suite of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
|
||||
** 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 General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** 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-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <QtTest/QtTest>
|
||||
#include <QtGui/qguiapplication.h>
|
||||
#include <QtGui/qguishortcut.h>
|
||||
#include <QtGui/qpainter.h>
|
||||
#include <QtGui/qrasterwindow.h>
|
||||
#include <QtGui/qscreen.h>
|
||||
#include <QtGui/qwindow.h>
|
||||
|
||||
class tst_QGuiShortcut : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
private slots:
|
||||
void trigger();
|
||||
};
|
||||
|
||||
class ColoredWindow : public QRasterWindow {
|
||||
public:
|
||||
ColoredWindow(QColor c) : m_color(c) {}
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
|
||||
private:
|
||||
const QColor m_color;
|
||||
};
|
||||
|
||||
void ColoredWindow::paintEvent(QPaintEvent *)
|
||||
{
|
||||
QPainter p(this);
|
||||
p.fillRect(QRect(QPoint(), size()), m_color);
|
||||
}
|
||||
|
||||
static void sendKey(QWindow *target, Qt::Key k, char c, Qt::KeyboardModifiers modifiers)
|
||||
{
|
||||
QTest::sendKeyEvent(QTest::Press, target, k, c, modifiers);
|
||||
QTest::sendKeyEvent(QTest::Release, target, k, c, modifiers);
|
||||
}
|
||||
|
||||
void tst_QGuiShortcut::trigger()
|
||||
{
|
||||
ColoredWindow w(Qt::yellow);
|
||||
w.setTitle(QTest::currentTestFunction());
|
||||
w.resize(QGuiApplication::primaryScreen()->size() / 4);
|
||||
new QGuiShortcut(Qt::CTRL + Qt::Key_Q, &w, SLOT(close()));
|
||||
w.show();
|
||||
QVERIFY(QTest::qWaitForWindowExposed(&w));
|
||||
sendKey(&w, Qt::Key_Q, 'q', Qt::ControlModifier);
|
||||
QTRY_VERIFY(!w.isVisible());
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QGuiShortcut)
|
||||
#include "tst_qguishortcut.moc"
|
Loading…
Reference in New Issue
Block a user