[2] | 1 | /****************************************************************************
|
---|
| 2 | ** $Id: qaccel.cpp 107 2006-07-29 14:22:12Z dmik $
|
---|
| 3 | **
|
---|
| 4 | ** Implementation of QAccel class
|
---|
| 5 | **
|
---|
| 6 | ** Created : 950419
|
---|
| 7 | **
|
---|
| 8 | ** Copyright (C) 1992-2002 Trolltech AS. All rights reserved.
|
---|
| 9 | **
|
---|
| 10 | ** This file is part of the kernel module of the Qt GUI Toolkit.
|
---|
| 11 | **
|
---|
| 12 | ** This file may be distributed under the terms of the Q Public License
|
---|
| 13 | ** as defined by Trolltech AS of Norway and appearing in the file
|
---|
| 14 | ** LICENSE.QPL included in the packaging of this file.
|
---|
| 15 | **
|
---|
| 16 | ** This file may be distributed and/or modified under the terms of the
|
---|
| 17 | ** GNU General Public License version 2 as published by the Free Software
|
---|
| 18 | ** Foundation and appearing in the file LICENSE.GPL included in the
|
---|
| 19 | ** packaging of this file.
|
---|
| 20 | **
|
---|
| 21 | ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
|
---|
| 22 | ** licenses may use this file in accordance with the Qt Commercial License
|
---|
| 23 | ** Agreement provided with the Software.
|
---|
| 24 | **
|
---|
| 25 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
---|
| 26 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
---|
| 27 | **
|
---|
| 28 | ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
|
---|
| 29 | ** information about Qt Commercial License Agreements.
|
---|
| 30 | ** See http://www.trolltech.com/qpl/ for QPL licensing information.
|
---|
| 31 | ** See http://www.trolltech.com/gpl/ for GPL licensing information.
|
---|
| 32 | **
|
---|
| 33 | ** Contact info@trolltech.com if any conditions of this licensing are
|
---|
| 34 | ** not clear to you.
|
---|
| 35 | **
|
---|
| 36 | **********************************************************************/
|
---|
| 37 |
|
---|
| 38 | #include "qaccel.h"
|
---|
| 39 |
|
---|
| 40 | #ifndef QT_NO_ACCEL
|
---|
| 41 |
|
---|
| 42 | #include "qsignal.h"
|
---|
| 43 | #include "qapplication.h"
|
---|
| 44 | #include "qwidget.h"
|
---|
| 45 | #include "qptrlist.h"
|
---|
| 46 | #include "qwhatsthis.h"
|
---|
| 47 | #include "qguardedptr.h"
|
---|
| 48 | #include "qstatusbar.h"
|
---|
| 49 | #include "qdockwindow.h"
|
---|
| 50 | #include "qsignalslotimp.h"
|
---|
| 51 | /*!
|
---|
| 52 | \class QAccel qaccel.h
|
---|
| 53 | \brief The QAccel class handles keyboard accelerator and shortcut keys.
|
---|
| 54 |
|
---|
| 55 | \ingroup misc
|
---|
| 56 |
|
---|
| 57 | A keyboard accelerator triggers an action when a certain key
|
---|
| 58 | combination is pressed. The accelerator handles all keyboard
|
---|
| 59 | activity for all the children of one top-level widget, so it is
|
---|
| 60 | not affected by the keyboard focus.
|
---|
| 61 |
|
---|
| 62 | In most cases, you will not need to use this class directly. Use
|
---|
| 63 | the QAction class to create actions with accelerators that can be
|
---|
| 64 | used in both menus and toolbars. If you're only interested in
|
---|
| 65 | menus use QMenuData::insertItem() or QMenuData::setAccel() to make
|
---|
| 66 | accelerators for operations that are also available on menus. Many
|
---|
| 67 | widgets automatically generate accelerators, such as QButton,
|
---|
| 68 | QGroupBox, QLabel (with QLabel::setBuddy()), QMenuBar and QTabBar.
|
---|
| 69 | Example:
|
---|
| 70 | \code
|
---|
| 71 | QPushButton p( "&Exit", parent ); // automatic shortcut ALT+Key_E
|
---|
| 72 | QPopupMenu *fileMenu = new fileMenu( parent );
|
---|
| 73 | fileMenu->insertItem( "Undo", parent, SLOT(undo()), CTRL+Key_Z );
|
---|
| 74 | \endcode
|
---|
| 75 |
|
---|
| 76 | A QAccel contains a list of accelerator items that can be
|
---|
| 77 | manipulated using insertItem(), removeItem(), clear(), key() and
|
---|
| 78 | findKey().
|
---|
| 79 |
|
---|
| 80 | Each accelerator item consists of an identifier and a \l
|
---|
| 81 | QKeySequence. A single key sequence consists of a keyboard code
|
---|
| 82 | combined with modifiers (\c SHIFT, \c CTRL, \c ALT or \c
|
---|
| 83 | UNICODE_ACCEL). For example, \c{CTRL + Key_P} could be a shortcut
|
---|
| 84 | for printing a document. The key codes are listed in \c
|
---|
| 85 | qnamespace.h. As an alternative, use \c UNICODE_ACCEL with the
|
---|
| 86 | unicode code point of the character. For example, \c{UNICODE_ACCEL
|
---|
| 87 | + 'A'} gives the same accelerator as \c Key_A.
|
---|
| 88 |
|
---|
| 89 | When an accelerator key is pressed, the accelerator sends out the
|
---|
| 90 | signal activated() with a number that identifies this particular
|
---|
| 91 | accelerator item. Accelerator items can also be individually
|
---|
| 92 | connected, so that two different keys will activate two different
|
---|
| 93 | slots (see connectItem() and disconnectItem()).
|
---|
| 94 |
|
---|
| 95 | The activated() signal is \e not emitted when two or more
|
---|
| 96 | accelerators match the same key. Instead, the first matching
|
---|
| 97 | accelerator sends out the activatedAmbiguously() signal. By
|
---|
| 98 | pressing the key multiple times, users can navigate between all
|
---|
| 99 | matching accelerators. Some standard controls like QPushButton and
|
---|
| 100 | QCheckBox connect the activatedAmbiguously() signal to the
|
---|
| 101 | harmless setFocus() slot, whereas activated() is connected to a
|
---|
| 102 | slot invoking the button's action. Most controls, like QLabel and
|
---|
| 103 | QTabBar, treat activated() and activatedAmbiguously() as
|
---|
| 104 | equivalent.
|
---|
| 105 |
|
---|
| 106 | Use setEnabled() to enable or disable all the items in an
|
---|
| 107 | accelerator, or setItemEnabled() to enable or disable individual
|
---|
| 108 | items. An item is active only when both the QAccel and the item
|
---|
| 109 | itself are enabled.
|
---|
| 110 |
|
---|
| 111 | The function setWhatsThis() specifies a help text that appears
|
---|
| 112 | when the user presses an accelerator key in What's This mode.
|
---|
| 113 |
|
---|
| 114 | The accelerator will be deleted when \e parent is deleted,
|
---|
| 115 | and will consume relevant key events until then.
|
---|
| 116 |
|
---|
| 117 | Please note that the accelerator
|
---|
| 118 | \code
|
---|
| 119 | accelerator->insertItem( QKeySequence("M") );
|
---|
| 120 | \endcode
|
---|
| 121 | can be triggered with both the 'M' key, and with Shift+M,
|
---|
| 122 | unless a second accelerator is defined for the Shift+M
|
---|
| 123 | combination.
|
---|
| 124 |
|
---|
| 125 |
|
---|
| 126 | Example:
|
---|
| 127 | \code
|
---|
| 128 | QAccel *a = new QAccel( myWindow ); // create accels for myWindow
|
---|
| 129 | a->connectItem( a->insertItem(Key_P+CTRL), // adds Ctrl+P accelerator
|
---|
| 130 | myWindow, // connected to myWindow's
|
---|
| 131 | SLOT(printDoc()) ); // printDoc() slot
|
---|
| 132 | \endcode
|
---|
| 133 |
|
---|
| 134 | \sa QKeyEvent QWidget::keyPressEvent() QMenuData::setAccel()
|
---|
| 135 | QButton::setAccel() QLabel::setBuddy() QKeySequence
|
---|
| 136 | \link guibooks.html#fowler GUI Design Handbook: Keyboard Shortcuts \endlink.
|
---|
| 137 | */
|
---|
| 138 |
|
---|
| 139 |
|
---|
| 140 | struct QAccelItem { // internal accelerator item
|
---|
| 141 | QAccelItem( const QKeySequence &k, int i )
|
---|
| 142 | { key=k; id=i; enabled=TRUE; signal=0; }
|
---|
| 143 | ~QAccelItem() { delete signal; }
|
---|
| 144 | int id;
|
---|
| 145 | QKeySequence key;
|
---|
| 146 | bool enabled;
|
---|
| 147 | QSignal *signal;
|
---|
| 148 | QString whatsthis;
|
---|
| 149 | };
|
---|
| 150 |
|
---|
| 151 |
|
---|
| 152 | typedef QPtrList<QAccelItem> QAccelList; // internal accelerator list
|
---|
| 153 |
|
---|
| 154 | class QAccelPrivate : public Qt {
|
---|
| 155 | public:
|
---|
| 156 | QAccelPrivate( QAccel* p );
|
---|
| 157 | ~QAccelPrivate();
|
---|
| 158 | QAccelList aitems;
|
---|
| 159 | bool enabled;
|
---|
| 160 | QGuardedPtr<QWidget> watch;
|
---|
| 161 | bool ignorewhatsthis;
|
---|
| 162 | QAccel* parent;
|
---|
| 163 |
|
---|
| 164 | void activate( QAccelItem* item );
|
---|
| 165 | void activateAmbiguously( QAccelItem* item );
|
---|
| 166 | };
|
---|
| 167 |
|
---|
| 168 | class QAccelManager : public Qt {
|
---|
| 169 | public:
|
---|
| 170 | static QAccelManager* self() { return self_ptr ? self_ptr : new QAccelManager; }
|
---|
| 171 | void registerAccel( QAccelPrivate* a ) { accels.append( a ); }
|
---|
| 172 | void unregisterAccel( QAccelPrivate* a ) { accels.removeRef( a ); if ( accels.isEmpty() ) delete this; }
|
---|
| 173 | bool tryAccelEvent( QWidget* w, QKeyEvent* e );
|
---|
| 174 | bool dispatchAccelEvent( QWidget* w, QKeyEvent* e );
|
---|
| 175 | bool tryComposeUnicode( QWidget* w, QKeyEvent* e );
|
---|
| 176 |
|
---|
| 177 | private:
|
---|
| 178 | QAccelManager():currentState(Qt::NoMatch), clash(-1) { self_ptr = this; }
|
---|
| 179 | ~QAccelManager() { self_ptr = 0; }
|
---|
| 180 |
|
---|
| 181 | bool correctSubWindow( QWidget *w, QAccelPrivate* d );
|
---|
| 182 | SequenceMatch match( QKeyEvent* e, QAccelItem* item, QKeySequence& temp );
|
---|
| 183 | int translateModifiers( ButtonState state );
|
---|
| 184 |
|
---|
| 185 | QPtrList<QAccelPrivate> accels;
|
---|
| 186 | static QAccelManager* self_ptr;
|
---|
| 187 | Qt::SequenceMatch currentState;
|
---|
| 188 | QKeySequence intermediate;
|
---|
| 189 | int clash;
|
---|
| 190 | };
|
---|
| 191 | QAccelManager* QAccelManager::self_ptr = 0;
|
---|
| 192 |
|
---|
| 193 | bool Q_EXPORT qt_tryAccelEvent( QWidget* w, QKeyEvent* e){
|
---|
| 194 | return QAccelManager::self()->tryAccelEvent( w, e );
|
---|
| 195 | }
|
---|
| 196 |
|
---|
| 197 | bool Q_EXPORT qt_dispatchAccelEvent( QWidget* w, QKeyEvent* e){
|
---|
| 198 | return QAccelManager::self()->dispatchAccelEvent( w, e );
|
---|
| 199 | }
|
---|
| 200 |
|
---|
| 201 | bool Q_EXPORT qt_tryComposeUnicode( QWidget* w, QKeyEvent* e){
|
---|
| 202 | return QAccelManager::self()->tryComposeUnicode( w, e );
|
---|
| 203 | }
|
---|
| 204 |
|
---|
| 205 | #ifdef Q_WS_MAC
|
---|
| 206 | static bool qt_accel_no_shortcuts = TRUE;
|
---|
| 207 | #else
|
---|
| 208 | static bool qt_accel_no_shortcuts = FALSE;
|
---|
| 209 | #endif
|
---|
| 210 | void Q_EXPORT qt_setAccelAutoShortcuts(bool b) { qt_accel_no_shortcuts = b; }
|
---|
| 211 |
|
---|
| 212 | /*
|
---|
| 213 | \internal
|
---|
| 214 | Returns TRUE if the accel is in the current subwindow, else FALSE.
|
---|
| 215 | */
|
---|
| 216 | bool QAccelManager::correctSubWindow( QWidget* w, QAccelPrivate* d ) {
|
---|
| 217 | #if !defined ( Q_OS_MACX )
|
---|
| 218 | if ( !d->watch || !d->watch->isVisible() || !d->watch->isEnabled() )
|
---|
| 219 | #else
|
---|
| 220 | if ( !d->watch || (!d->watch->isVisible() && !d->watch->inherits( "QMenuBar" )) || !d->watch->isEnabled() )
|
---|
| 221 | #endif
|
---|
| 222 | return FALSE;
|
---|
| 223 | QWidget* tlw = w->topLevelWidget();
|
---|
| 224 | QWidget* wtlw = d->watch->topLevelWidget();
|
---|
| 225 |
|
---|
| 226 | /* if we live in a floating dock window, keep our parent's
|
---|
| 227 | * accelerators working */
|
---|
| 228 | #ifndef QT_NO_MAINWINDOW
|
---|
| 229 | if ( tlw->isDialog() && tlw->parentWidget() && ::qt_cast<QDockWindow*>(tlw) )
|
---|
| 230 | return tlw->parentWidget()->topLevelWidget() == wtlw;
|
---|
| 231 |
|
---|
| 232 | if ( wtlw != tlw )
|
---|
| 233 | return FALSE;
|
---|
| 234 | #endif
|
---|
| 235 | /* if we live in a MDI subwindow, ignore the event if we are
|
---|
| 236 | not the active document window */
|
---|
| 237 | QWidget* sw = d->watch;
|
---|
| 238 | while ( sw && !sw->testWFlags( WSubWindow ) )
|
---|
| 239 | sw = sw->parentWidget( TRUE );
|
---|
| 240 | if ( sw ) { // we are in a subwindow indeed
|
---|
| 241 | QWidget* fw = w;
|
---|
| 242 | while ( fw && fw != sw )
|
---|
| 243 | fw = fw->parentWidget( TRUE );
|
---|
| 244 | if ( fw != sw ) // focus widget not in our subwindow
|
---|
| 245 | return FALSE;
|
---|
| 246 | }
|
---|
| 247 | return TRUE;
|
---|
| 248 | }
|
---|
| 249 |
|
---|
| 250 | inline int QAccelManager::translateModifiers( ButtonState state )
|
---|
| 251 | {
|
---|
| 252 | int result = 0;
|
---|
| 253 | if ( state & ShiftButton )
|
---|
| 254 | result |= SHIFT;
|
---|
| 255 | if ( state & ControlButton )
|
---|
| 256 | result |= CTRL;
|
---|
| 257 | if ( state & MetaButton )
|
---|
| 258 | result |= META;
|
---|
| 259 | if ( state & AltButton )
|
---|
| 260 | result |= ALT;
|
---|
| 261 | return result;
|
---|
| 262 | }
|
---|
| 263 |
|
---|
| 264 | /*
|
---|
| 265 | \internal
|
---|
| 266 | Matches the current intermediate key sequence + the latest
|
---|
| 267 | keyevent, with and AccelItem. Returns Identical,
|
---|
| 268 | PartialMatch or NoMatch, and fills \a temp with the
|
---|
| 269 | resulting key sequence.
|
---|
| 270 | */
|
---|
| 271 | Qt::SequenceMatch QAccelManager::match( QKeyEvent *e, QAccelItem* item, QKeySequence& temp )
|
---|
| 272 | {
|
---|
| 273 | SequenceMatch result = Qt::NoMatch;
|
---|
| 274 | int index = intermediate.count();
|
---|
| 275 | temp = intermediate;
|
---|
| 276 |
|
---|
| 277 | int modifier = translateModifiers( e->state() );
|
---|
| 278 |
|
---|
| 279 | if ( e->key() && e->key() != Key_unknown) {
|
---|
| 280 | int key = e->key() | modifier;
|
---|
| 281 | if ( e->key() == Key_BackTab ) {
|
---|
| 282 | /*
|
---|
| 283 | In QApplication, we map shift+tab to shift+backtab.
|
---|
| 284 | This code here reverts the mapping in a way that keeps
|
---|
| 285 | backtab and shift+tab accelerators working, in that
|
---|
| 286 | order, meaning backtab has priority.*/
|
---|
| 287 | key &= ~SHIFT;
|
---|
| 288 |
|
---|
| 289 | temp.setKey( key, index );
|
---|
| 290 | if ( Qt::NoMatch != (result = temp.matches( item->key )) )
|
---|
| 291 | return result;
|
---|
| 292 | if ( e->state() & ShiftButton )
|
---|
| 293 | key |= SHIFT;
|
---|
| 294 | key = Key_Tab | ( key & MODIFIER_MASK );
|
---|
| 295 | temp.setKey( key, index );
|
---|
| 296 | if ( Qt::NoMatch != (result = temp.matches( item->key )) )
|
---|
| 297 | return result;
|
---|
| 298 | } else {
|
---|
| 299 | temp.setKey( key, index );
|
---|
| 300 | if ( Qt::NoMatch != (result = temp.matches( item->key )) )
|
---|
| 301 | return result;
|
---|
| 302 | }
|
---|
| 303 |
|
---|
| 304 | if ( key == Key_BackTab ) {
|
---|
| 305 | if ( e->state() & ShiftButton )
|
---|
| 306 | key |= SHIFT;
|
---|
| 307 | temp.setKey( key, index );
|
---|
| 308 | if ( Qt::NoMatch != (result = temp.matches( item->key )) )
|
---|
| 309 | return result;
|
---|
| 310 | }
|
---|
| 311 | }
|
---|
| 312 | if ( !e->text().isEmpty() ) {
|
---|
[107] | 313 | QChar c = e->text()[0];
|
---|
| 314 | // be in accordance with accoQAccel::shortcutKey()
|
---|
| 315 | if ( modifier != 0 && c.isPrint() )
|
---|
| 316 | c = c.upper();
|
---|
| 317 | temp.setKey( (int)c.unicode() | UNICODE_ACCEL | modifier, index );
|
---|
[2] | 318 | result = temp.matches( item->key );
|
---|
| 319 | }
|
---|
| 320 | return result;
|
---|
| 321 | }
|
---|
| 322 |
|
---|
| 323 | bool QAccelManager::tryAccelEvent( QWidget* w, QKeyEvent* e )
|
---|
| 324 | {
|
---|
| 325 | if ( Qt::NoMatch == currentState ) {
|
---|
| 326 | e->t = QEvent::AccelOverride;
|
---|
| 327 | e->ignore();
|
---|
| 328 | QApplication::sendSpontaneousEvent( w, e );
|
---|
| 329 | if ( e->isAccepted() )
|
---|
| 330 | return FALSE;
|
---|
| 331 | }
|
---|
| 332 | e->t = QEvent::Accel;
|
---|
| 333 | e->ignore();
|
---|
| 334 | QApplication::sendSpontaneousEvent( w, e );
|
---|
| 335 | return e->isAccepted();
|
---|
| 336 | }
|
---|
| 337 |
|
---|
| 338 | bool QAccelManager::tryComposeUnicode( QWidget* w, QKeyEvent* e )
|
---|
| 339 | {
|
---|
| 340 | if ( QApplication::metaComposeUnicode ) {
|
---|
| 341 | int value = e->key() - Key_0;
|
---|
| 342 | // Ignore acceloverrides so we don't trigger
|
---|
| 343 | // accels on keypad when Meta compose is on
|
---|
| 344 | if ( (e->type() == QEvent::AccelOverride) &&
|
---|
| 345 | (e->state() == Qt::Keypad + Qt::MetaButton) ) {
|
---|
| 346 | e->accept();
|
---|
| 347 | // Meta compose start/continue
|
---|
| 348 | } else if ( (e->type() == QEvent::KeyPress) &&
|
---|
| 349 | (e->state() == Qt::Keypad + Qt::MetaButton) ) {
|
---|
| 350 | if ( value >= 0 && value <= 9 ) {
|
---|
| 351 | QApplication::composedUnicode *= 10;
|
---|
| 352 | QApplication::composedUnicode += value;
|
---|
| 353 | return TRUE;
|
---|
| 354 | } else {
|
---|
| 355 | // Composing interrupted, dispatch!
|
---|
| 356 | if ( QApplication::composedUnicode ) {
|
---|
| 357 | QChar ch( QApplication::composedUnicode );
|
---|
| 358 | QString s( ch );
|
---|
| 359 | QKeyEvent kep( QEvent::KeyPress, 0, ch.row() ? 0 : ch.cell(), 0, s );
|
---|
| 360 | QKeyEvent ker( QEvent::KeyRelease, 0, ch.row() ? 0 : ch.cell(), 0, s );
|
---|
| 361 | QApplication::sendEvent( w, &kep );
|
---|
| 362 | QApplication::sendEvent( w, &ker );
|
---|
| 363 | }
|
---|
| 364 | QApplication::composedUnicode = 0;
|
---|
| 365 | return TRUE;
|
---|
| 366 | }
|
---|
| 367 | // Meta compose end, dispatch
|
---|
| 368 | } else if ( (e->type() == QEvent::KeyRelease) &&
|
---|
| 369 | (e->key() == Key_Meta) &&
|
---|
| 370 | (QApplication::composedUnicode != 0) ) {
|
---|
| 371 | if ( (QApplication::composedUnicode > 0) &&
|
---|
| 372 | (QApplication::composedUnicode < 0xFFFE) ) {
|
---|
| 373 | QChar ch( QApplication::composedUnicode );
|
---|
| 374 | QString s( ch );
|
---|
| 375 | QKeyEvent kep( QEvent::KeyPress, 0, ch.row() ? 0 : ch.cell(), 0, s );
|
---|
| 376 | QKeyEvent ker( QEvent::KeyRelease, 0, ch.row() ? 0 : ch.cell(), 0, s );
|
---|
| 377 | QApplication::sendEvent( w, &kep );
|
---|
| 378 | QApplication::sendEvent( w, &ker );
|
---|
| 379 | }
|
---|
| 380 | QApplication::composedUnicode = 0;
|
---|
| 381 | return TRUE;
|
---|
| 382 | }
|
---|
| 383 | }
|
---|
| 384 | return FALSE;
|
---|
| 385 | }
|
---|
| 386 |
|
---|
| 387 | /*
|
---|
| 388 | \internal
|
---|
| 389 | Checks for possible accelerators, if no widget
|
---|
| 390 | ate the keypres, or we are in the middle of a
|
---|
| 391 | partial key sequence.
|
---|
| 392 | */
|
---|
| 393 | bool QAccelManager::dispatchAccelEvent( QWidget* w, QKeyEvent* e )
|
---|
| 394 | {
|
---|
| 395 | #ifndef QT_NO_STATUSBAR
|
---|
| 396 | // Needs to be declared and used here because of "goto doclash"
|
---|
| 397 | QStatusBar* mainStatusBar = 0;
|
---|
| 398 | #endif
|
---|
| 399 |
|
---|
| 400 | // Modifiers can NOT be accelerators...
|
---|
| 401 | if ( e->key() >= Key_Shift &&
|
---|
| 402 | e->key() <= Key_Alt )
|
---|
| 403 | return FALSE;
|
---|
| 404 |
|
---|
| 405 | SequenceMatch result = Qt::NoMatch;
|
---|
| 406 | QKeySequence tocheck, partial;
|
---|
| 407 | QAccelPrivate* accel = 0;
|
---|
| 408 | QAccelItem* item = 0;
|
---|
| 409 | QAccelPrivate* firstaccel = 0;
|
---|
| 410 | QAccelItem* firstitem = 0;
|
---|
| 411 | QAccelPrivate* lastaccel = 0;
|
---|
| 412 | QAccelItem* lastitem = 0;
|
---|
| 413 |
|
---|
| 414 | QKeyEvent pe = *e;
|
---|
| 415 | int n = -1;
|
---|
| 416 | int hasShift = (e->state()&Qt::ShiftButton)?1:0;
|
---|
| 417 | bool identicalDisabled = FALSE;
|
---|
| 418 | bool matchFound = FALSE;
|
---|
| 419 | do {
|
---|
| 420 | accel = accels.first();
|
---|
| 421 | matchFound = FALSE;
|
---|
| 422 | while ( accel ) {
|
---|
| 423 | if ( correctSubWindow( w, accel ) ) {
|
---|
| 424 | if ( accel->enabled ) {
|
---|
| 425 | item = accel->aitems.last();
|
---|
| 426 | while( item ) {
|
---|
| 427 | if ( Qt::Identical == (result = match( &pe, item, tocheck )) ) {
|
---|
| 428 | if ( item->enabled ) {
|
---|
| 429 | if ( !firstaccel ) {
|
---|
| 430 | firstaccel = accel;
|
---|
| 431 | firstitem = item;
|
---|
| 432 | }
|
---|
| 433 | lastaccel = accel;
|
---|
| 434 | lastitem = item;
|
---|
| 435 | n++;
|
---|
| 436 | matchFound = TRUE;
|
---|
| 437 | if ( n > QMAX(clash,0) )
|
---|
| 438 | goto doclash;
|
---|
| 439 | } else {
|
---|
| 440 | identicalDisabled = TRUE;
|
---|
| 441 | }
|
---|
| 442 | }
|
---|
| 443 | if ( item->enabled && Qt::PartialMatch == result ) {
|
---|
| 444 | partial = tocheck;
|
---|
| 445 | matchFound = TRUE;
|
---|
| 446 | }
|
---|
| 447 | item = accel->aitems.prev();
|
---|
| 448 | }
|
---|
| 449 | } else {
|
---|
| 450 | item = accel->aitems.last();
|
---|
| 451 | while( item ) {
|
---|
| 452 | if ( Qt::Identical == match( &pe, item, tocheck ) )
|
---|
| 453 | identicalDisabled = TRUE;
|
---|
| 454 | item = accel->aitems.prev();
|
---|
| 455 | }
|
---|
| 456 | }
|
---|
| 457 | }
|
---|
| 458 | accel = accels.next();
|
---|
| 459 | }
|
---|
| 460 | pe = QKeyEvent( QEvent::Accel, pe.key(), pe.ascii(), pe.state()&~Qt::ShiftButton, pe.text() );
|
---|
| 461 | } while ( hasShift-- && !matchFound && !identicalDisabled );
|
---|
| 462 |
|
---|
| 463 | #ifndef QT_NO_STATUSBAR
|
---|
| 464 | mainStatusBar = (QStatusBar*) w->topLevelWidget()->child( 0, "QStatusBar" );
|
---|
| 465 | #endif
|
---|
| 466 | if ( n < 0 ) { // no match found
|
---|
| 467 | currentState = partial.count() ? PartialMatch : NoMatch;
|
---|
| 468 | #ifndef QT_NO_STATUSBAR
|
---|
| 469 | // Only display message if we are, or were, in a partial match
|
---|
| 470 | if ( mainStatusBar && (PartialMatch == currentState || intermediate.count() ) ) {
|
---|
| 471 | if ( currentState == Qt::PartialMatch ) {
|
---|
| 472 | mainStatusBar->message( (QString)partial + ", ...", 0 );
|
---|
| 473 | } else if (!identicalDisabled) {
|
---|
| 474 | QString message = QAccel::tr("%1, %2 not defined").
|
---|
| 475 | arg( (QString)intermediate ).
|
---|
| 476 | arg( QKeySequence::encodeString( e->key() | translateModifiers(e->state()) ) );
|
---|
| 477 | mainStatusBar->message( message, 2000 );
|
---|
| 478 | // Since we're a NoMatch, reset the clash count
|
---|
| 479 | clash = -1;
|
---|
| 480 | } else {
|
---|
| 481 | mainStatusBar->clear();
|
---|
| 482 | }
|
---|
| 483 | }
|
---|
| 484 | #endif
|
---|
| 485 |
|
---|
| 486 | bool eatKey = (PartialMatch == currentState || intermediate.count() );
|
---|
| 487 | intermediate = partial;
|
---|
| 488 | if ( eatKey )
|
---|
| 489 | e->accept();
|
---|
| 490 | return eatKey;
|
---|
| 491 | } else if ( n == 0 ) { // found exactly one match
|
---|
| 492 | clash = -1; // reset
|
---|
| 493 | #ifndef QT_NO_STATUSBAR
|
---|
| 494 | if ( currentState == Qt::PartialMatch && mainStatusBar )
|
---|
| 495 | mainStatusBar->clear();
|
---|
| 496 | #endif
|
---|
| 497 | currentState = Qt::NoMatch; // Free sequence keylock
|
---|
| 498 | intermediate = QKeySequence();
|
---|
| 499 | lastaccel->activate( lastitem );
|
---|
| 500 | e->accept();
|
---|
| 501 | return TRUE;
|
---|
| 502 | }
|
---|
| 503 |
|
---|
| 504 | doclash: // found more than one match
|
---|
| 505 | #ifndef QT_NO_STATUSBAR
|
---|
| 506 | if ( !mainStatusBar ) // if "goto doclash", we need to get statusbar again.
|
---|
| 507 | mainStatusBar = (QStatusBar*) w->topLevelWidget()->child( 0, "QStatusBar" );
|
---|
| 508 | #endif
|
---|
| 509 |
|
---|
| 510 | QString message = QAccel::tr( "Ambiguous \"%1\" not handled" ).arg( (QString)tocheck );
|
---|
| 511 | if ( clash >= 0 && n > clash ) { // pick next match
|
---|
| 512 | intermediate = QKeySequence();
|
---|
| 513 | currentState = Qt::NoMatch; // Free sequence keylock
|
---|
| 514 | clash++;
|
---|
| 515 | #ifndef QT_NO_STATUSBAR
|
---|
| 516 | if ( mainStatusBar &&
|
---|
| 517 | !lastitem->signal &&
|
---|
| 518 | !(lastaccel->parent->receivers( "activatedAmbiguously(int)" )) )
|
---|
| 519 | mainStatusBar->message( message, 2000 );
|
---|
| 520 | #endif
|
---|
| 521 | lastaccel->activateAmbiguously( lastitem );
|
---|
| 522 | } else { // start (or wrap) with the first matching
|
---|
| 523 | intermediate = QKeySequence();
|
---|
| 524 | currentState = Qt::NoMatch; // Free sequence keylock
|
---|
| 525 | clash = 0;
|
---|
| 526 | #ifndef QT_NO_STATUSBAR
|
---|
| 527 | if ( mainStatusBar &&
|
---|
| 528 | !firstitem->signal &&
|
---|
| 529 | !(firstaccel->parent->receivers( "activatedAmbiguously(int)" )) )
|
---|
| 530 | mainStatusBar->message( message, 2000 );
|
---|
| 531 | #endif
|
---|
| 532 | firstaccel->activateAmbiguously( firstitem );
|
---|
| 533 | }
|
---|
| 534 | e->accept();
|
---|
| 535 | return TRUE;
|
---|
| 536 | }
|
---|
| 537 |
|
---|
| 538 | QAccelPrivate::QAccelPrivate( QAccel* p )
|
---|
| 539 | : parent( p )
|
---|
| 540 | {
|
---|
| 541 | QAccelManager::self()->registerAccel( this );
|
---|
| 542 | aitems.setAutoDelete( TRUE );
|
---|
| 543 | ignorewhatsthis = FALSE;
|
---|
| 544 | }
|
---|
| 545 |
|
---|
| 546 | QAccelPrivate::~QAccelPrivate()
|
---|
| 547 | {
|
---|
| 548 | QAccelManager::self()->unregisterAccel( this );
|
---|
| 549 | }
|
---|
| 550 |
|
---|
| 551 | static QAccelItem *find_id( QAccelList &list, int id )
|
---|
| 552 | {
|
---|
| 553 | register QAccelItem *item = list.first();
|
---|
| 554 | while ( item && item->id != id )
|
---|
| 555 | item = list.next();
|
---|
| 556 | return item;
|
---|
| 557 | }
|
---|
| 558 |
|
---|
| 559 | static QAccelItem *find_key( QAccelList &list, const QKeySequence &key )
|
---|
| 560 | {
|
---|
| 561 | register QAccelItem *item = list.first();
|
---|
| 562 | while ( item && !( item->key == key ) )
|
---|
| 563 | item = list.next();
|
---|
| 564 | return item;
|
---|
| 565 | }
|
---|
| 566 |
|
---|
| 567 | /*!
|
---|
| 568 | Constructs a QAccel object called \a name, with parent \a parent.
|
---|
| 569 | The accelerator operates on \a parent.
|
---|
| 570 | */
|
---|
| 571 |
|
---|
| 572 | QAccel::QAccel( QWidget *parent, const char *name )
|
---|
| 573 | : QObject( parent, name )
|
---|
| 574 | {
|
---|
| 575 | d = new QAccelPrivate( this );
|
---|
| 576 | d->enabled = TRUE;
|
---|
| 577 | d->watch = parent;
|
---|
| 578 | #if defined(QT_CHECK_NULL)
|
---|
| 579 | if ( !d->watch )
|
---|
| 580 | qWarning( "QAccel: An accelerator must have a parent or a watch widget" );
|
---|
| 581 | #endif
|
---|
| 582 | }
|
---|
| 583 |
|
---|
| 584 | /*!
|
---|
| 585 | Constructs a QAccel object called \a name, that operates on \a
|
---|
| 586 | watch, and is a child of \a parent.
|
---|
| 587 |
|
---|
| 588 | This constructor is not needed for normal application programming.
|
---|
| 589 | */
|
---|
| 590 | QAccel::QAccel( QWidget* watch, QObject *parent, const char *name )
|
---|
| 591 | : QObject( parent, name )
|
---|
| 592 | {
|
---|
| 593 | d = new QAccelPrivate( this );
|
---|
| 594 | d->enabled = TRUE;
|
---|
| 595 | d->watch = watch;
|
---|
| 596 | #if defined(QT_CHECK_NULL)
|
---|
| 597 | if ( !d->watch )
|
---|
| 598 | qWarning( "QAccel: An accelerator must have a parent or a watch widget" );
|
---|
| 599 | #endif
|
---|
| 600 | }
|
---|
| 601 |
|
---|
| 602 | /*!
|
---|
| 603 | Destroys the accelerator object and frees all allocated resources.
|
---|
| 604 | */
|
---|
| 605 |
|
---|
| 606 | QAccel::~QAccel()
|
---|
| 607 | {
|
---|
| 608 | delete d;
|
---|
| 609 | }
|
---|
| 610 |
|
---|
| 611 |
|
---|
| 612 | /*!
|
---|
| 613 | \fn void QAccel::activated( int id )
|
---|
| 614 |
|
---|
| 615 | This signal is emitted when an accelerator key is pressed. \a id
|
---|
| 616 | is a number that identifies this particular accelerator item.
|
---|
| 617 |
|
---|
| 618 | \sa activatedAmbiguously()
|
---|
| 619 | */
|
---|
| 620 |
|
---|
| 621 | /*!
|
---|
| 622 | \fn void QAccel::activatedAmbiguously( int id )
|
---|
| 623 |
|
---|
| 624 | This signal is emitted when an accelerator key is pressed. \a id
|
---|
| 625 | is a number that identifies this particular accelerator item.
|
---|
| 626 |
|
---|
| 627 | \sa activated()
|
---|
| 628 | */
|
---|
| 629 |
|
---|
| 630 |
|
---|
| 631 | /*!
|
---|
| 632 | Returns TRUE if the accelerator is enabled; otherwise returns
|
---|
| 633 | FALSE.
|
---|
| 634 |
|
---|
| 635 | \sa setEnabled(), isItemEnabled()
|
---|
| 636 | */
|
---|
| 637 |
|
---|
| 638 | bool QAccel::isEnabled() const
|
---|
| 639 | {
|
---|
| 640 | return d->enabled;
|
---|
| 641 | }
|
---|
| 642 |
|
---|
| 643 |
|
---|
| 644 | /*!
|
---|
| 645 | Enables the accelerator if \a enable is TRUE, or disables it if \a
|
---|
| 646 | enable is FALSE.
|
---|
| 647 |
|
---|
| 648 | Individual keys can also be enabled or disabled using
|
---|
| 649 | setItemEnabled(). To work, a key must be an enabled item in an
|
---|
| 650 | enabled QAccel.
|
---|
| 651 |
|
---|
| 652 | \sa isEnabled(), setItemEnabled()
|
---|
| 653 | */
|
---|
| 654 |
|
---|
| 655 | void QAccel::setEnabled( bool enable )
|
---|
| 656 | {
|
---|
| 657 | d->enabled = enable;
|
---|
| 658 | }
|
---|
| 659 |
|
---|
| 660 |
|
---|
| 661 | /*!
|
---|
| 662 | Returns the number of accelerator items in this accelerator.
|
---|
| 663 | */
|
---|
| 664 |
|
---|
| 665 | uint QAccel::count() const
|
---|
| 666 | {
|
---|
| 667 | return d->aitems.count();
|
---|
| 668 | }
|
---|
| 669 |
|
---|
| 670 |
|
---|
| 671 | static int get_seq_id()
|
---|
| 672 | {
|
---|
| 673 | static int seq_no = -2; // -1 is used as return value in findKey()
|
---|
| 674 | return seq_no--;
|
---|
| 675 | }
|
---|
| 676 |
|
---|
| 677 | /*!
|
---|
| 678 | Inserts an accelerator item and returns the item's identifier.
|
---|
| 679 |
|
---|
| 680 | \a key is a key code and an optional combination of SHIFT, CTRL
|
---|
| 681 | and ALT. \a id is the accelerator item id.
|
---|
| 682 |
|
---|
| 683 | If \a id is negative, then the item will be assigned a unique
|
---|
| 684 | negative identifier less than -1.
|
---|
| 685 |
|
---|
| 686 | \code
|
---|
| 687 | QAccel *a = new QAccel( myWindow ); // create accels for myWindow
|
---|
| 688 | a->insertItem( CTRL + Key_P, 200 ); // Ctrl+P, e.g. to print document
|
---|
| 689 | a->insertItem( ALT + Key_X, 201 ); // Alt+X, e.g. to quit
|
---|
| 690 | a->insertItem( UNICODE_ACCEL + 'q', 202 ); // Unicode 'q', e.g. to quit
|
---|
| 691 | a->insertItem( Key_D ); // gets a unique negative id < -1
|
---|
| 692 | a->insertItem( CTRL + SHIFT + Key_P ); // gets a unique negative id < -1
|
---|
| 693 | \endcode
|
---|
| 694 | */
|
---|
| 695 |
|
---|
| 696 | int QAccel::insertItem( const QKeySequence& key, int id )
|
---|
| 697 | {
|
---|
| 698 | if ( id == -1 )
|
---|
| 699 | id = get_seq_id();
|
---|
| 700 | d->aitems.insert( 0, new QAccelItem(key,id) );
|
---|
| 701 | return id;
|
---|
| 702 | }
|
---|
| 703 |
|
---|
| 704 | /*!
|
---|
| 705 | Removes the accelerator item with the identifier \a id.
|
---|
| 706 | */
|
---|
| 707 |
|
---|
| 708 | void QAccel::removeItem( int id )
|
---|
| 709 | {
|
---|
| 710 | if ( find_id( d->aitems, id) )
|
---|
| 711 | d->aitems.remove();
|
---|
| 712 | }
|
---|
| 713 |
|
---|
| 714 |
|
---|
| 715 | /*!
|
---|
| 716 | Removes all accelerator items.
|
---|
| 717 | */
|
---|
| 718 |
|
---|
| 719 | void QAccel::clear()
|
---|
| 720 | {
|
---|
| 721 | d->aitems.clear();
|
---|
| 722 | }
|
---|
| 723 |
|
---|
| 724 |
|
---|
| 725 | /*!
|
---|
| 726 | Returns the key sequence of the accelerator item with identifier
|
---|
| 727 | \a id, or an invalid key sequence (0) if the id cannot be found.
|
---|
| 728 | */
|
---|
| 729 |
|
---|
| 730 | QKeySequence QAccel::key( int id )
|
---|
| 731 | {
|
---|
| 732 | QAccelItem *item = find_id( d->aitems, id);
|
---|
| 733 | return item ? item->key : QKeySequence( 0 );
|
---|
| 734 | }
|
---|
| 735 |
|
---|
| 736 |
|
---|
| 737 | /*!
|
---|
| 738 | Returns the identifier of the accelerator item with the key code
|
---|
| 739 | \a key, or -1 if the item cannot be found.
|
---|
| 740 | */
|
---|
| 741 |
|
---|
| 742 | int QAccel::findKey( const QKeySequence& key ) const
|
---|
| 743 | {
|
---|
| 744 | QAccelItem *item = find_key( d->aitems, key );
|
---|
| 745 | return item ? item->id : -1;
|
---|
| 746 | }
|
---|
| 747 |
|
---|
| 748 |
|
---|
| 749 | /*!
|
---|
| 750 | Returns TRUE if the accelerator item with the identifier \a id is
|
---|
| 751 | enabled. Returns FALSE if the item is disabled or cannot be found.
|
---|
| 752 |
|
---|
| 753 | \sa setItemEnabled(), isEnabled()
|
---|
| 754 | */
|
---|
| 755 |
|
---|
| 756 | bool QAccel::isItemEnabled( int id ) const
|
---|
| 757 | {
|
---|
| 758 | QAccelItem *item = find_id( d->aitems, id);
|
---|
| 759 | return item ? item->enabled : FALSE;
|
---|
| 760 | }
|
---|
| 761 |
|
---|
| 762 |
|
---|
| 763 | /*!
|
---|
| 764 | Enables the accelerator item with the identifier \a id if \a
|
---|
| 765 | enable is TRUE, and disables item \a id if \a enable is FALSE.
|
---|
| 766 |
|
---|
| 767 | To work, an item must be enabled and be in an enabled QAccel.
|
---|
| 768 |
|
---|
| 769 | \sa isItemEnabled(), isEnabled()
|
---|
| 770 | */
|
---|
| 771 |
|
---|
| 772 | void QAccel::setItemEnabled( int id, bool enable )
|
---|
| 773 | {
|
---|
| 774 | QAccelItem *item = find_id( d->aitems, id);
|
---|
| 775 | if ( item )
|
---|
| 776 | item->enabled = enable;
|
---|
| 777 | }
|
---|
| 778 |
|
---|
| 779 |
|
---|
| 780 | /*!
|
---|
| 781 | Connects the accelerator item \a id to the slot \a member of \a
|
---|
| 782 | receiver.
|
---|
| 783 |
|
---|
| 784 | \code
|
---|
| 785 | a->connectItem( 201, mainView, SLOT(quit()) );
|
---|
| 786 | \endcode
|
---|
| 787 |
|
---|
| 788 | Of course, you can also send a signal as \a member.
|
---|
| 789 |
|
---|
| 790 | Normally accelerators are connected to slots which then receive
|
---|
| 791 | the \c activated(int id) signal with the id of the accelerator
|
---|
| 792 | item that was activated. If you choose to connect a specific
|
---|
| 793 | accelerator item using this function, the \c activated() signal is
|
---|
| 794 | emitted if the associated key sequence is pressed but no \c
|
---|
| 795 | activated(int id) signal is emitted.
|
---|
| 796 |
|
---|
| 797 | \sa disconnectItem()
|
---|
| 798 | */
|
---|
| 799 |
|
---|
| 800 | bool QAccel::connectItem( int id, const QObject *receiver, const char *member )
|
---|
| 801 | {
|
---|
| 802 | QAccelItem *item = find_id( d->aitems, id);
|
---|
| 803 | if ( item ) {
|
---|
| 804 | if ( !item->signal ) {
|
---|
| 805 | item->signal = new QSignal;
|
---|
| 806 | Q_CHECK_PTR( item->signal );
|
---|
| 807 | }
|
---|
| 808 | return item->signal->connect( receiver, member );
|
---|
| 809 | }
|
---|
| 810 | return FALSE;
|
---|
| 811 | }
|
---|
| 812 |
|
---|
| 813 | /*!
|
---|
| 814 | Disconnects an accelerator item with id \a id from the function
|
---|
| 815 | called \a member in the \a receiver object.
|
---|
| 816 |
|
---|
| 817 | \sa connectItem()
|
---|
| 818 | */
|
---|
| 819 |
|
---|
| 820 | bool QAccel::disconnectItem( int id, const QObject *receiver,
|
---|
| 821 | const char *member )
|
---|
| 822 | {
|
---|
| 823 | QAccelItem *item = find_id( d->aitems, id);
|
---|
| 824 | if ( item && item->signal )
|
---|
| 825 | return item->signal->disconnect( receiver, member );
|
---|
| 826 | return FALSE;
|
---|
| 827 | }
|
---|
| 828 |
|
---|
| 829 | void QAccelPrivate::activate( QAccelItem* item )
|
---|
| 830 | {
|
---|
| 831 | #ifndef QT_NO_WHATSTHIS
|
---|
| 832 | if ( QWhatsThis::inWhatsThisMode() && !ignorewhatsthis ) {
|
---|
| 833 | QWhatsThis::leaveWhatsThisMode( item->whatsthis );
|
---|
| 834 | return;
|
---|
| 835 | }
|
---|
| 836 | #endif
|
---|
| 837 | if ( item->signal )
|
---|
| 838 | item->signal->activate();
|
---|
| 839 | else
|
---|
| 840 | emit parent->activated( item->id );
|
---|
| 841 | }
|
---|
| 842 |
|
---|
| 843 | void QAccelPrivate::activateAmbiguously( QAccelItem* item )
|
---|
| 844 | {
|
---|
| 845 | if ( item->signal )
|
---|
| 846 | item->signal->activate();
|
---|
| 847 | else
|
---|
| 848 | emit parent->activatedAmbiguously( item->id );
|
---|
| 849 | }
|
---|
| 850 |
|
---|
| 851 |
|
---|
| 852 | /*!
|
---|
| 853 | Returns the shortcut key sequence for \a str, or an invalid key
|
---|
| 854 | sequence (0) if \a str has no shortcut sequence.
|
---|
| 855 |
|
---|
| 856 | For example, shortcutKey("E&xit") returns ALT+Key_X,
|
---|
| 857 | shortcutKey("&Quit") returns ALT+Key_Q and shortcutKey("Quit")
|
---|
| 858 | returns 0. (In code that does not inherit the Qt namespace class,
|
---|
| 859 | you must write e.g. Qt::ALT+Qt::Key_Q.)
|
---|
| 860 |
|
---|
| 861 | We provide a \link accelerators.html list of common accelerators
|
---|
| 862 | \endlink in English. At the time of writing, Microsoft and Open
|
---|
| 863 | Group do not appear to have issued equivalent recommendations for
|
---|
| 864 | other languages.
|
---|
| 865 | */
|
---|
| 866 |
|
---|
| 867 | QKeySequence QAccel::shortcutKey( const QString &str )
|
---|
| 868 | {
|
---|
| 869 | if(qt_accel_no_shortcuts)
|
---|
| 870 | return QKeySequence();
|
---|
| 871 |
|
---|
| 872 | int p = 0;
|
---|
| 873 | while ( p >= 0 ) {
|
---|
| 874 | p = str.find( '&', p ) + 1;
|
---|
| 875 | if ( p <= 0 || p >= (int)str.length() )
|
---|
| 876 | return 0;
|
---|
| 877 | if ( str[p] != '&' ) {
|
---|
| 878 | QChar c = str[p];
|
---|
| 879 | if ( c.isPrint() ) {
|
---|
| 880 | c = c.upper();
|
---|
| 881 | return QKeySequence( c.unicode() + ALT + UNICODE_ACCEL );
|
---|
| 882 | }
|
---|
| 883 | }
|
---|
| 884 | p++;
|
---|
| 885 | }
|
---|
| 886 | return QKeySequence();
|
---|
| 887 | }
|
---|
| 888 |
|
---|
| 889 | /*! \obsolete
|
---|
| 890 |
|
---|
| 891 | Creates an accelerator string for the key \a k.
|
---|
| 892 | For instance CTRL+Key_O gives "Ctrl+O". The "Ctrl" etc.
|
---|
| 893 | are translated (using QObject::tr()) in the "QAccel" context.
|
---|
| 894 |
|
---|
| 895 | The function is superfluous. Cast the QKeySequence \a k to a
|
---|
| 896 | QString for the same effect.
|
---|
| 897 | */
|
---|
| 898 | QString QAccel::keyToString( QKeySequence k )
|
---|
| 899 | {
|
---|
| 900 | return (QString) k;
|
---|
| 901 | }
|
---|
| 902 |
|
---|
| 903 | /*!\obsolete
|
---|
| 904 |
|
---|
| 905 | Returns an accelerator code for the string \a s. For example
|
---|
| 906 | "Ctrl+O" gives CTRL+UNICODE_ACCEL+'O'. The strings "Ctrl",
|
---|
| 907 | "Shift", "Alt" are recognized, as well as their translated
|
---|
| 908 | equivalents in the "QAccel" context (using QObject::tr()). Returns 0
|
---|
| 909 | if \a s is not recognized.
|
---|
| 910 |
|
---|
| 911 | This function is typically used with \link QObject::tr() tr
|
---|
| 912 | \endlink(), so that accelerator keys can be replaced in
|
---|
| 913 | translations:
|
---|
| 914 |
|
---|
| 915 | \code
|
---|
| 916 | QPopupMenu *file = new QPopupMenu( this );
|
---|
| 917 | file->insertItem( p1, tr("&Open..."), this, SLOT(open()),
|
---|
| 918 | QAccel::stringToKey(tr("Ctrl+O", "File|Open")) );
|
---|
| 919 | \endcode
|
---|
| 920 |
|
---|
| 921 | Notice the \c "File|Open" translator comment. It is by no means
|
---|
| 922 | necessary, but it provides some context for the human translator.
|
---|
| 923 |
|
---|
| 924 |
|
---|
| 925 | The function is superfluous. Construct a QKeySequence from the
|
---|
| 926 | string \a s for the same effect.
|
---|
| 927 |
|
---|
| 928 | \sa QObject::tr()
|
---|
| 929 | \link i18n.html Internationalization with Qt \endlink
|
---|
| 930 | */
|
---|
| 931 | QKeySequence QAccel::stringToKey( const QString & s )
|
---|
| 932 | {
|
---|
| 933 | return QKeySequence( s );
|
---|
| 934 | }
|
---|
| 935 |
|
---|
| 936 |
|
---|
| 937 | /*!
|
---|
| 938 | Sets a What's This help text for the accelerator item \a id to \a
|
---|
| 939 | text.
|
---|
| 940 |
|
---|
| 941 | The text will be shown when the application is in What's This mode
|
---|
| 942 | and the user hits the accelerator key.
|
---|
| 943 |
|
---|
| 944 | To set What's This help on a menu item (with or without an
|
---|
| 945 | accelerator key), use QMenuData::setWhatsThis().
|
---|
| 946 |
|
---|
| 947 | \sa whatsThis(), QWhatsThis::inWhatsThisMode(),
|
---|
| 948 | QMenuData::setWhatsThis(), QAction::setWhatsThis()
|
---|
| 949 | */
|
---|
| 950 | void QAccel::setWhatsThis( int id, const QString& text )
|
---|
| 951 | {
|
---|
| 952 |
|
---|
| 953 | QAccelItem *item = find_id( d->aitems, id);
|
---|
| 954 | if ( item )
|
---|
| 955 | item->whatsthis = text;
|
---|
| 956 | }
|
---|
| 957 |
|
---|
| 958 | /*!
|
---|
| 959 | Returns the What's This help text for the specified item \a id or
|
---|
| 960 | QString::null if no text has been specified.
|
---|
| 961 |
|
---|
| 962 | \sa setWhatsThis()
|
---|
| 963 | */
|
---|
| 964 | QString QAccel::whatsThis( int id ) const
|
---|
| 965 | {
|
---|
| 966 |
|
---|
| 967 | QAccelItem *item = find_id( d->aitems, id);
|
---|
| 968 | return item? item->whatsthis : QString::null;
|
---|
| 969 | }
|
---|
| 970 |
|
---|
| 971 | /*!\internal */
|
---|
| 972 | void QAccel::setIgnoreWhatsThis( bool b)
|
---|
| 973 | {
|
---|
| 974 | d->ignorewhatsthis = b;
|
---|
| 975 | }
|
---|
| 976 |
|
---|
| 977 | /*!\internal */
|
---|
| 978 | bool QAccel::ignoreWhatsThis() const
|
---|
| 979 | {
|
---|
| 980 | return d->ignorewhatsthis;
|
---|
| 981 | }
|
---|
| 982 |
|
---|
| 983 |
|
---|
| 984 | /*!
|
---|
| 985 |
|
---|
| 986 | \page accelerators.html
|
---|
| 987 |
|
---|
| 988 | \title Standard Accelerator Keys
|
---|
| 989 |
|
---|
| 990 | Applications invariably need to define accelerator keys for actions.
|
---|
| 991 | Qt fully supports accelerators, for example with \l QAccel::shortcutKey().
|
---|
| 992 |
|
---|
| 993 | Here are Microsoft's recommendations for accelerator keys, with
|
---|
| 994 | comments about the Open Group's recommendations where they exist
|
---|
| 995 | and differ. For most commands, the Open Group either has no advice or
|
---|
| 996 | agrees with Microsoft.
|
---|
| 997 |
|
---|
| 998 | The emboldened letter plus Alt is Microsoft's recommended choice, and
|
---|
| 999 | we recommend supporting it. For an Apply button, for example, we
|
---|
| 1000 | recommend QButton::setText( \link QWidget::tr() tr \endlink("&Apply") );
|
---|
| 1001 |
|
---|
| 1002 | If you have conflicting commands (e.g. About and Apply buttons in the
|
---|
| 1003 | same dialog), you must decide for yourself.
|
---|
| 1004 |
|
---|
| 1005 | \list
|
---|
| 1006 | \i <b><u>A</u></b>bout
|
---|
| 1007 | \i Always on <b><u>T</u></b>op
|
---|
| 1008 | \i <b><u>A</u></b>pply
|
---|
| 1009 | \i <b><u>B</u></b>ack
|
---|
| 1010 | \i <b><u>B</u></b>rowse
|
---|
| 1011 | \i <b><u>C</u></b>lose (CDE: Alt+F4; Alt+F4 is "close window" in Windows)
|
---|
| 1012 | \i <b><u>C</u></b>opy (CDE: Ctrl+C, Ctrl+Insert)
|
---|
| 1013 | \i <b><u>C</u></b>opy Here
|
---|
| 1014 | \i Create <b><u>S</u></b>hortcut
|
---|
| 1015 | \i Create <b><u>S</u></b>hortcut Here
|
---|
| 1016 | \i Cu<b><u>t</u></b>
|
---|
| 1017 | \i <b><u>D</u></b>elete
|
---|
| 1018 | \i <b><u>E</u></b>dit
|
---|
| 1019 | \i <b><u>E</u></b>xit (CDE: E<b><u>x</u></b>it)
|
---|
| 1020 | \i <b><u>E</u></b>xplore
|
---|
| 1021 | \i <b><u>F</u></b>ile
|
---|
| 1022 | \i <b><u>F</u></b>ind
|
---|
| 1023 | \i <b><u>H</u></b>elp
|
---|
| 1024 | \i Help <b><u>T</u></b>opics
|
---|
| 1025 | \i <b><u>H</u></b>ide
|
---|
| 1026 | \i <b><u>I</u></b>nsert
|
---|
| 1027 | \i Insert <b><u>O</u></b>bject
|
---|
| 1028 | \i <b><u>L</u></b>ink Here
|
---|
| 1029 | \i Ma<b><u>x</u></b>imize
|
---|
| 1030 | \i Mi<b><u>n</u></b>imize
|
---|
| 1031 | \i <b><u>M</u></b>ove
|
---|
| 1032 | \i <b><u>M</u></b>ove Here
|
---|
| 1033 | \i <b><u>N</u></b>ew
|
---|
| 1034 | \i <b><u>N</u></b>ext
|
---|
| 1035 | \i <b><u>N</u></b>o
|
---|
| 1036 | \i <b><u>O</u></b>pen
|
---|
| 1037 | \i Open <b><u>W</u></b>ith
|
---|
| 1038 | \i Page Set<b><u>u</u></b>p
|
---|
| 1039 | \i <b><u>P</u></b>aste
|
---|
| 1040 | \i Paste <b><u>L</u></b>ink
|
---|
| 1041 | \i Paste <b><u>S</u></b>hortcut
|
---|
| 1042 | \i Paste <b><u>S</u></b>pecial
|
---|
| 1043 | \i <b><u>P</u></b>ause
|
---|
| 1044 | \i <b><u>P</u></b>lay
|
---|
| 1045 | \i <b><u>P</u></b>rint
|
---|
| 1046 | \i <b><u>P</u></b>rint Here
|
---|
| 1047 | \i P<b><u>r</u></b>operties
|
---|
| 1048 | \i <b><u>Q</u></b>uick View
|
---|
| 1049 | \i <b><u>R</u></b>edo (CDE: Ctrl+Y, Shift+Alt+Backspace)
|
---|
| 1050 | \i <b><u>R</u></b>epeat
|
---|
| 1051 | \i <b><u>R</u></b>estore
|
---|
| 1052 | \i <b><u>R</u></b>esume
|
---|
| 1053 | \i <b><u>R</u></b>etry
|
---|
| 1054 | \i <b><u>R</u></b>un
|
---|
| 1055 | \i <b><u>S</u></b>ave
|
---|
| 1056 | \i Save <b><u>A</u></b>s
|
---|
| 1057 | \i Select <b><u>A</u></b>ll
|
---|
| 1058 | \i Se<b><u>n</u></b>d To
|
---|
| 1059 | \i <b><u>S</u></b>how
|
---|
| 1060 | \i <b><u>S</u></b>ize
|
---|
| 1061 | \i S<b><u>p</u></b>lit
|
---|
| 1062 | \i <b><u>S</u></b>top
|
---|
| 1063 | \i <b><u>U</u></b>ndo (CDE: Ctrl+Z or Alt+Backspace)
|
---|
| 1064 | \i <b><u>V</u></b>iew
|
---|
| 1065 | \i <b><u>W</u></b>hat's This?
|
---|
| 1066 | \i <b><u>W</u></b>indow
|
---|
| 1067 | \i <b><u>Y</u></b>es
|
---|
| 1068 | \endlist
|
---|
| 1069 |
|
---|
| 1070 | There are also a lot of other keys and actions (that use other
|
---|
| 1071 | modifier keys than Alt). See the Microsoft and The Open Group
|
---|
| 1072 | documentation for details.
|
---|
| 1073 |
|
---|
| 1074 | The \link http://www.amazon.com/exec/obidos/ASIN/0735605661/trolltech/t
|
---|
| 1075 | Microsoft book \endlink has ISBN 0735605661. The corresponding Open Group
|
---|
| 1076 | book is very hard to find, rather expensive and we cannot recommend
|
---|
| 1077 | it. However, if you really want it, OGPubs@opengroup.org might be able
|
---|
| 1078 | to help. Ask them for ISBN 1859121047.
|
---|
| 1079 |
|
---|
| 1080 | */
|
---|
| 1081 |
|
---|
| 1082 | /*! \obsolete serves no purpose anymore */
|
---|
| 1083 | void QAccel::repairEventFilter() {}
|
---|
| 1084 | /*! \obsolete serves no purpose anymore */
|
---|
| 1085 | bool QAccel::eventFilter( QObject *, QEvent * ) { return FALSE; }
|
---|
| 1086 | #endif // QT_NO_ACCEL
|
---|