diff options
Diffstat (limited to 'src/kernel/qaccel.cpp')
-rw-r--r-- | src/kernel/qaccel.cpp | 1089 |
1 files changed, 1089 insertions, 0 deletions
diff --git a/src/kernel/qaccel.cpp b/src/kernel/qaccel.cpp new file mode 100644 index 000000000..b761c7365 --- /dev/null +++ b/src/kernel/qaccel.cpp @@ -0,0 +1,1089 @@ +/**************************************************************************** +** +** Implementation of TQAccel class +** +** Created : 950419 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the kernel module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing retquirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#include "qaccel.h" + +#ifndef QT_NO_ACCEL + +#include "qsignal.h" +#include "qapplication.h" +#include "qwidget.h" +#include "qptrlist.h" +#include "qwhatsthis.h" +#include "qguardedptr.h" +#include "qstatusbar.h" +#include "qdockwindow.h" +#include "qsignalslotimp.h" +/*! + \class TQAccel qaccel.h + \brief The TQAccel class handles keyboard accelerator and shortcut keys. + + \ingroup misc + + A keyboard accelerator triggers an action when a certain key + combination is pressed. The accelerator handles all keyboard + activity for all the children of one top-level widget, so it is + not affected by the keyboard focus. + + In most cases, you will not need to use this class directly. Use + the TQAction class to create actions with accelerators that can be + used in both menus and toolbars. If you're only interested in + menus use TQMenuData::insertItem() or TQMenuData::setAccel() to make + accelerators for operations that are also available on menus. Many + widgets automatically generate accelerators, such as TQButton, + TQGroupBox, TQLabel (with TQLabel::setBuddy()), TQMenuBar and TQTabBar. + Example: + \code + TQPushButton p( "&Exit", parent ); // automatic shortcut ALT+Key_E + TQPopupMenu *fileMenu = new fileMenu( parent ); + fileMenu->insertItem( "Undo", parent, SLOT(undo()), CTRL+Key_Z ); + \endcode + + A TQAccel contains a list of accelerator items that can be + manipulated using insertItem(), removeItem(), clear(), key() and + findKey(). + + Each accelerator item consists of an identifier and a \l + TQKeySequence. A single key sequence consists of a keyboard code + combined with modifiers (\c SHIFT, \c CTRL, \c ALT or \c + UNICODE_ACCEL). For example, \c{CTRL + Key_P} could be a shortcut + for printing a document. The key codes are listed in \c + qnamespace.h. As an alternative, use \c UNICODE_ACCEL with the + unicode code point of the character. For example, \c{UNICODE_ACCEL + + 'A'} gives the same accelerator as \c Key_A. + + When an accelerator key is pressed, the accelerator sends out the + signal activated() with a number that identifies this particular + accelerator item. Accelerator items can also be individually + connected, so that two different keys will activate two different + slots (see connectItem() and disconnectItem()). + + The activated() signal is \e not emitted when two or more + accelerators match the same key. Instead, the first matching + accelerator sends out the activatedAmbiguously() signal. By + pressing the key multiple times, users can navigate between all + matching accelerators. Some standard controls like TQPushButton and + TQCheckBox connect the activatedAmbiguously() signal to the + harmless setFocus() slot, whereas activated() is connected to a + slot invoking the button's action. Most controls, like TQLabel and + TQTabBar, treat activated() and activatedAmbiguously() as + equivalent. + + Use setEnabled() to enable or disable all the items in an + accelerator, or setItemEnabled() to enable or disable individual + items. An item is active only when both the TQAccel and the item + itself are enabled. + + The function setWhatsThis() specifies a help text that appears + when the user presses an accelerator key in What's This mode. + + The accelerator will be deleted when \e parent is deleted, + and will consume relevant key events until then. + + Please note that the accelerator + \code + accelerator->insertItem( TQKeySequence("M") ); + \endcode + can be triggered with both the 'M' key, and with Shift+M, + unless a second accelerator is defined for the Shift+M + combination. + + + Example: + \code + TQAccel *a = new TQAccel( myWindow ); // create accels for myWindow + a->connectItem( a->insertItem(Key_P+CTRL), // adds Ctrl+P accelerator + myWindow, // connected to myWindow's + SLOT(printDoc()) ); // printDoc() slot + \endcode + + \sa TQKeyEvent TQWidget::keyPressEvent() TQMenuData::setAccel() + TQButton::setAccel() TQLabel::setBuddy() TQKeySequence + \link guibooks.html#fowler GUI Design Handbook: Keyboard Shortcuts \endlink. +*/ + + +struct TQAccelItem { // internal accelerator item + TQAccelItem( const TQKeySequence &k, int i ) + { key=k; id=i; enabled=TRUE; signal=0; } + ~TQAccelItem() { delete signal; } + int id; + TQKeySequence key; + bool enabled; + TQSignal *signal; + TQString whatsthis; +}; + + +typedef TQPtrList<TQAccelItem> TQAccelList; // internal accelerator list + +class TQAccelPrivate : public TQt { +public: + TQAccelPrivate( TQAccel* p ); + ~TQAccelPrivate(); + TQAccelList aitems; + bool enabled; + TQGuardedPtr<TQWidget> watch; + bool ignorewhatsthis; + TQAccel* parent; + + void activate( TQAccelItem* item ); + void activateAmbiguously( TQAccelItem* item ); +}; + +class TQAccelManager : public TQt { +public: + static TQAccelManager* self() { return self_ptr ? self_ptr : new TQAccelManager; } + void registerAccel( TQAccelPrivate* a ) { accels.append( a ); } + void unregisterAccel( TQAccelPrivate* a ) { accels.removeRef( a ); if ( accels.isEmpty() ) delete this; } + bool tryAccelEvent( TQWidget* w, TQKeyEvent* e ); + bool dispatchAccelEvent( TQWidget* w, TQKeyEvent* e ); + bool tryComposeUnicode( TQWidget* w, TQKeyEvent* e ); + +private: + TQAccelManager():currentState(TQt::NoMatch), clash(-1) { self_ptr = this; } + ~TQAccelManager() { self_ptr = 0; } + + bool correctSubWindow( TQWidget *w, TQAccelPrivate* d ); + SequenceMatch match( TQKeyEvent* e, TQAccelItem* item, TQKeySequence& temp ); + int translateModifiers( ButtonState state ); + + TQPtrList<TQAccelPrivate> accels; + static TQAccelManager* self_ptr; + TQt::SequenceMatch currentState; + TQKeySequence intermediate; + int clash; +}; +TQAccelManager* TQAccelManager::self_ptr = 0; + +bool Q_EXPORT qt_tryAccelEvent( TQWidget* w, TQKeyEvent* e){ + return TQAccelManager::self()->tryAccelEvent( w, e ); +} + +bool Q_EXPORT qt_dispatchAccelEvent( TQWidget* w, TQKeyEvent* e){ + return TQAccelManager::self()->dispatchAccelEvent( w, e ); +} + +bool Q_EXPORT qt_tryComposeUnicode( TQWidget* w, TQKeyEvent* e){ + return TQAccelManager::self()->tryComposeUnicode( w, e ); +} + +#ifdef Q_WS_MAC +static bool qt_accel_no_shortcuts = TRUE; +#else +static bool qt_accel_no_shortcuts = FALSE; +#endif +void Q_EXPORT qt_setAccelAutoShortcuts(bool b) { qt_accel_no_shortcuts = b; } + +/* + \internal + Returns TRUE if the accel is in the current subwindow, else FALSE. +*/ +bool TQAccelManager::correctSubWindow( TQWidget* w, TQAccelPrivate* d ) { +#if !defined ( Q_OS_MACX ) + if ( !d->watch || !d->watch->isVisible() || !d->watch->isEnabled() ) +#else + if ( !d->watch || (!d->watch->isVisible() && !d->watch->inherits( "TQMenuBar" )) || !d->watch->isEnabled() ) +#endif + return FALSE; + TQWidget* tlw = w->topLevelWidget(); + TQWidget* wtlw = d->watch->topLevelWidget(); + + /* if we live in a floating dock window, keep our parent's + * accelerators working */ +#ifndef QT_NO_MAINWINDOW + if ( tlw->isDialog() && tlw->parentWidget() && ::qt_cast<TQDockWindow*>(tlw) ) + return tlw->parentWidget()->topLevelWidget() == wtlw; + + if ( wtlw != tlw ) + return FALSE; +#endif + /* if we live in a MDI subwindow, ignore the event if we are + not the active document window */ + TQWidget* sw = d->watch; + while ( sw && !sw->testWFlags( WSubWindow ) ) + sw = sw->parentWidget( TRUE ); + if ( sw ) { // we are in a subwindow indeed + TQWidget* fw = w; + while ( fw && fw != sw ) + fw = fw->parentWidget( TRUE ); + if ( fw != sw ) // focus widget not in our subwindow + return FALSE; + } + return TRUE; +} + +inline int TQAccelManager::translateModifiers( ButtonState state ) +{ + int result = 0; + if ( state & ShiftButton ) + result |= SHIFT; + if ( state & ControlButton ) + result |= CTRL; + if ( state & MetaButton ) + result |= META; + if ( state & AltButton ) + result |= ALT; + return result; +} + +/* + \internal + Matches the current intermediate key sequence + the latest + keyevent, with and AccelItem. Returns Identical, + PartialMatch or NoMatch, and fills \a temp with the + resulting key sequence. +*/ +TQt::SequenceMatch TQAccelManager::match( TQKeyEvent *e, TQAccelItem* item, TQKeySequence& temp ) +{ + SequenceMatch result = TQt::NoMatch; + int index = intermediate.count(); + temp = intermediate; + + int modifier = translateModifiers( e->state() ); + + if ( e->key() && e->key() != Key_unknown) { + int key = e->key() | modifier; + if ( e->key() == Key_BackTab ) { + /* + In TQApplication, we map shift+tab to shift+backtab. + This code here reverts the mapping in a way that keeps + backtab and shift+tab accelerators working, in that + order, meaning backtab has priority.*/ + key &= ~SHIFT; + + temp.setKey( key, index ); + if ( TQt::NoMatch != (result = temp.matches( item->key )) ) + return result; + if ( e->state() & ShiftButton ) + key |= SHIFT; + key = Key_Tab | ( key & MODIFIER_MASK ); + temp.setKey( key, index ); + if ( TQt::NoMatch != (result = temp.matches( item->key )) ) + return result; + } else { + temp.setKey( key, index ); + if ( TQt::NoMatch != (result = temp.matches( item->key )) ) + return result; + } + + if ( key == Key_BackTab ) { + if ( e->state() & ShiftButton ) + key |= SHIFT; + temp.setKey( key, index ); + if ( TQt::NoMatch != (result = temp.matches( item->key )) ) + return result; + } + } + if ( !e->text().isEmpty() ) { + temp.setKey( (int)e->text()[0].unicode() | UNICODE_ACCEL | modifier, index ); + result = temp.matches( item->key ); + } + return result; +} + +bool TQAccelManager::tryAccelEvent( TQWidget* w, TQKeyEvent* e ) +{ + if ( TQt::NoMatch == currentState ) { + e->t = TQEvent::AccelOverride; + e->ignore(); + TQApplication::sendSpontaneousEvent( w, e ); + if ( e->isAccepted() ) + return FALSE; + } + e->t = TQEvent::Accel; + e->ignore(); + TQApplication::sendSpontaneousEvent( w, e ); + return e->isAccepted(); +} + +bool TQAccelManager::tryComposeUnicode( TQWidget* w, TQKeyEvent* e ) +{ + if ( TQApplication::metaComposeUnicode ) { + int value = e->key() - Key_0; + // Ignore acceloverrides so we don't trigger + // accels on keypad when Meta compose is on + if ( (e->type() == TQEvent::AccelOverride) && + (e->state() == TQt::Keypad + TQt::MetaButton) ) { + e->accept(); + // Meta compose start/continue + } else if ( (e->type() == TQEvent::KeyPress) && + (e->state() == TQt::Keypad + TQt::MetaButton) ) { + if ( value >= 0 && value <= 9 ) { + TQApplication::composedUnicode *= 10; + TQApplication::composedUnicode += value; + return TRUE; + } else { + // Composing interrupted, dispatch! + if ( TQApplication::composedUnicode ) { + TQChar ch( TQApplication::composedUnicode ); + TQString s( ch ); + TQKeyEvent kep( TQEvent::KeyPress, 0, ch.row() ? 0 : ch.cell(), 0, s ); + TQKeyEvent ker( TQEvent::KeyRelease, 0, ch.row() ? 0 : ch.cell(), 0, s ); + TQApplication::sendEvent( w, &kep ); + TQApplication::sendEvent( w, &ker ); + } + TQApplication::composedUnicode = 0; + return TRUE; + } + // Meta compose end, dispatch + } else if ( (e->type() == TQEvent::KeyRelease) && + (e->key() == Key_Meta) && + (TQApplication::composedUnicode != 0) ) { + if ( (TQApplication::composedUnicode > 0) && + (TQApplication::composedUnicode < 0xFFFE) ) { + TQChar ch( TQApplication::composedUnicode ); + TQString s( ch ); + TQKeyEvent kep( TQEvent::KeyPress, 0, ch.row() ? 0 : ch.cell(), 0, s ); + TQKeyEvent ker( TQEvent::KeyRelease, 0, ch.row() ? 0 : ch.cell(), 0, s ); + TQApplication::sendEvent( w, &kep ); + TQApplication::sendEvent( w, &ker ); + } + TQApplication::composedUnicode = 0; + return TRUE; + } + } + return FALSE; +} + +/* + \internal + Checks for possible accelerators, if no widget + ate the keypres, or we are in the middle of a + partial key sequence. +*/ +bool TQAccelManager::dispatchAccelEvent( TQWidget* w, TQKeyEvent* e ) +{ +#ifndef QT_NO_STATUSBAR + // Needs to be declared and used here because of "goto doclash" + TQStatusBar* mainStatusBar = 0; +#endif + + // Modifiers can NOT be accelerators... + if ( e->key() >= Key_Shift && + e->key() <= Key_Alt ) + return FALSE; + + SequenceMatch result = TQt::NoMatch; + TQKeySequence tocheck, partial; + TQAccelPrivate* accel = 0; + TQAccelItem* item = 0; + TQAccelPrivate* firstaccel = 0; + TQAccelItem* firstitem = 0; + TQAccelPrivate* lastaccel = 0; + TQAccelItem* lastitem = 0; + + TQKeyEvent pe = *e; + int n = -1; + int hasShift = (e->state()&TQt::ShiftButton)?1:0; + bool identicalDisabled = FALSE; + bool matchFound = FALSE; + do { + accel = accels.first(); + matchFound = FALSE; + while ( accel ) { + if ( correctSubWindow( w, accel ) ) { + if ( accel->enabled ) { + item = accel->aitems.last(); + while( item ) { + if ( TQt::Identical == (result = match( &pe, item, tocheck )) ) { + if ( item->enabled ) { + if ( !firstaccel ) { + firstaccel = accel; + firstitem = item; + } + lastaccel = accel; + lastitem = item; + n++; + matchFound = TRUE; + if ( n > TQMAX(clash,0) ) + goto doclash; + } else { + identicalDisabled = TRUE; + } + } + if ( item->enabled && TQt::PartialMatch == result ) { + partial = tocheck; + matchFound = TRUE; + } + item = accel->aitems.prev(); + } + } else { + item = accel->aitems.last(); + while( item ) { + if ( TQt::Identical == match( &pe, item, tocheck ) ) + identicalDisabled = TRUE; + item = accel->aitems.prev(); + } + } + } + accel = accels.next(); + } + pe = TQKeyEvent( TQEvent::Accel, pe.key(), pe.ascii(), pe.state()&~TQt::ShiftButton, pe.text() ); + } while ( hasShift-- && !matchFound && !identicalDisabled ); + +#ifndef QT_NO_STATUSBAR + mainStatusBar = (TQStatusBar*) w->topLevelWidget()->child( 0, "TQStatusBar" ); +#endif + if ( n < 0 ) { // no match found + currentState = partial.count() ? PartialMatch : NoMatch; +#ifndef QT_NO_STATUSBAR + // Only display message if we are, or were, in a partial match + if ( mainStatusBar && (PartialMatch == currentState || intermediate.count() ) ) { + if ( currentState == TQt::PartialMatch ) { + mainStatusBar->message( (TQString)partial + ", ...", 0 ); + } else if (!identicalDisabled) { + TQString message = TQAccel::tr("%1, %2 not defined"). + arg( (TQString)intermediate ). + arg( TQKeySequence::encodeString( e->key() | translateModifiers(e->state()) ) ); + mainStatusBar->message( message, 2000 ); + // Since we're a NoMatch, reset the clash count + clash = -1; + } else { + mainStatusBar->clear(); + } + } +#endif + + bool eatKey = (PartialMatch == currentState || intermediate.count() ); + intermediate = partial; + if ( eatKey ) + e->accept(); + return eatKey; + } else if ( n == 0 ) { // found exactly one match + clash = -1; // reset +#ifndef QT_NO_STATUSBAR + if ( currentState == TQt::PartialMatch && mainStatusBar ) + mainStatusBar->clear(); +#endif + currentState = TQt::NoMatch; // Free sequence keylock + intermediate = TQKeySequence(); + lastaccel->activate( lastitem ); + e->accept(); + return TRUE; + } + + doclash: // found more than one match +#ifndef QT_NO_STATUSBAR + if ( !mainStatusBar ) // if "goto doclash", we need to get statusbar again. + mainStatusBar = (TQStatusBar*) w->topLevelWidget()->child( 0, "TQStatusBar" ); +#endif + + TQString message = TQAccel::tr( "Ambiguous \"%1\" not handled" ).arg( (TQString)tocheck ); + if ( clash >= 0 && n > clash ) { // pick next match + intermediate = TQKeySequence(); + currentState = TQt::NoMatch; // Free sequence keylock + clash++; +#ifndef QT_NO_STATUSBAR + if ( mainStatusBar && + !lastitem->signal && + !(lastaccel->parent->receivers( "activatedAmbiguously(int)" )) ) + mainStatusBar->message( message, 2000 ); +#endif + lastaccel->activateAmbiguously( lastitem ); + } else { // start (or wrap) with the first matching + intermediate = TQKeySequence(); + currentState = TQt::NoMatch; // Free sequence keylock + clash = 0; +#ifndef QT_NO_STATUSBAR + if ( mainStatusBar && + !firstitem->signal && + !(firstaccel->parent->receivers( "activatedAmbiguously(int)" )) ) + mainStatusBar->message( message, 2000 ); +#endif + firstaccel->activateAmbiguously( firstitem ); + } + e->accept(); + return TRUE; +} + +TQAccelPrivate::TQAccelPrivate( TQAccel* p ) + : parent( p ) +{ + TQAccelManager::self()->registerAccel( this ); + aitems.setAutoDelete( TRUE ); + ignorewhatsthis = FALSE; +} + +TQAccelPrivate::~TQAccelPrivate() +{ + TQAccelManager::self()->unregisterAccel( this ); +} + +static TQAccelItem *find_id( TQAccelList &list, int id ) +{ + register TQAccelItem *item = list.first(); + while ( item && item->id != id ) + item = list.next(); + return item; +} + +static TQAccelItem *find_key( TQAccelList &list, const TQKeySequence &key ) +{ + register TQAccelItem *item = list.first(); + while ( item && !( item->key == key ) ) + item = list.next(); + return item; +} + +/*! + Constructs a TQAccel object called \a name, with parent \a parent. + The accelerator operates on \a parent. +*/ + +TQAccel::TQAccel( TQWidget *parent, const char *name ) + : TQObject( parent, name ) +{ + d = new TQAccelPrivate( this ); + d->enabled = TRUE; + d->watch = parent; +#if defined(QT_CHECK_NULL) + if ( !d->watch ) + qWarning( "TQAccel: An accelerator must have a parent or a watch widget" ); +#endif +} + +/*! + Constructs a TQAccel object called \a name, that operates on \a + watch, and is a child of \a parent. + + This constructor is not needed for normal application programming. +*/ +TQAccel::TQAccel( TQWidget* watch, TQObject *parent, const char *name ) + : TQObject( parent, name ) +{ + d = new TQAccelPrivate( this ); + d->enabled = TRUE; + d->watch = watch; +#if defined(QT_CHECK_NULL) + if ( !d->watch ) + qWarning( "TQAccel: An accelerator must have a parent or a watch widget" ); +#endif +} + +/*! + Destroys the accelerator object and frees all allocated resources. +*/ + +TQAccel::~TQAccel() +{ + delete d; +} + + +/*! + \fn void TQAccel::activated( int id ) + + This signal is emitted when an accelerator key is pressed. \a id + is a number that identifies this particular accelerator item. + + \sa activatedAmbiguously() +*/ + +/*! + \fn void TQAccel::activatedAmbiguously( int id ) + + This signal is emitted when an accelerator key is pressed. \a id + is a number that identifies this particular accelerator item. + + \sa activated() +*/ + + +/*! + Returns TRUE if the accelerator is enabled; otherwise returns + FALSE. + + \sa setEnabled(), isItemEnabled() +*/ + +bool TQAccel::isEnabled() const +{ + return d->enabled; +} + + +/*! + Enables the accelerator if \a enable is TRUE, or disables it if \a + enable is FALSE. + + Individual keys can also be enabled or disabled using + setItemEnabled(). To work, a key must be an enabled item in an + enabled TQAccel. + + \sa isEnabled(), setItemEnabled() +*/ + +void TQAccel::setEnabled( bool enable ) +{ + d->enabled = enable; +} + + +/*! + Returns the number of accelerator items in this accelerator. +*/ + +uint TQAccel::count() const +{ + return d->aitems.count(); +} + + +static int get_seq_id() +{ + static int seq_no = -2; // -1 is used as return value in findKey() + return seq_no--; +} + +/*! + Inserts an accelerator item and returns the item's identifier. + + \a key is a key code and an optional combination of SHIFT, CTRL + and ALT. \a id is the accelerator item id. + + If \a id is negative, then the item will be assigned a unique + negative identifier less than -1. + + \code + TQAccel *a = new TQAccel( myWindow ); // create accels for myWindow + a->insertItem( CTRL + Key_P, 200 ); // Ctrl+P, e.g. to print document + a->insertItem( ALT + Key_X, 201 ); // Alt+X, e.g. to tquit + a->insertItem( UNICODE_ACCEL + 'q', 202 ); // Unicode 'q', e.g. to tquit + a->insertItem( Key_D ); // gets a unique negative id < -1 + a->insertItem( CTRL + SHIFT + Key_P ); // gets a unique negative id < -1 + \endcode +*/ + +int TQAccel::insertItem( const TQKeySequence& key, int id ) +{ + if ( id == -1 ) + id = get_seq_id(); + d->aitems.insert( 0, new TQAccelItem(key,id) ); + return id; +} + +/*! + Removes the accelerator item with the identifier \a id. +*/ + +void TQAccel::removeItem( int id ) +{ + if ( find_id( d->aitems, id) ) + d->aitems.remove(); +} + + +/*! + Removes all accelerator items. +*/ + +void TQAccel::clear() +{ + d->aitems.clear(); +} + + +/*! + Returns the key sequence of the accelerator item with identifier + \a id, or an invalid key sequence (0) if the id cannot be found. +*/ + +TQKeySequence TQAccel::key( int id ) +{ + TQAccelItem *item = find_id( d->aitems, id); + return item ? item->key : TQKeySequence( 0 ); +} + + +/*! + Returns the identifier of the accelerator item with the key code + \a key, or -1 if the item cannot be found. +*/ + +int TQAccel::findKey( const TQKeySequence& key ) const +{ + TQAccelItem *item = find_key( d->aitems, key ); + return item ? item->id : -1; +} + + +/*! + Returns TRUE if the accelerator item with the identifier \a id is + enabled. Returns FALSE if the item is disabled or cannot be found. + + \sa setItemEnabled(), isEnabled() +*/ + +bool TQAccel::isItemEnabled( int id ) const +{ + TQAccelItem *item = find_id( d->aitems, id); + return item ? item->enabled : FALSE; +} + + +/*! + Enables the accelerator item with the identifier \a id if \a + enable is TRUE, and disables item \a id if \a enable is FALSE. + + To work, an item must be enabled and be in an enabled TQAccel. + + \sa isItemEnabled(), isEnabled() +*/ + +void TQAccel::setItemEnabled( int id, bool enable ) +{ + TQAccelItem *item = find_id( d->aitems, id); + if ( item ) + item->enabled = enable; +} + + +/*! + Connects the accelerator item \a id to the slot \a member of \a + receiver. + + \code + a->connectItem( 201, mainView, SLOT(tquit()) ); + \endcode + + Of course, you can also send a signal as \a member. + + Normally accelerators are connected to slots which then receive + the \c activated(int id) signal with the id of the accelerator + item that was activated. If you choose to connect a specific + accelerator item using this function, the \c activated() signal is + emitted if the associated key sequence is pressed but no \c + activated(int id) signal is emitted. + + \sa disconnectItem() +*/ + +bool TQAccel::connectItem( int id, const TQObject *receiver, const char *member ) +{ + TQAccelItem *item = find_id( d->aitems, id); + if ( item ) { + if ( !item->signal ) { + item->signal = new TQSignal; + Q_CHECK_PTR( item->signal ); + } + return item->signal->connect( receiver, member ); + } + return FALSE; +} + +/*! + Disconnects an accelerator item with id \a id from the function + called \a member in the \a receiver object. + + \sa connectItem() +*/ + +bool TQAccel::disconnectItem( int id, const TQObject *receiver, + const char *member ) +{ + TQAccelItem *item = find_id( d->aitems, id); + if ( item && item->signal ) + return item->signal->disconnect( receiver, member ); + return FALSE; +} + +void TQAccelPrivate::activate( TQAccelItem* item ) +{ +#ifndef QT_NO_WHATSTHIS + if ( TQWhatsThis::inWhatsThisMode() && !ignorewhatsthis ) { + TQWhatsThis::leaveWhatsThisMode( item->whatsthis ); + return; + } +#endif + if ( item->signal ) + item->signal->activate(); + else + emit parent->activated( item->id ); +} + +void TQAccelPrivate::activateAmbiguously( TQAccelItem* item ) +{ + if ( item->signal ) + item->signal->activate(); + else + emit parent->activatedAmbiguously( item->id ); +} + + +/*! + Returns the shortcut key sequence for \a str, or an invalid key + sequence (0) if \a str has no shortcut sequence. + + For example, shortcutKey("E&xit") returns ALT+Key_X, + shortcutKey("&Quit") returns ALT+Key_Q and shortcutKey("Quit") + returns 0. (In code that does not inherit the TQt namespace class, + you must write e.g. TQt::ALT+TQt::Key_Q.) + + We provide a \link accelerators.html list of common accelerators + \endlink in English. At the time of writing, Microsoft and Open + Group do not appear to have issued equivalent recommendations for + other languages. +*/ + +TQKeySequence TQAccel::shortcutKey( const TQString &str ) +{ + if(qt_accel_no_shortcuts) + return TQKeySequence(); + + int p = 0; + while ( p >= 0 ) { + p = str.find( '&', p ) + 1; + if ( p <= 0 || p >= (int)str.length() ) + return 0; + if ( str[p] != '&' ) { + TQChar c = str[p]; + if ( c.isPrint() ) { + char ltr = c.upper().latin1(); + if ( ltr >= (char)Key_A && ltr <= (char)Key_Z ) + c = ltr; + else + c = c.lower(); + return TQKeySequence( c.unicode() + ALT + UNICODE_ACCEL ); + } + } + p++; + } + return TQKeySequence(); +} + +/*! \obsolete + + Creates an accelerator string for the key \a k. + For instance CTRL+Key_O gives "Ctrl+O". The "Ctrl" etc. + are translated (using TQObject::tr()) in the "TQAccel" context. + + The function is superfluous. Cast the TQKeySequence \a k to a + TQString for the same effect. +*/ +TQString TQAccel::keyToString( TQKeySequence k ) +{ + return (TQString) k; +} + +/*!\obsolete + + Returns an accelerator code for the string \a s. For example + "Ctrl+O" gives CTRL+UNICODE_ACCEL+'O'. The strings "Ctrl", + "Shift", "Alt" are recognized, as well as their translated + equivalents in the "TQAccel" context (using TQObject::tr()). Returns 0 + if \a s is not recognized. + + This function is typically used with \link TQObject::tr() tr + \endlink(), so that accelerator keys can be replaced in + translations: + + \code + TQPopupMenu *file = new TQPopupMenu( this ); + file->insertItem( p1, tr("&Open..."), this, SLOT(open()), + TQAccel::stringToKey(tr("Ctrl+O", "File|Open")) ); + \endcode + + Notice the \c "File|Open" translator comment. It is by no means + necessary, but it provides some context for the human translator. + + + The function is superfluous. Construct a TQKeySequence from the + string \a s for the same effect. + + \sa TQObject::tr() + \link i18n.html Internationalization with TQt \endlink +*/ +TQKeySequence TQAccel::stringToKey( const TQString & s ) +{ + return TQKeySequence( s ); +} + + +/*! + Sets a What's This help text for the accelerator item \a id to \a + text. + + The text will be shown when the application is in What's This mode + and the user hits the accelerator key. + + To set What's This help on a menu item (with or without an + accelerator key), use TQMenuData::setWhatsThis(). + + \sa whatsThis(), TQWhatsThis::inWhatsThisMode(), + TQMenuData::setWhatsThis(), TQAction::setWhatsThis() +*/ +void TQAccel::setWhatsThis( int id, const TQString& text ) +{ + + TQAccelItem *item = find_id( d->aitems, id); + if ( item ) + item->whatsthis = text; +} + +/*! + Returns the What's This help text for the specified item \a id or + TQString::null if no text has been specified. + + \sa setWhatsThis() +*/ +TQString TQAccel::whatsThis( int id ) const +{ + + TQAccelItem *item = find_id( d->aitems, id); + return item? item->whatsthis : TQString::null; +} + +/*!\internal */ +void TQAccel::setIgnoreWhatsThis( bool b) +{ + d->ignorewhatsthis = b; +} + +/*!\internal */ +bool TQAccel::ignoreWhatsThis() const +{ + return d->ignorewhatsthis; +} + + +/*! + +\page accelerators.html + +\title Standard Accelerator Keys + +Applications invariably need to define accelerator keys for actions. +TQt fully supports accelerators, for example with \l TQAccel::shortcutKey(). + +Here are Microsoft's recommendations for accelerator keys, with +comments about the Open Group's recommendations where they exist +and differ. For most commands, the Open Group either has no advice or +agrees with Microsoft. + +The emboldened letter plus Alt is Microsoft's recommended choice, and +we recommend supporting it. For an Apply button, for example, we +recommend TQButton::setText( \link TQWidget::tr() tr \endlink("&Apply") ); + +If you have conflicting commands (e.g. About and Apply buttons in the +same dialog), you must decide for yourself. + +\list +\i <b><u>A</u></b>bout +\i Always on <b><u>T</u></b>op +\i <b><u>A</u></b>pply +\i <b><u>B</u></b>ack +\i <b><u>B</u></b>rowse +\i <b><u>C</u></b>lose (CDE: Alt+F4; Alt+F4 is "close window" in Windows) +\i <b><u>C</u></b>opy (CDE: Ctrl+C, Ctrl+Insert) +\i <b><u>C</u></b>opy Here +\i Create <b><u>S</u></b>hortcut +\i Create <b><u>S</u></b>hortcut Here +\i Cu<b><u>t</u></b> +\i <b><u>D</u></b>elete +\i <b><u>E</u></b>dit +\i <b><u>E</u></b>xit (CDE: E<b><u>x</u></b>it) +\i <b><u>E</u></b>xplore +\i <b><u>F</u></b>ile +\i <b><u>F</u></b>ind +\i <b><u>H</u></b>elp +\i Help <b><u>T</u></b>opics +\i <b><u>H</u></b>ide +\i <b><u>I</u></b>nsert +\i Insert <b><u>O</u></b>bject +\i <b><u>L</u></b>ink Here +\i Ma<b><u>x</u></b>imize +\i Mi<b><u>n</u></b>imize +\i <b><u>M</u></b>ove +\i <b><u>M</u></b>ove Here +\i <b><u>N</u></b>ew +\i <b><u>N</u></b>ext +\i <b><u>N</u></b>o +\i <b><u>O</u></b>pen +\i Open <b><u>W</u></b>ith +\i Page Set<b><u>u</u></b>p +\i <b><u>P</u></b>aste +\i Paste <b><u>L</u></b>ink +\i Paste <b><u>S</u></b>hortcut +\i Paste <b><u>S</u></b>pecial +\i <b><u>P</u></b>ause +\i <b><u>P</u></b>lay +\i <b><u>P</u></b>rint +\i <b><u>P</u></b>rint Here +\i P<b><u>r</u></b>operties +\i <b><u>Q</u></b>uick View +\i <b><u>R</u></b>edo (CDE: Ctrl+Y, Shift+Alt+Backspace) +\i <b><u>R</u></b>epeat +\i <b><u>R</u></b>estore +\i <b><u>R</u></b>esume +\i <b><u>R</u></b>etry +\i <b><u>R</u></b>un +\i <b><u>S</u></b>ave +\i Save <b><u>A</u></b>s +\i Select <b><u>A</u></b>ll +\i Se<b><u>n</u></b>d To +\i <b><u>S</u></b>how +\i <b><u>S</u></b>ize +\i S<b><u>p</u></b>lit +\i <b><u>S</u></b>top +\i <b><u>U</u></b>ndo (CDE: Ctrl+Z or Alt+Backspace) +\i <b><u>V</u></b>iew +\i <b><u>W</u></b>hat's This? +\i <b><u>W</u></b>indow +\i <b><u>Y</u></b>es +\endlist + +There are also a lot of other keys and actions (that use other +modifier keys than Alt). See the Microsoft and The Open Group +documentation for details. + +The \link http://www.amazon.com/exec/obidos/ASIN/0735605661/trolltech/t +Microsoft book \endlink has ISBN 0735605661. The corresponding Open Group +book is very hard to find, rather expensive and we cannot recommend +it. However, if you really want it, OGPubs@opengroup.org might be able +to help. Ask them for ISBN 1859121047. + +*/ + +/*! \obsolete serves no purpose anymore */ +void TQAccel::repairEventFilter() {} +/*! \obsolete serves no purpose anymore */ +bool TQAccel::eventFilter( TQObject *, TQEvent * ) { return FALSE; } +#endif // QT_NO_ACCEL |