src/gui/kernel/qshortcut.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qshortcut.h"
       
    43 #include "private/qwidget_p.h"
       
    44 
       
    45 #ifndef QT_NO_SHORTCUT
       
    46 #include <qevent.h>
       
    47 #include <qwhatsthis.h>
       
    48 #include <qmenu.h>
       
    49 #include <qapplication.h>
       
    50 #include <private/qapplication_p.h>
       
    51 #include <private/qshortcutmap_p.h>
       
    52 
       
    53 QT_BEGIN_NAMESPACE
       
    54 
       
    55 #define QAPP_CHECK(functionName) \
       
    56     if (!qApp) { \
       
    57         qWarning("QShortcut: Initialize QApplication before calling '" functionName "'."); \
       
    58         return; \
       
    59     }
       
    60 
       
    61 /*!
       
    62     \class QShortcut
       
    63     \brief The QShortcut class is used to create keyboard shortcuts.
       
    64 
       
    65     \ingroup events
       
    66 
       
    67 
       
    68     The QShortcut class provides a way of connecting keyboard
       
    69     shortcuts to Qt's \l{signals and slots} mechanism, so that
       
    70     objects can be informed when a shortcut is executed. The shortcut
       
    71     can be set up to contain all the key presses necessary to
       
    72     describe a keyboard shortcut, including the states of modifier
       
    73     keys such as \gui Shift, \gui Ctrl, and \gui Alt.
       
    74 
       
    75     \target mnemonic
       
    76 
       
    77     On certain widgets, using '&' in front of a character will
       
    78     automatically create a mnemonic (a shortcut) for that character,
       
    79     e.g. "E&xit" will create the shortcut \gui Alt+X (use '&&' to
       
    80     display an actual ampersand). The widget might consume and perform
       
    81     an action on a given shortcut. On X11 the ampersand will not be
       
    82     shown and the character will be underlined. On Windows, shortcuts
       
    83     are normally not displayed until the user presses the \gui Alt
       
    84     key, but this is a setting the user can change. On Mac, shortcuts
       
    85     are disabled by default. Call qt_set_sequence_auto_mnemonic() to
       
    86     enable them. However, because mnemonic shortcuts do not fit in
       
    87     with Aqua's guidelines, Qt will not show the shortcut character
       
    88     underlined.
       
    89 
       
    90     For applications that use menus, it may be more convenient to
       
    91     use the convenience functions provided in the QMenu class to
       
    92     assign keyboard shortcuts to menu items as they are created.
       
    93     Alternatively, shortcuts may be associated with other types of
       
    94     actions in the QAction class.
       
    95 
       
    96     The simplest way to create a shortcut for a particular widget is
       
    97     to construct the shortcut with a key sequence. For example:
       
    98 
       
    99     \snippet doc/src/snippets/code/src_gui_kernel_qshortcut.cpp 0
       
   100 
       
   101     When the user types the \l{QKeySequence}{key sequence}
       
   102     for a given shortcut, the shortcut's activated() signal is
       
   103     emitted. (In the case of ambiguity, the activatedAmbiguously()
       
   104     signal is emitted.) A shortcut is "listened for" by Qt's event
       
   105     loop when the shortcut's parent widget is receiving events.
       
   106 
       
   107     A shortcut's key sequence can be set with setKey() and retrieved
       
   108     with key(). A shortcut can be enabled or disabled with
       
   109     setEnabled(), and can have "What's This?" help text set with
       
   110     setWhatsThis().
       
   111 
       
   112     \sa QShortcutEvent, QKeySequence, QAction
       
   113 */
       
   114 
       
   115 /*!
       
   116     \fn QWidget *QShortcut::parentWidget() const
       
   117 
       
   118     Returns the shortcut's parent widget.
       
   119 */
       
   120 
       
   121 /*!
       
   122     \fn void QShortcut::activated()
       
   123 
       
   124     This signal is emitted when the user types the shortcut's key
       
   125     sequence.
       
   126 
       
   127     \sa activatedAmbiguously()
       
   128 */
       
   129 
       
   130 /*!
       
   131     \fn void QShortcut::activatedAmbiguously()
       
   132 
       
   133     When a key sequence is being typed at the keyboard, it is said to
       
   134     be ambiguous as long as it matches the start of more than one
       
   135     shortcut.
       
   136 
       
   137     When a shortcut's key sequence is completed,
       
   138     activatedAmbiguously() is emitted if the key sequence is still
       
   139     ambiguous (i.e., it is the start of one or more other shortcuts).
       
   140     The activated() signal is not emitted in this case.
       
   141 
       
   142     \sa activated()
       
   143 */
       
   144 
       
   145 /*
       
   146     \internal
       
   147     Private data accessed through d-pointer.
       
   148 */
       
   149 class QShortcutPrivate : public QObjectPrivate
       
   150 {
       
   151     Q_DECLARE_PUBLIC(QShortcut)
       
   152 public:
       
   153     QShortcutPrivate() : sc_context(Qt::WindowShortcut), sc_enabled(true), sc_autorepeat(true), sc_id(0) {}
       
   154     QKeySequence sc_sequence;
       
   155     Qt::ShortcutContext sc_context;
       
   156     bool sc_enabled;
       
   157     bool sc_autorepeat;
       
   158     int sc_id;
       
   159     QString sc_whatsthis;
       
   160     void redoGrab(QShortcutMap &map);
       
   161 };
       
   162 
       
   163 void QShortcutPrivate::redoGrab(QShortcutMap &map)
       
   164 {
       
   165     Q_Q(QShortcut);
       
   166     if (!parent) {
       
   167         qWarning("QShortcut: No widget parent defined");
       
   168         return;
       
   169     }
       
   170 
       
   171     if (sc_id)
       
   172         map.removeShortcut(sc_id, q);
       
   173     if (sc_sequence.isEmpty())
       
   174         return;
       
   175     sc_id = map.addShortcut(q, sc_sequence, sc_context);
       
   176     if (!sc_enabled)
       
   177         map.setShortcutEnabled(false, sc_id, q);
       
   178     if (!sc_autorepeat)
       
   179         map.setShortcutAutoRepeat(false, sc_id, q);
       
   180 }
       
   181 
       
   182 /*!
       
   183     Constructs a QShortcut object for the \a parent widget. Since no
       
   184     shortcut key sequence is specified, the shortcut will not emit any
       
   185     signals.
       
   186 
       
   187     \sa setKey()
       
   188 */
       
   189 QShortcut::QShortcut(QWidget *parent)
       
   190     : QObject(*new QShortcutPrivate, parent)
       
   191 {
       
   192     Q_ASSERT(parent != 0);
       
   193 }
       
   194 
       
   195 /*!
       
   196     Constructs a QShortcut object for the \a parent widget. The shortcut
       
   197     operates on its parent, listening for \l{QShortcutEvent}s that
       
   198     match the \a key sequence. Depending on the ambiguity of the
       
   199     event, the shortcut will call the \a member function, or the \a
       
   200     ambiguousMember function, if the key press was in the shortcut's
       
   201     \a context.
       
   202 */
       
   203 QShortcut::QShortcut(const QKeySequence &key, QWidget *parent,
       
   204                      const char *member, const char *ambiguousMember,
       
   205                      Qt::ShortcutContext context)
       
   206     : QObject(*new QShortcutPrivate, parent)
       
   207 {
       
   208     QAPP_CHECK("QShortcut");
       
   209 
       
   210     Q_D(QShortcut);
       
   211     Q_ASSERT(parent != 0);
       
   212     d->sc_context = context;
       
   213     d->sc_sequence = key;
       
   214     d->redoGrab(qApp->d_func()->shortcutMap);
       
   215     if (member)
       
   216         connect(this, SIGNAL(activated()), parent, member);
       
   217     if (ambiguousMember)
       
   218         connect(this, SIGNAL(activatedAmbiguously()), parent, ambiguousMember);
       
   219 }
       
   220 
       
   221 /*!
       
   222     Destroys the shortcut.
       
   223 */
       
   224 QShortcut::~QShortcut()
       
   225 {
       
   226     Q_D(QShortcut);
       
   227     if (qApp)
       
   228         qApp->d_func()->shortcutMap.removeShortcut(d->sc_id, this);
       
   229 }
       
   230 
       
   231 /*!
       
   232     \property QShortcut::key
       
   233     \brief the shortcut's key sequence
       
   234 
       
   235     This is a key sequence with an optional combination of Shift, Ctrl,
       
   236     and Alt. The key sequence may be supplied in a number of ways:
       
   237 
       
   238     \snippet doc/src/snippets/code/src_gui_kernel_qshortcut.cpp 1
       
   239 
       
   240     By default, this property contains an empty key sequence.
       
   241 */
       
   242 void QShortcut::setKey(const QKeySequence &key)
       
   243 {
       
   244     Q_D(QShortcut);
       
   245     if (d->sc_sequence == key)
       
   246         return;
       
   247     QAPP_CHECK("setKey");
       
   248     d->sc_sequence = key;
       
   249     d->redoGrab(qApp->d_func()->shortcutMap);
       
   250 }
       
   251 
       
   252 QKeySequence QShortcut::key() const
       
   253 {
       
   254     Q_D(const QShortcut);
       
   255     return d->sc_sequence;
       
   256 }
       
   257 
       
   258 /*!
       
   259     \property QShortcut::enabled
       
   260     \brief whether the shortcut is enabled
       
   261 
       
   262     An enabled shortcut emits the activated() or activatedAmbiguously()
       
   263     signal when a QShortcutEvent occurs that matches the shortcut's
       
   264     key() sequence.
       
   265 
       
   266     If the application is in \c WhatsThis mode the shortcut will not emit
       
   267     the signals, but will show the "What's This?" text instead.
       
   268 
       
   269     By default, this property is true.
       
   270 
       
   271     \sa whatsThis
       
   272 */
       
   273 void QShortcut::setEnabled(bool enable)
       
   274 {
       
   275     Q_D(QShortcut);
       
   276     if (d->sc_enabled == enable)
       
   277         return;
       
   278     QAPP_CHECK("setEnabled");
       
   279     d->sc_enabled = enable;
       
   280     qApp->d_func()->shortcutMap.setShortcutEnabled(enable, d->sc_id, this);
       
   281 }
       
   282 
       
   283 bool QShortcut::isEnabled() const
       
   284 {
       
   285     Q_D(const QShortcut);
       
   286     return d->sc_enabled;
       
   287 }
       
   288 
       
   289 /*!
       
   290     \property QShortcut::context
       
   291     \brief the context in which the shortcut is valid
       
   292 
       
   293     A shortcut's context decides in which circumstances a shortcut is
       
   294     allowed to be triggered. The normal context is Qt::WindowShortcut,
       
   295     which allows the shortcut to trigger if the parent (the widget
       
   296     containing the shortcut) is a subwidget of the active top-level
       
   297     window.
       
   298 
       
   299     By default, this property is set to Qt::WindowShortcut.
       
   300 */
       
   301 void QShortcut::setContext(Qt::ShortcutContext context)
       
   302 {
       
   303     Q_D(QShortcut);
       
   304     if(d->sc_context == context)
       
   305         return;
       
   306     QAPP_CHECK("setContext");
       
   307     d->sc_context = context;
       
   308     d->redoGrab(qApp->d_func()->shortcutMap);
       
   309 }
       
   310 
       
   311 Qt::ShortcutContext QShortcut::context()
       
   312 {
       
   313     Q_D(QShortcut);
       
   314     return d->sc_context;
       
   315 }
       
   316 
       
   317 /*!
       
   318     \property QShortcut::whatsThis
       
   319     \brief the shortcut's "What's This?" help text
       
   320 
       
   321     The text will be shown when the application is in "What's
       
   322     This?" mode and the user types the shortcut key() sequence.
       
   323 
       
   324     To set "What's This?" help on a menu item (with or without a
       
   325     shortcut key), set the help on the item's action.
       
   326 
       
   327     By default, this property contains an empty string.
       
   328 
       
   329     \sa QWhatsThis::inWhatsThisMode(), QAction::setWhatsThis()
       
   330 */
       
   331 void QShortcut::setWhatsThis(const QString &text)
       
   332 {
       
   333     Q_D(QShortcut);
       
   334     d->sc_whatsthis = text;
       
   335 }
       
   336 
       
   337 QString QShortcut::whatsThis() const
       
   338 {
       
   339     Q_D(const QShortcut);
       
   340     return d->sc_whatsthis;
       
   341 }
       
   342 
       
   343 /*!
       
   344     \property QShortcut::autoRepeat
       
   345     \brief whether the shortcut can auto repeat
       
   346     \since 4.2
       
   347 
       
   348     If true, the shortcut will auto repeat when the keyboard shortcut
       
   349     combination is held down, provided that keyboard auto repeat is
       
   350     enabled on the system.
       
   351     The default value is true.
       
   352 */
       
   353 void QShortcut::setAutoRepeat(bool on)
       
   354 {
       
   355     Q_D(QShortcut);
       
   356     if (d->sc_autorepeat == on)
       
   357         return;
       
   358     QAPP_CHECK("setAutoRepeat");
       
   359     d->sc_autorepeat = on;
       
   360     qApp->d_func()->shortcutMap.setShortcutAutoRepeat(on, d->sc_id, this);
       
   361 }
       
   362 
       
   363 bool QShortcut::autoRepeat() const
       
   364 {
       
   365     Q_D(const QShortcut);
       
   366     return d->sc_autorepeat;
       
   367 }
       
   368 
       
   369 /*!
       
   370     Returns the shortcut's ID.
       
   371 
       
   372     \sa QShortcutEvent::shortcutId()
       
   373 */
       
   374 int QShortcut::id() const
       
   375 {
       
   376     Q_D(const QShortcut);
       
   377     return d->sc_id;
       
   378 }
       
   379 
       
   380 /*!
       
   381     \internal
       
   382 */
       
   383 bool QShortcut::event(QEvent *e)
       
   384 {
       
   385     Q_D(QShortcut);
       
   386     bool handled = false;
       
   387     if (d->sc_enabled && e->type() == QEvent::Shortcut) {
       
   388         QShortcutEvent *se = static_cast<QShortcutEvent *>(e);
       
   389         if (se->shortcutId() == d->sc_id && se->key() == d->sc_sequence){
       
   390 #ifndef QT_NO_WHATSTHIS
       
   391             if (QWhatsThis::inWhatsThisMode()) {
       
   392                 QWhatsThis::showText(QCursor::pos(), d->sc_whatsthis);
       
   393                 handled = true;
       
   394             } else
       
   395 #endif
       
   396             if (se->isAmbiguous())
       
   397                 emit activatedAmbiguously();
       
   398             else
       
   399                 emit activated();
       
   400             handled = true;
       
   401         }
       
   402     }
       
   403     return handled;
       
   404 }
       
   405 #endif // QT_NO_SHORTCUT
       
   406 
       
   407 QT_END_NAMESPACE