1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtWidgets module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
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 https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://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 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qshortcut.h"
41#include "private/qwidget_p.h"
42
43#ifndef QT_NO_SHORTCUT
44#include <qevent.h>
45#if QT_CONFIG(whatsthis)
46#include <qwhatsthis.h>
47#endif
48#if QT_CONFIG(menu)
49#include <qmenu.h>
50#endif
51#if QT_CONFIG(menubar)
52#include <qmenubar.h>
53#endif
54#include <qapplication.h>
55#include <private/qapplication_p.h>
56#include <private/qshortcutmap_p.h>
57#include <private/qaction_p.h>
58#include <private/qwidgetwindow_p.h>
59#include <qpa/qplatformmenu.h>
60
61QT_BEGIN_NAMESPACE
62
63#define QAPP_CHECK(functionName) \
64 if (Q_UNLIKELY(!qApp)) { \
65 qWarning("QShortcut: Initialize QApplication before calling '" functionName "'."); \
66 return; \
67 }
68
69
70static bool correctWidgetContext(Qt::ShortcutContext context, QWidget *w, QWidget *active_window);
71#if QT_CONFIG(graphicsview)
72static bool correctGraphicsWidgetContext(Qt::ShortcutContext context, QGraphicsWidget *w, QWidget *active_window);
73#endif
74#ifndef QT_NO_ACTION
75static bool correctActionContext(Qt::ShortcutContext context, QAction *a, QWidget *active_window);
76#endif
77
78
79/*! \internal
80 Returns \c true if the widget \a w is a logical sub window of the current
81 top-level widget.
82*/
83bool qWidgetShortcutContextMatcher(QObject *object, Qt::ShortcutContext context)
84{
85 Q_ASSERT_X(object, "QShortcutMap", "Shortcut has no owner. Illegal map state!");
86
87 QWidget *active_window = QApplication::activeWindow();
88
89 // popups do not become the active window,
90 // so we fake it here to get the correct context
91 // for the shortcut system.
92 if (QApplication::activePopupWidget())
93 active_window = QApplication::activePopupWidget();
94
95 if (!active_window) {
96 QWindow *qwindow = QGuiApplication::focusWindow();
97 if (qwindow && qwindow->isActive()) {
98 while (qwindow) {
99 if (auto widgetWindow = qobject_cast<QWidgetWindow *>(object: qwindow)) {
100 active_window = widgetWindow->widget();
101 break;
102 }
103 qwindow = qwindow->parent();
104 }
105 }
106 }
107
108 if (!active_window)
109 return false;
110
111#ifndef QT_NO_ACTION
112 if (auto a = qobject_cast<QAction *>(object))
113 return correctActionContext(context, a, active_window);
114#endif
115
116#if QT_CONFIG(graphicsview)
117 if (auto gw = qobject_cast<QGraphicsWidget *>(object))
118 return correctGraphicsWidgetContext(context, w: gw, active_window);
119#endif
120
121 auto w = qobject_cast<QWidget *>(o: object);
122 if (!w) {
123 if (auto s = qobject_cast<QShortcut *>(object))
124 w = s->parentWidget();
125 }
126
127 if (!w) {
128 auto qwindow = qobject_cast<QWindow *>(o: object);
129 while (qwindow) {
130 if (auto widget_window = qobject_cast<QWidgetWindow *>(object: qwindow)) {
131 w = widget_window->widget();
132 break;
133 }
134 qwindow = qwindow->parent();
135 }
136 }
137
138 if (!w)
139 return false;
140
141 return correctWidgetContext(context, w, active_window);
142}
143
144static bool correctWidgetContext(Qt::ShortcutContext context, QWidget *w, QWidget *active_window)
145{
146 bool visible = w->isVisible();
147#if QT_CONFIG(menubar)
148 if (auto menuBar = qobject_cast<QMenuBar *>(object: w)) {
149 if (auto *pmb = menuBar->platformMenuBar()) {
150 if (menuBar->parentWidget()) {
151 visible = true;
152 } else {
153 if (auto *ww = qobject_cast<QWidgetWindow *>(object: pmb->parentWindow()))
154 w = ww->widget(); // Good enough since we only care about the window
155 else
156 return false; // This is not a QWidget window. We won't deliver
157 }
158 }
159 }
160#endif
161
162 if (!visible || !w->isEnabled())
163 return false;
164
165 if (context == Qt::ApplicationShortcut)
166 return QApplicationPrivate::tryModalHelper(widget: w, rettop: nullptr); // true, unless w is shadowed by a modal dialog
167
168 if (context == Qt::WidgetShortcut)
169 return w == QApplication::focusWidget();
170
171 if (context == Qt::WidgetWithChildrenShortcut) {
172 const QWidget *tw = QApplication::focusWidget();
173 while (tw && tw != w && (tw->windowType() == Qt::Widget || tw->windowType() == Qt::Popup || tw->windowType() == Qt::SubWindow))
174 tw = tw->parentWidget();
175 return tw == w;
176 }
177
178 // Below is Qt::WindowShortcut context
179 QWidget *tlw = w->window();
180#if QT_CONFIG(graphicsview)
181 if (auto topData = static_cast<QWidgetPrivate *>(QObjectPrivate::get(o: tlw))->extra.get()) {
182 if (topData->proxyWidget) {
183 bool res = correctGraphicsWidgetContext(context, w: topData->proxyWidget, active_window);
184 return res;
185 }
186 }
187#endif
188
189 if (active_window && active_window != tlw) {
190 /* if a floating tool window is active, keep shortcuts on the parent working.
191 * and if a popup window is active (f.ex a completer), keep shortcuts on the
192 * focus proxy working */
193 if (active_window->windowType() == Qt::Tool && active_window->parentWidget()) {
194 active_window = active_window->parentWidget()->window();
195 } else if (active_window->windowType() == Qt::Popup && active_window->focusProxy()) {
196 active_window = active_window->focusProxy()->window();
197 }
198 }
199
200 if (active_window != tlw) {
201#if QT_CONFIG(menubar)
202 // If the tlw is a QMenuBar then we allow it to proceed as this indicates that
203 // the QMenuBar is a parentless one and is therefore used for multiple top level
204 // windows in the application. This is common on macOS platforms for example.
205 if (!qobject_cast<QMenuBar *>(object: tlw))
206#endif
207 return false;
208 }
209
210 /* if we live in a MDI subwindow, ignore the event if we are
211 not the active document window */
212 const QWidget* sw = w;
213 while (sw && !(sw->windowType() == Qt::SubWindow) && !sw->isWindow())
214 sw = sw->parentWidget();
215 if (sw && (sw->windowType() == Qt::SubWindow)) {
216 QWidget *focus_widget = QApplication::focusWidget();
217 while (focus_widget && focus_widget != sw)
218 focus_widget = focus_widget->parentWidget();
219 return sw == focus_widget;
220 }
221
222#if defined(DEBUG_QSHORTCUTMAP)
223 qDebug().nospace() << "..true [Pass-through]";
224#endif
225 return QApplicationPrivate::tryModalHelper(widget: w, rettop: nullptr);
226}
227
228#if QT_CONFIG(graphicsview)
229static bool correctGraphicsWidgetContext(Qt::ShortcutContext context, QGraphicsWidget *w, QWidget *active_window)
230{
231 bool visible = w->isVisible();
232#if defined(Q_OS_DARWIN) && QT_CONFIG(menubar)
233 if (!QCoreApplication::testAttribute(Qt::AA_DontUseNativeMenuBar) && qobject_cast<QMenuBar *>(w))
234 visible = true;
235#endif
236
237 if (!visible || !w->isEnabled() || !w->scene())
238 return false;
239
240 if (context == Qt::ApplicationShortcut) {
241 // Applicationwide shortcuts are always reachable unless their owner
242 // is shadowed by modality. In QGV there's no modality concept, but we
243 // must still check if all views are shadowed.
244 const auto &views = w->scene()->views();
245 for (auto view : views) {
246 if (QApplicationPrivate::tryModalHelper(widget: view, rettop: nullptr))
247 return true;
248 }
249 return false;
250 }
251
252 if (context == Qt::WidgetShortcut)
253 return static_cast<QGraphicsItem *>(w) == w->scene()->focusItem();
254
255 if (context == Qt::WidgetWithChildrenShortcut) {
256 const QGraphicsItem *ti = w->scene()->focusItem();
257 if (ti && ti->isWidget()) {
258 const auto *tw = static_cast<const QGraphicsWidget *>(ti);
259 while (tw && tw != w && (tw->windowType() == Qt::Widget || tw->windowType() == Qt::Popup))
260 tw = tw->parentWidget();
261 return tw == w;
262 }
263 return false;
264 }
265
266 // Below is Qt::WindowShortcut context
267
268 // Find the active view (if any).
269 const auto &views = w->scene()->views();
270 QGraphicsView *activeView = nullptr;
271 for (auto view : views) {
272 if (view->window() == active_window) {
273 activeView = view;
274 break;
275 }
276 }
277 if (!activeView)
278 return false;
279
280 // The shortcut is reachable if owned by a windowless widget, or if the
281 // widget's window is the same as the focus item's window.
282 QGraphicsWidget *a = w->scene()->activeWindow();
283 return !w->window() || a == w->window();
284}
285#endif
286
287#ifndef QT_NO_ACTION
288static bool correctActionContext(Qt::ShortcutContext context, QAction *a, QWidget *active_window)
289{
290 const QWidgetList &widgets = static_cast<QActionPrivate *>(QObjectPrivate::get(o: a))->widgets;
291#if defined(DEBUG_QSHORTCUTMAP)
292 if (widgets.isEmpty())
293 qDebug() << a << "not connected to any widgets; won't trigger";
294#endif
295 for (auto w : widgets) {
296#if QT_CONFIG(menu)
297 if (auto menu = qobject_cast<QMenu *>(object: w)) {
298#ifdef Q_OS_DARWIN
299 // On Mac, menu item shortcuts are processed before reaching any window.
300 // That means that if a menu action shortcut has not been already processed
301 // (and reaches this point), then the menu item itself has been disabled.
302 // This occurs at the QPA level on Mac, where we disable all the Cocoa menus
303 // when showing a modal window. (Notice that only the QPA menu is disabled,
304 // not the QMenu.) Since we can also reach this code by climbing the menu
305 // hierarchy (see below), or when the shortcut is not a key-equivalent, we
306 // need to check whether the QPA menu is actually disabled.
307 // When there is no QPA menu, there will be no QCocoaMenuDelegate checking
308 // for the actual shortcuts. We can then fallback to our own logic.
309 QPlatformMenu *pm = menu->platformMenu();
310 if (pm && !pm->isEnabled())
311 continue;
312#endif
313 QAction *a = menu->menuAction();
314 if (correctActionContext(context, a, active_window))
315 return true;
316 } else
317#endif
318 if (correctWidgetContext(context, w, active_window))
319 return true;
320 }
321
322#if QT_CONFIG(graphicsview)
323 const auto &graphicsWidgets = static_cast<QActionPrivate *>(QObjectPrivate::get(o: a))->graphicsWidgets;
324#if defined(DEBUG_QSHORTCUTMAP)
325 if (graphicsWidgets.isEmpty())
326 qDebug() << a << "not connected to any widgets; won't trigger";
327#endif
328 for (auto graphicsWidget : graphicsWidgets) {
329 if (correctGraphicsWidgetContext(context, w: graphicsWidget, active_window))
330 return true;
331 }
332#endif
333 return false;
334}
335#endif // QT_NO_ACTION
336
337
338/*!
339 \class QShortcut
340 \brief The QShortcut class is used to create keyboard shortcuts.
341
342 \ingroup events
343 \inmodule QtWidgets
344
345 The QShortcut class provides a way of connecting keyboard
346 shortcuts to Qt's \l{signals and slots} mechanism, so that
347 objects can be informed when a shortcut is executed. The shortcut
348 can be set up to contain all the key presses necessary to
349 describe a keyboard shortcut, including the states of modifier
350 keys such as \uicontrol Shift, \uicontrol Ctrl, and \uicontrol Alt.
351
352 \target mnemonic
353
354 On certain widgets, using '&' in front of a character will
355 automatically create a mnemonic (a shortcut) for that character,
356 e.g. "E&xit" will create the shortcut \uicontrol Alt+X (use '&&' to
357 display an actual ampersand). The widget might consume and perform
358 an action on a given shortcut. On X11 the ampersand will not be
359 shown and the character will be underlined. On Windows, shortcuts
360 are normally not displayed until the user presses the \uicontrol Alt
361 key, but this is a setting the user can change. On Mac, shortcuts
362 are disabled by default. Call \l qt_set_sequence_auto_mnemonic() to
363 enable them. However, because mnemonic shortcuts do not fit in
364 with Aqua's guidelines, Qt will not show the shortcut character
365 underlined.
366
367 For applications that use menus, it may be more convenient to
368 use the convenience functions provided in the QMenu class to
369 assign keyboard shortcuts to menu items as they are created.
370 Alternatively, shortcuts may be associated with other types of
371 actions in the QAction class.
372
373 The simplest way to create a shortcut for a particular widget is
374 to construct the shortcut with a key sequence. For example:
375
376 \snippet code/src_gui_kernel_qshortcut.cpp 0
377
378 When the user types the \l{QKeySequence}{key sequence}
379 for a given shortcut, the shortcut's activated() signal is
380 emitted. (In the case of ambiguity, the activatedAmbiguously()
381 signal is emitted.) A shortcut is "listened for" by Qt's event
382 loop when the shortcut's parent widget is receiving events.
383
384 A shortcut's key sequence can be set with setKey() and retrieved
385 with key(). A shortcut can be enabled or disabled with
386 setEnabled(), and can have "What's This?" help text set with
387 setWhatsThis().
388
389 \sa QShortcutEvent, QKeySequence, QAction
390*/
391
392/*!
393 \fn QWidget *QShortcut::parentWidget() const
394
395 Returns the shortcut's parent widget.
396*/
397
398/*!
399 \fn void QShortcut::activated()
400
401 This signal is emitted when the user types the shortcut's key
402 sequence.
403
404 \sa activatedAmbiguously()
405*/
406
407/*!
408 \fn void QShortcut::activatedAmbiguously()
409
410 When a key sequence is being typed at the keyboard, it is said to
411 be ambiguous as long as it matches the start of more than one
412 shortcut.
413
414 When a shortcut's key sequence is completed,
415 activatedAmbiguously() is emitted if the key sequence is still
416 ambiguous (i.e., it is the start of one or more other shortcuts).
417 The activated() signal is not emitted in this case.
418
419 \sa activated()
420*/
421
422/*!
423 \fn template<typename Functor>
424 QShortcut(const QKeySequence &key, QWidget *parent,
425 Functor functor,
426 Qt::ShortcutContext shortcutContext = Qt::WindowShortcut);
427 \since 5.15
428 \overload
429
430 This is a QShortcut convenience constructor which connects the shortcut's
431 \l{QShortcut::activated()}{activated()} signal to the \a functor.
432*/
433/*!
434 \fn template<typename Functor>
435 QShortcut(const QKeySequence &key, QWidget *parent,
436 const QObject *context, Functor functor,
437 Qt::ShortcutContext shortcutContext = Qt::WindowShortcut);
438 \since 5.15
439 \overload
440
441 This is a QShortcut convenience constructor which connects the shortcut's
442 \l{QShortcut::activated()}{activated()} signal to the \a functor.
443
444 The \a functor can be a pointer to a member function of the \a context object.
445
446 If the \a context object is destroyed, the \a functor will not be called.
447*/
448/*!
449 \fn template<typename Functor, typename FunctorAmbiguous>
450 QShortcut(const QKeySequence &key, QWidget *parent,
451 const QObject *context1, Functor functor,
452 FunctorAmbiguous functorAmbiguous,
453 Qt::ShortcutContext shortcutContext = Qt::WindowShortcut);
454 \since 5.15
455 \overload
456
457 This is a QShortcut convenience constructor which connects the shortcut's
458 \l{QShortcut::activated()}{activated()} signal to the \a functor and
459 \l{QShortcut::activatedAmbiguously()}{activatedAmbiguously()}
460 signal to the \a FunctorAmbiguous.
461
462 The \a functor and \a FunctorAmbiguous can be a pointer to a member
463 function of the \a context object.
464
465 If the \a context object is destroyed, the \a functor and
466 \a FunctorAmbiguous will not be called.
467*/
468/*!
469 \fn template<typename Functor, typename FunctorAmbiguous>
470 QShortcut(const QKeySequence &key, QWidget *parent,
471 const QObject *context1, Functor functor,
472 const QObject *context2, FunctorAmbiguous functorAmbiguous,
473 Qt::ShortcutContext shortcutContext = Qt::WindowShortcut);
474 \since 5.15
475 \overload
476
477 This is a QShortcut convenience constructor which connects the shortcut's
478 \l{QShortcut::activated()}{activated()} signal to the \a functor and
479 \l{QShortcut::activatedAmbiguously()}{activatedAmbiguously()}
480 signal to the \a FunctorAmbiguous.
481
482 The \a functor can be a pointer to a member function of the
483 \a context1 object.
484 The \a FunctorAmbiguous can be a pointer to a member function of the
485 \a context2 object.
486
487 If the \a context1 object is destroyed, the \a functor will not be called.
488 If the \a context2 object is destroyed, the \a FunctorAmbiguous
489 will not be called.
490*/
491
492/*
493 \internal
494 Private data accessed through d-pointer.
495*/
496class QShortcutPrivate : public QObjectPrivate
497{
498 Q_DECLARE_PUBLIC(QShortcut)
499public:
500 QShortcutPrivate() = default;
501 QKeySequence sc_sequence;
502 Qt::ShortcutContext sc_context = Qt::WindowShortcut;
503 bool sc_enabled = true;
504 bool sc_autorepeat = true;
505 int sc_id = 0;
506 QString sc_whatsthis;
507 void redoGrab(QShortcutMap &map);
508};
509
510void QShortcutPrivate::redoGrab(QShortcutMap &map)
511{
512 Q_Q(QShortcut);
513 if (Q_UNLIKELY(!parent)) {
514 qWarning(msg: "QShortcut: No widget parent defined");
515 return;
516 }
517
518 if (sc_id)
519 map.removeShortcut(id: sc_id, owner: q);
520 if (sc_sequence.isEmpty())
521 return;
522 sc_id = map.addShortcut(owner: q, key: sc_sequence, context: sc_context, matcher: qWidgetShortcutContextMatcher);
523 if (!sc_enabled)
524 map.setShortcutEnabled(enable: false, id: sc_id, owner: q);
525 if (!sc_autorepeat)
526 map.setShortcutAutoRepeat(on: false, id: sc_id, owner: q);
527}
528
529/*!
530 Constructs a QShortcut object for the \a parent widget. Since no
531 shortcut key sequence is specified, the shortcut will not emit any
532 signals.
533
534 \sa setKey()
535*/
536QShortcut::QShortcut(QWidget *parent)
537 : QObject(*new QShortcutPrivate, parent)
538{
539 Q_ASSERT(parent != nullptr);
540}
541
542/*!
543 Constructs a QShortcut object for the \a parent widget. The shortcut
544 operates on its parent, listening for \l{QShortcutEvent}s that
545 match the \a key sequence. Depending on the ambiguity of the
546 event, the shortcut will call the \a member function, or the \a
547 ambiguousMember function, if the key press was in the shortcut's
548 \a shortcutContext.
549*/
550QShortcut::QShortcut(const QKeySequence &key, QWidget *parent,
551 const char *member, const char *ambiguousMember,
552 Qt::ShortcutContext shortcutContext)
553 : QShortcut(parent)
554{
555 QAPP_CHECK("QShortcut");
556
557 Q_D(QShortcut);
558 d->sc_context = shortcutContext;
559 d->sc_sequence = key;
560 d->redoGrab(map&: QGuiApplicationPrivate::instance()->shortcutMap);
561 if (member)
562 connect(sender: this, SIGNAL(activated()), receiver: parent, member);
563 if (ambiguousMember)
564 connect(sender: this, SIGNAL(activatedAmbiguously()), receiver: parent, member: ambiguousMember);
565}
566
567/*!
568 Destroys the shortcut.
569*/
570QShortcut::~QShortcut()
571{
572 Q_D(QShortcut);
573 if (qApp)
574 QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(id: d->sc_id, owner: this);
575}
576
577/*!
578 \property QShortcut::key
579 \brief the shortcut's key sequence
580
581 This is a key sequence with an optional combination of Shift, Ctrl,
582 and Alt. The key sequence may be supplied in a number of ways:
583
584 \snippet code/src_gui_kernel_qshortcut.cpp 1
585
586 By default, this property contains an empty key sequence.
587*/
588void QShortcut::setKey(const QKeySequence &key)
589{
590 Q_D(QShortcut);
591 if (d->sc_sequence == key)
592 return;
593 QAPP_CHECK("setKey");
594 d->sc_sequence = key;
595 d->redoGrab(map&: QGuiApplicationPrivate::instance()->shortcutMap);
596}
597
598QKeySequence QShortcut::key() const
599{
600 Q_D(const QShortcut);
601 return d->sc_sequence;
602}
603
604/*!
605 \property QShortcut::enabled
606 \brief whether the shortcut is enabled
607
608 An enabled shortcut emits the activated() or activatedAmbiguously()
609 signal when a QShortcutEvent occurs that matches the shortcut's
610 key() sequence.
611
612 If the application is in \c WhatsThis mode the shortcut will not emit
613 the signals, but will show the "What's This?" text instead.
614
615 By default, this property is \c true.
616
617 \sa whatsThis
618*/
619void QShortcut::setEnabled(bool enable)
620{
621 Q_D(QShortcut);
622 if (d->sc_enabled == enable)
623 return;
624 QAPP_CHECK("setEnabled");
625 d->sc_enabled = enable;
626 QGuiApplicationPrivate::instance()->shortcutMap.setShortcutEnabled(enable, id: d->sc_id, owner: this);
627}
628
629bool QShortcut::isEnabled() const
630{
631 Q_D(const QShortcut);
632 return d->sc_enabled;
633}
634
635/*!
636 \property QShortcut::context
637 \brief the context in which the shortcut is valid
638
639 A shortcut's context decides in which circumstances a shortcut is
640 allowed to be triggered. The normal context is Qt::WindowShortcut,
641 which allows the shortcut to trigger if the parent (the widget
642 containing the shortcut) is a subwidget of the active top-level
643 window.
644
645 By default, this property is set to Qt::WindowShortcut.
646*/
647void QShortcut::setContext(Qt::ShortcutContext context)
648{
649 Q_D(QShortcut);
650 if(d->sc_context == context)
651 return;
652 QAPP_CHECK("setContext");
653 d->sc_context = context;
654 d->redoGrab(map&: QGuiApplicationPrivate::instance()->shortcutMap);
655}
656
657Qt::ShortcutContext QShortcut::context() const
658{
659 Q_D(const QShortcut);
660 return d->sc_context;
661}
662
663/*!
664 \property QShortcut::whatsThis
665 \brief the shortcut's "What's This?" help text
666
667 The text will be shown when the application is in "What's
668 This?" mode and the user types the shortcut key() sequence.
669
670 To set "What's This?" help on a menu item (with or without a
671 shortcut key), set the help on the item's action.
672
673 By default, this property contains an empty string.
674
675 \sa QWhatsThis::inWhatsThisMode(), QAction::setWhatsThis()
676*/
677void QShortcut::setWhatsThis(const QString &text)
678{
679 Q_D(QShortcut);
680 d->sc_whatsthis = text;
681}
682
683QString QShortcut::whatsThis() const
684{
685 Q_D(const QShortcut);
686 return d->sc_whatsthis;
687}
688
689/*!
690 \property QShortcut::autoRepeat
691 \brief whether the shortcut can auto repeat
692 \since 4.2
693
694 If true, the shortcut will auto repeat when the keyboard shortcut
695 combination is held down, provided that keyboard auto repeat is
696 enabled on the system.
697 The default value is true.
698*/
699void QShortcut::setAutoRepeat(bool on)
700{
701 Q_D(QShortcut);
702 if (d->sc_autorepeat == on)
703 return;
704 QAPP_CHECK("setAutoRepeat");
705 d->sc_autorepeat = on;
706 QGuiApplicationPrivate::instance()->shortcutMap.setShortcutAutoRepeat(on, id: d->sc_id, owner: this);
707}
708
709bool QShortcut::autoRepeat() const
710{
711 Q_D(const QShortcut);
712 return d->sc_autorepeat;
713}
714
715/*!
716 Returns the shortcut's ID.
717
718 \sa QShortcutEvent::shortcutId()
719*/
720int QShortcut::id() const
721{
722 Q_D(const QShortcut);
723 return d->sc_id;
724}
725
726/*!
727 \internal
728*/
729bool QShortcut::event(QEvent *e)
730{
731 Q_D(QShortcut);
732 if (d->sc_enabled && e->type() == QEvent::Shortcut) {
733 auto se = static_cast<QShortcutEvent *>(e);
734 if (se->shortcutId() == d->sc_id && se->key() == d->sc_sequence){
735#if QT_CONFIG(whatsthis)
736 if (QWhatsThis::inWhatsThisMode()) {
737 QWhatsThis::showText(pos: QCursor::pos(), text: d->sc_whatsthis);
738 } else
739#endif
740 if (se->isAmbiguous())
741 emit activatedAmbiguously();
742 else
743 emit activated();
744 return true;
745 }
746 }
747 return QObject::event(event: e);
748}
749#endif // QT_NO_SHORTCUT
750
751QT_END_NAMESPACE
752
753#include "moc_qshortcut.cpp"
754

source code of qtbase/src/widgets/kernel/qshortcut.cpp