Shortcut: add sequenceString property
[platform/upstream/qtdeclarative.git] / src / quick / util / qquickshortcut.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtQuick module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL21$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** $QT_END_LICENSE$
31 **
32 ****************************************************************************/
33
34 #include "qquickshortcut_p.h"
35
36 #include <QtQuick/qquickitem.h>
37 #include <QtQuick/qquickwindow.h>
38 #include <QtGui/private/qguiapplication_p.h>
39
40 QT_BEGIN_NAMESPACE
41
42 /*!
43     \qmltype Shortcut
44     \instantiates QQuickShortcut
45     \inqmlmodule QtQuick
46     \since 5.5
47     \ingroup qtquick-input
48     \brief Provides keyboard shortcuts
49
50     The Shortcut type provides a way of handling keyboard shortcuts. The shortcut can
51     be set to one of the \l{QKeySequence::StandardKey}{standard keyboard shortcuts},
52     or it can be described with a string containing a sequence of up to four key
53     presses that are needed to \l{Shortcut::activated}{activate} the shortcut.
54
55     \qml
56     Item {
57         id: view
58
59         property int currentIndex
60
61         Shortcut {
62             sequence: StandardKey.NextChild
63             onActivated: view.currentIndex++
64         }
65     }
66     \endqml
67
68     \sa Keys
69 */
70
71 /*! \qmlsignal QtQuick::Shortcut::activated()
72
73     This signal is emitted when the shortcut is activated.
74
75     The corresponding handler is \c onActivated.
76 */
77
78 /*! \qmlsignal QtQuick::Shortcut::activatedAmbiguously()
79
80     This signal is emitted when the shortcut is activated ambigously,
81     meaning that it matches the start of more than one shortcut.
82
83     The corresponding handler is \c onActivatedAmbiguously.
84 */
85
86 QQuickShortcut::QQuickShortcut(QObject *parent) : QObject(parent), m_id(0),
87     m_enabled(true), m_completed(false), m_autorepeat(true), m_context(Qt::WindowShortcut)
88 {
89 }
90
91 QQuickShortcut::~QQuickShortcut()
92 {
93     ungrabShortcut();
94 }
95
96 /*!
97     \qmlproperty keysequence QtQuick::Shortcut::sequence
98
99     This property holds the shortcut's key sequence. The key sequence can be set
100     to one of the \l{QKeySequence::StandardKey}{standard keyboard shortcuts}, or
101     it can be described with a string containing a sequence of up to four key
102     presses that are needed to \l{Shortcut::activated}{activate} the shortcut.
103
104     The default value is an empty key sequence.
105
106     \qml
107     Shortcut {
108         sequence: "Ctrl+E,Ctrl+W"
109         onActivated: edit.wrapMode = TextEdit.Wrap
110     }
111     \endqml
112 */
113 QVariant QQuickShortcut::sequence() const
114 {
115     return m_sequence;
116 }
117
118 void QQuickShortcut::setSequence(const QVariant &sequence)
119 {
120     if (sequence == m_sequence)
121         return;
122
123     QKeySequence shortcut;
124     if (sequence.type() == QVariant::Int)
125         shortcut = QKeySequence(static_cast<QKeySequence::StandardKey>(sequence.toInt()));
126     else
127         shortcut = QKeySequence::fromString(sequence.toString());
128
129     grabShortcut(shortcut, m_context);
130
131     m_sequence = sequence;
132     m_shortcut = shortcut;
133     emit sequenceChanged();
134 }
135
136 /*!
137     \qmlproperty string QtQuick::Shortcut::sequenceString
138     \since 5.6
139
140     This property provides the shortcut's key sequence as a string,
141     for display purposes (tooltips, for example).
142
143     \sa sequence
144 */
145 QString QQuickShortcut::sequenceString() const
146 {
147     return m_shortcut.toString(QKeySequence::NativeText);
148 }
149
150 /*!
151     \qmlproperty bool QtQuick::Shortcut::enabled
152
153     This property holds whether the shortcut is enabled.
154
155     The default value is \c true.
156 */
157 bool QQuickShortcut::isEnabled() const
158 {
159     return m_enabled;
160 }
161
162 void QQuickShortcut::setEnabled(bool enabled)
163 {
164     if (enabled == m_enabled)
165         return;
166
167     if (m_id)
168         QGuiApplicationPrivate::instance()->shortcutMap.setShortcutEnabled(enabled, m_id, this);
169
170     m_enabled = enabled;
171     emit enabledChanged();
172 }
173
174 /*!
175     \qmlproperty bool QtQuick::Shortcut::autoRepeat
176
177     This property holds whether the shortcut can auto repeat.
178
179     The default value is \c true.
180 */
181 bool QQuickShortcut::autoRepeat() const
182 {
183     return m_autorepeat;
184 }
185
186 void QQuickShortcut::setAutoRepeat(bool repeat)
187 {
188     if (repeat == m_autorepeat)
189         return;
190
191     if (m_id)
192         QGuiApplicationPrivate::instance()->shortcutMap.setShortcutAutoRepeat(repeat, m_id, this);
193
194     m_autorepeat = repeat;
195     emit autoRepeatChanged();
196 }
197
198 /*!
199     \qmlproperty enumeration QtQuick::Shortcut::context
200
201     This property holds the \l{Qt::ShortcutContext}{shortcut context}.
202
203     Supported values are:
204     \list
205     \li \c Qt.WindowShortcut (default) - The shortcut is active when its parent item is in an active top-level window.
206     \li \c Qt.ApplicationShortcut - The shortcut is active when one of the application's windows are active.
207     \endlist
208
209     \qml
210     Shortcut {
211         sequence: StandardKey.Quit
212         context: Qt.ApplicationShortcut
213         onActivated: Qt.quit()
214     }
215     \endqml
216 */
217 Qt::ShortcutContext QQuickShortcut::context() const
218 {
219     return m_context;
220 }
221
222 void QQuickShortcut::setContext(Qt::ShortcutContext context)
223 {
224     if (context == m_context)
225         return;
226
227     grabShortcut(m_shortcut, context);
228
229     m_context = context;
230     emit contextChanged();
231 }
232
233 void QQuickShortcut::classBegin()
234 {
235 }
236
237 void QQuickShortcut::componentComplete()
238 {
239     m_completed = true;
240     grabShortcut(m_shortcut, m_context);
241 }
242
243 bool QQuickShortcut::event(QEvent *event)
244 {
245     if (m_enabled && event->type() == QEvent::Shortcut) {
246         QShortcutEvent *se = static_cast<QShortcutEvent *>(event);
247         if (se->shortcutId() == m_id && se->key() == m_shortcut){
248             if (se->isAmbiguous())
249                 emit activatedAmbiguously();
250             else
251                 emit activated();
252             return true;
253         }
254     }
255     return false;
256 }
257
258 static bool qQuickShortcutContextMatcher(QObject *obj, Qt::ShortcutContext context)
259 {
260     switch (context) {
261     case Qt::ApplicationShortcut:
262         return true;
263     case Qt::WindowShortcut:
264         while (obj && !obj->isWindowType()) {
265             obj = obj->parent();
266             if (QQuickItem *item = qobject_cast<QQuickItem *>(obj))
267                 obj = item->window();
268         }
269         return obj && obj == QGuiApplication::focusWindow();
270     default:
271         return false;
272     }
273 }
274
275 void QQuickShortcut::grabShortcut(const QKeySequence &sequence, Qt::ShortcutContext context)
276 {
277     ungrabShortcut();
278
279     if (m_completed && !sequence.isEmpty()) {
280         QGuiApplicationPrivate *pApp = QGuiApplicationPrivate::instance();
281         m_id = pApp->shortcutMap.addShortcut(this, sequence, context, qQuickShortcutContextMatcher);
282         if (!m_enabled)
283             pApp->shortcutMap.setShortcutEnabled(false, m_id, this);
284         if (!m_autorepeat)
285             pApp->shortcutMap.setShortcutAutoRepeat(false, m_id, this);
286     }
287 }
288
289 void QQuickShortcut::ungrabShortcut()
290 {
291     if (m_id) {
292         QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(m_id, this);
293         m_id = 0;
294     }
295 }
296
297 QT_END_NAMESPACE