Q3AccelManager Class Reference

Collaboration diagram for Q3AccelManager:

Collaboration graph
[legend]
List of all members.

Detailed Description

Definition at line 154 of file q3accel.cpp.

Public Member Functions

void registerAccel (Q3AccelPrivate *a)
void unregisterAccel (Q3AccelPrivate *a)
bool tryAccelEvent (QWidget *w, QKeyEvent *e)
bool dispatchAccelEvent (QWidget *w, QKeyEvent *e)
bool tryComposeUnicode (QWidget *w, QKeyEvent *e)

Static Public Member Functions

static Q3AccelManagerself ()

Private Member Functions

 Q3AccelManager ()
 ~Q3AccelManager ()
void setFuncPtr ()
bool correctSubWindow (QWidget *w, Q3AccelPrivate *d)
QKeySequence::SequenceMatch match (QKeyEvent *e, Q3AccelItem *item, QKeySequence &temp)
int translateModifiers (ButtonState state)

Private Attributes

Q3PtrList< Q3AccelPrivateaccels
QKeySequence::SequenceMatch currentState
QKeySequence intermediate
int clash
bool metaComposeUnicode
int composedUnicode

Static Private Attributes

static Q3AccelManagerself_ptr


Constructor & Destructor Documentation

Q3AccelManager::Q3AccelManager (  )  [inline, private]

Definition at line 164 of file q3accel.cpp.

References self_ptr, and setFuncPtr().

Here is the call graph for this function:

Q3AccelManager::~Q3AccelManager (  )  [inline, private]

Definition at line 167 of file q3accel.cpp.

References self_ptr.

00167 { self_ptr = 0; }


Member Function Documentation

static Q3AccelManager* Q3AccelManager::self (  )  [inline, static]

Definition at line 156 of file q3accel.cpp.

References self_ptr.

Referenced by Q3AccelPrivate::Q3AccelPrivate(), qt_dispatchAccelEvent(), qt_tryAccelEvent(), qt_tryComposeUnicode(), and Q3AccelPrivate::~Q3AccelPrivate().

00156 { return self_ptr ? self_ptr : new Q3AccelManager; }

void Q3AccelManager::registerAccel ( Q3AccelPrivate a  )  [inline]

Definition at line 157 of file q3accel.cpp.

References a, accels, and Q3PtrList< type >::append().

Referenced by Q3AccelPrivate::Q3AccelPrivate().

00157 { accels.append(a); }

Here is the call graph for this function:

void Q3AccelManager::unregisterAccel ( Q3AccelPrivate a  )  [inline]

Definition at line 158 of file q3accel.cpp.

References a, accels, Q3PtrList< type >::isEmpty(), and Q3PtrList< type >::removeRef().

Referenced by Q3AccelPrivate::~Q3AccelPrivate().

00158 { accels.removeRef(a); if (accels.isEmpty()) delete this; }

Here is the call graph for this function:

bool Q3AccelManager::tryAccelEvent ( QWidget w,
QKeyEvent e 
)

Definition at line 320 of file q3accel.cpp.

References currentState, QEvent::ignore(), QEvent::isAccepted(), QKeySequence::NoMatch, QCoreApplication::sendSpontaneousEvent(), QEvent::t, and w.

Referenced by qt_tryAccelEvent().

00321 {
00322     if (QKeySequence::NoMatch == currentState) {
00323         e->t = QEvent::AccelOverride;
00324         e->ignore();
00325         QApplication::sendSpontaneousEvent(w, e);
00326         if (e->isAccepted())
00327             return false;
00328     }
00329     e->t = QEvent::Accel;
00330     e->ignore();
00331     QApplication::sendSpontaneousEvent(w, e);
00332     return e->isAccepted();
00333 }

Here is the call graph for this function:

bool Q3AccelManager::dispatchAccelEvent ( QWidget w,
QKeyEvent e 
)

Definition at line 390 of file q3accel.cpp.

References accels, QEvent::accept(), Q3AccelPrivate::activate(), Q3AccelPrivate::activateAmbiguously(), Q3AccelPrivate::aitems, clash, QStatusBar::clearMessage(), correctSubWindow(), QKeySequence::count(), currentState, Q3AccelPrivate::enabled, Q3AccelItem::enabled, QKeySequence::encodeString(), Q3PtrList< type >::first(), intermediate, QKeyEvent::key(), Qt::Key_Alt, Qt::Key_Shift, Q3PtrList< type >::last(), match(), message, n, Q3PtrList< type >::next(), QKeySequence::NoMatch, Q3AccelPrivate::parent, QKeySequence::PartialMatch, Q3PtrList< type >::prev(), QObject::receivers(), QStatusBar::showMessage(), Q3AccelItem::signal, SIGNAL, QKeyEvent::text(), translateModifiers(), and w.

Referenced by qt_dispatchAccelEvent().

00391 {
00392 #ifndef QT_NO_STATUSBAR
00393     // Needs to be declared and used here because of "goto doclash"
00394     QStatusBar* mainStatusBar = 0;
00395 #endif
00396 
00397     // Modifiers can NOT be accelerators...
00398     if (e->key() >= Key_Shift &&
00399          e->key() <= Key_Alt)
00400          return false;
00401 
00402     QKeySequence::SequenceMatch result = QKeySequence::NoMatch;
00403     QKeySequence tocheck, partial;
00404     Q3AccelPrivate* accel = 0;
00405     Q3AccelItem* item = 0;
00406     Q3AccelPrivate* firstaccel = 0;
00407     Q3AccelItem* firstitem = 0;
00408     Q3AccelPrivate* lastaccel = 0;
00409     Q3AccelItem* lastitem = 0;
00410 
00411     QKeyEvent pe = *e;
00412     int n = -1;
00413     int hasShift = (e->state()&Qt::ShiftButton)?1:0;
00414     bool identicalDisabled = false;
00415     bool matchFound = false;
00416     do {
00417         accel = accels.first();
00418         matchFound = false;
00419         while (accel) {
00420             if (correctSubWindow(w, accel)) {
00421                 if (accel->enabled) {
00422                     item = accel->aitems.last();
00423                     while(item) {
00424                         if (QKeySequence::Identical == (result = match(&pe, item, tocheck))) {
00425                             if (item->enabled) {
00426                                 if (!firstaccel) {
00427                                     firstaccel = accel;
00428                                     firstitem = item;
00429                                 }
00430                                 lastaccel = accel;
00431                                 lastitem = item;
00432                                 n++;
00433                                 matchFound = true;
00434                                 if (n > QMAX(clash,0))
00435                                     goto doclash;
00436                             } else {
00437                                 identicalDisabled = true;
00438                             }
00439                         }
00440                         if (item->enabled && QKeySequence::PartialMatch == result) {
00441                             partial = tocheck;
00442                             matchFound = true;
00443                         }
00444                         item = accel->aitems.prev();
00445                     }
00446                 } else {
00447                     item = accel->aitems.last();
00448                     while(item) {
00449                         if (QKeySequence::Identical == match(&pe, item, tocheck))
00450                             identicalDisabled = true;
00451                         item = accel->aitems.prev();
00452                     }
00453                 }
00454             }
00455             accel = accels.next();
00456         }
00457         pe = QKeyEvent(QEvent::Accel, pe.key(), pe.ascii(), pe.state()&~Qt::ShiftButton, pe.text());
00458     } while (hasShift-- && !matchFound && !identicalDisabled);
00459 
00460 #ifndef QT_NO_STATUSBAR
00461     mainStatusBar = (QStatusBar*) w->window()->child(0, "QStatusBar");
00462 #endif
00463     if (n < 0) { // no match found
00464         currentState = partial.count() ? QKeySequence::PartialMatch : QKeySequence::NoMatch;
00465 #ifndef QT_NO_STATUSBAR
00466         // Only display message if we are, or were, in a partial match
00467         if (mainStatusBar && (QKeySequence::PartialMatch == currentState || intermediate.count())) {
00468             if (currentState == QKeySequence::PartialMatch) {
00469                 mainStatusBar->showMessage((QString)partial + ", ...");
00470             } else if (!identicalDisabled) {
00471                 QString message = Q3Accel::tr("%1, %2 not defined").
00472                     arg((QString)intermediate).
00473                     arg(QKeySequence::encodeString(e->key() | translateModifiers(e->state())));
00474                 mainStatusBar->showMessage(message, 2000);
00475                 // Since we're a NoMatch, reset the clash count
00476                 clash = -1;
00477             } else {
00478               mainStatusBar->clearMessage();
00479             }
00480         }
00481 #endif
00482 
00483         bool eatKey = (QKeySequence::PartialMatch == currentState || intermediate.count());
00484         intermediate = partial;
00485         if (eatKey)
00486             e->accept();
00487         return eatKey;
00488     } else if (n == 0) { // found exactly one match
00489         clash = -1; // reset
00490 #ifndef QT_NO_STATUSBAR
00491         if (currentState == QKeySequence::PartialMatch && mainStatusBar)
00492                 mainStatusBar->clearMessage();
00493 #endif
00494         currentState = QKeySequence::NoMatch; // Free sequence keylock
00495         intermediate = QKeySequence();
00496         lastaccel->activate(lastitem);
00497         e->accept();
00498         return true;
00499     }
00500 
00501  doclash: // found more than one match
00502 #ifndef QT_NO_STATUSBAR
00503     if (!mainStatusBar) // if "goto doclash", we need to get statusbar again.
00504         mainStatusBar = (QStatusBar*) w->window()->child(0, "QStatusBar");
00505 #endif
00506 
00507     QString message = Q3Accel::tr("Ambiguous %1 not handled").arg((QString)tocheck);
00508     if (clash >= 0 && n > clash) { // pick next  match
00509         intermediate = QKeySequence();
00510         currentState = QKeySequence::NoMatch; // Free sequence keylock
00511         clash++;
00512 #ifndef QT_NO_STATUSBAR
00513         if (mainStatusBar &&
00514              !lastitem->signal &&
00515              !(lastaccel->parent->receivers(SIGNAL(activatedAmbiguously(int)))))
00516             mainStatusBar->showMessage(message, 2000);
00517 #endif
00518         lastaccel->activateAmbiguously(lastitem);
00519     } else { // start (or wrap) with the first matching
00520         intermediate = QKeySequence();
00521         currentState = QKeySequence::NoMatch; // Free sequence keylock
00522         clash = 0;
00523 #ifndef QT_NO_STATUSBAR
00524         if (mainStatusBar &&
00525              !firstitem->signal &&
00526              !(firstaccel->parent->receivers(SIGNAL(activatedAmbiguously(int)))))
00527             mainStatusBar->showMessage(message, 2000);
00528 #endif
00529         firstaccel->activateAmbiguously(firstitem);
00530     }
00531     e->accept();
00532     return true;
00533 }

Here is the call graph for this function:

bool Q3AccelManager::tryComposeUnicode ( QWidget w,
QKeyEvent e 
)

Definition at line 335 of file q3accel.cpp.

References QEvent::accept(), QChar::cell(), composedUnicode, QKeyEvent::key(), Qt::Key_0, Qt::Key_Meta, QEvent::KeyPress, QEvent::KeyRelease, metaComposeUnicode, QChar::row(), s, QCoreApplication::sendEvent(), QEvent::type(), value, and w.

Referenced by qt_tryComposeUnicode().

00336 {
00337     if (metaComposeUnicode) {
00338         int value = e->key() - Key_0;
00339         // Ignore acceloverrides so we don't trigger
00340         // accels on keypad when Meta compose is on
00341         if ((e->type() == QEvent::AccelOverride) &&
00342              (e->state() == Qt::Keypad + Qt::MetaButton)) {
00343             e->accept();
00344         // Meta compose start/continue
00345         } else if ((e->type() == QEvent::KeyPress) &&
00346              (e->state() == Qt::Keypad + Qt::MetaButton)) {
00347             if (value >= 0 && value <= 9) {
00348                 composedUnicode *= 10;
00349                 composedUnicode += value;
00350                 return true;
00351             } else {
00352                 // Composing interrupted, dispatch!
00353                 if (composedUnicode) {
00354                     QChar ch(composedUnicode);
00355                     QString s(ch);
00356                     QKeyEvent kep(QEvent::KeyPress, 0, ch.row() ? 0 : ch.cell(), 0, s);
00357                     QKeyEvent ker(QEvent::KeyRelease, 0, ch.row() ? 0 : ch.cell(), 0, s);
00358                     QApplication::sendEvent(w, &kep);
00359                     QApplication::sendEvent(w, &ker);
00360                 }
00361                 composedUnicode = 0;
00362                 return true;
00363             }
00364         // Meta compose end, dispatch
00365         } else if ((e->type() == QEvent::KeyRelease) &&
00366                     (e->key() == Key_Meta) &&
00367                     (composedUnicode != 0)) {
00368             if ((composedUnicode > 0) &&
00369                  (composedUnicode < 0xFFFE)) {
00370                 QChar ch(composedUnicode);
00371                 QString s(ch);
00372                 QKeyEvent kep(QEvent::KeyPress, 0, ch.row() ? 0 : ch.cell(), 0, s);
00373                 QKeyEvent ker(QEvent::KeyRelease, 0, ch.row() ? 0 : ch.cell(), 0, s);
00374                 QApplication::sendEvent(w, &kep);
00375                 QApplication::sendEvent(w, &ker);
00376             }
00377             composedUnicode = 0;
00378             return true;
00379         }
00380     }
00381     return false;
00382 }

Here is the call graph for this function:

void Q3AccelManager::setFuncPtr (  )  [private]

Definition at line 196 of file q3accel.cpp.

References data, qApp, qt_dispatchAccelEvent(), qt_tryAccelEvent(), and qt_tryComposeUnicode().

Referenced by Q3AccelManager().

00196                                 {
00197     if (qApp->d_func()->qt_compat_used)
00198         return;
00199     QApplicationPrivate *data = static_cast<QApplicationPrivate*>(qApp->d_ptr);
00200     data->qt_tryAccelEvent = qt_tryAccelEvent;
00201     data->qt_tryComposeUnicode = qt_tryComposeUnicode;
00202     data->qt_dispatchAccelEvent = qt_dispatchAccelEvent;
00203     data->qt_compat_used = true;
00204 }

Here is the call graph for this function:

bool Q3AccelManager::correctSubWindow ( QWidget w,
Q3AccelPrivate d 
) [private]

Definition at line 217 of file q3accel.cpp.

References d, Qt::Dialog, QWidget::parentWidget(), Qt::SubWindow, w, QWidget::window(), and QWidget::windowType().

Referenced by dispatchAccelEvent().

00217                                                                    {
00218 #if !defined (Q_OS_MACX)
00219      if (!d->watch || !d->watch->isVisible() || !d->watch->isEnabled())
00220 #else
00221     if (!d->watch || (!d->watch->isVisible() && !d->watch->inherits("QMenuBar")) || !d->watch->isEnabled())
00222 #endif
00223         return false;
00224     QWidget* tlw = w->window();
00225     QWidget* wtlw = d->watch->window();
00226 
00227     /* if we live in a floating dock window, keep our parent's
00228      * accelerators working */
00229 #ifndef QT_NO_MAINWINDOW
00230     if ((tlw->windowType() == Qt::Dialog) && tlw->parentWidget() && ::qobject_cast<QDockWidget*>(tlw))
00231         return tlw->parentWidget()->window() == wtlw;
00232 
00233     if (wtlw  != tlw)
00234         return false;
00235 #endif
00236     /* if we live in a MDI subwindow, ignore the event if we are
00237        not the active document window */
00238     QWidget* sw = d->watch;
00239     while (sw && sw->windowType() != Qt::SubWindow)
00240         sw = sw->parentWidget(true);
00241     if (sw)  { // we are in a subwindow indeed
00242         QWidget* fw = w;
00243         while (fw && fw != sw)
00244             fw = fw->parentWidget(true);
00245         if (fw != sw) // focus widget not in our subwindow
00246             return false;
00247     }
00248     return true;
00249 }

Here is the call graph for this function:

QKeySequence::SequenceMatch Q3AccelManager::match ( QKeyEvent e,
Q3AccelItem item,
QKeySequence temp 
) [private]

Definition at line 272 of file q3accel.cpp.

References QKeySequence::count(), index, intermediate, QString::isEmpty(), QKeyEvent::key(), key, Q3AccelItem::key, Qt::Key_Tab, Qt::Key_unknown, QKeySequence::matches(), Qt::MODIFIER_MASK, QKeySequence::NoMatch, QKeySequence::setKey(), Qt::SHIFT, QKeyEvent::text(), translateModifiers(), QString::unicode(), and Qt::UNICODE_ACCEL.

Referenced by dispatchAccelEvent().

00273 {
00274     QKeySequence::SequenceMatch result = QKeySequence::NoMatch;
00275     int index = intermediate.count();
00276     temp = intermediate;
00277 
00278     int modifier = translateModifiers(e->state());
00279 
00280     if (e->key() && e->key() != Key_unknown) {
00281         int key = e->key()  | modifier;
00282         if (e->key() == Key_BackTab) {
00283             /*
00284             In QApplication, we map shift+tab to shift+backtab.
00285             This code here reverts the mapping in a way that keeps
00286             backtab and shift+tab accelerators working, in that
00287             order, meaning backtab has priority.*/
00288             key &= ~SHIFT;
00289 
00290             temp.setKey(key, index);
00291             if (QKeySequence::NoMatch != (result = temp.matches(item->key)))
00292                 return result;
00293             if (e->state() & ShiftButton)
00294                 key |= SHIFT;
00295             key = Key_Tab | (key & MODIFIER_MASK);
00296             temp.setKey(key, index);
00297             if (QKeySequence::NoMatch != (result = temp.matches(item->key)))
00298                 return result;
00299         } else {
00300             temp.setKey(key, index);
00301             if (QKeySequence::NoMatch != (result = temp.matches(item->key)))
00302                 return result;
00303         }
00304 
00305         if (key == Key_BackTab) {
00306             if (e->state() & ShiftButton)
00307                 key |= SHIFT;
00308             temp.setKey(key, index);
00309             if (QKeySequence::NoMatch != (result = temp.matches(item->key)))
00310                 return result;
00311         }
00312     }
00313     if (!e->text().isEmpty()) {
00314         temp.setKey((int)e->text()[0].unicode() | UNICODE_ACCEL | modifier, index);
00315         result = temp.matches(item->key);
00316     }
00317     return result;
00318 }

Here is the call graph for this function:

int Q3AccelManager::translateModifiers ( ButtonState  state  )  [inline, private]

Definition at line 251 of file q3accel.cpp.

References Qt::ALT, Qt::CTRL, Qt::META, and Qt::SHIFT.

Referenced by dispatchAccelEvent(), and match().

00252 {
00253     int result = 0;
00254     if (state & ShiftButton)
00255         result |= SHIFT;
00256     if (state & ControlButton)
00257         result |= CTRL;
00258     if (state & MetaButton)
00259         result |= META;
00260     if (state & AltButton)
00261         result |= ALT;
00262     return result;
00263 }


Member Data Documentation

Q3PtrList<Q3AccelPrivate> Q3AccelManager::accels [private]

Definition at line 174 of file q3accel.cpp.

Referenced by dispatchAccelEvent(), registerAccel(), and unregisterAccel().

Q3AccelManager * Q3AccelManager::self_ptr [static, private]

Definition at line 175 of file q3accel.cpp.

Referenced by Q3AccelManager(), self(), and ~Q3AccelManager().

QKeySequence::SequenceMatch Q3AccelManager::currentState [private]

Definition at line 176 of file q3accel.cpp.

Referenced by dispatchAccelEvent(), and tryAccelEvent().

QKeySequence Q3AccelManager::intermediate [private]

Definition at line 177 of file q3accel.cpp.

Referenced by dispatchAccelEvent(), and match().

int Q3AccelManager::clash [private]

Definition at line 178 of file q3accel.cpp.

Referenced by dispatchAccelEvent().

bool Q3AccelManager::metaComposeUnicode [private]

Definition at line 179 of file q3accel.cpp.

Referenced by tryComposeUnicode().

int Q3AccelManager::composedUnicode [private]

Definition at line 180 of file q3accel.cpp.

Referenced by tryComposeUnicode().


The documentation for this class was generated from the following file:
Generated on Thu Mar 15 15:39:25 2007 for Qt 4.2 User's Guide by  doxygen 1.5.1