F:/KPlato/koffice/libs/kofficecore/kkbdaccessextensions.cpp

Aller à la documentation de ce fichier.
00001 /* This file is part of the KDE project
00002    Copyright (C) 2005, Gary Cramblitt <garycramblitt@comcast.net>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017    Boston, MA 02110-1301, USA.
00018 */
00019 
00020 // Qt includes
00021 #include <QSplitter>
00022 #include <q3dockwindow.h>
00023 #include <q3dockarea.h>
00024 #include <QEvent>
00025 #include <QCursor>
00026 #include <QObject>
00027 #include <QWidget>
00028 #include <QLabel>
00029 #include <QToolTip>
00030 #include <kxmlguifactory.h>
00031 //Added by qt3to4:
00032 #include <Q3PtrList>
00033 #include <QKeyEvent>
00034 #include <QFrame>
00035 #include <Q3ValueList>
00036 #include <QMouseEvent>
00037 
00038 // KDE includes
00039 #include <klocale.h>
00040 #include <kglobal.h>
00041 #include <kapplication.h>
00042 #include <kmainwindow.h>
00043 #include <kaction.h>
00044 #include <kdebug.h>
00045 #include <q3tl.h>
00046 #include <kactioncollection.h>
00047 
00048 // KKbdAccessExtensions includes
00049 #include "kkbdaccessextensions.h"
00050 // TODO: See eventFilter method.
00051 //#include "kkbdaccessextensions.moc"
00052 
00053 class KPanelKbdSizerIcon : public QCursor
00054 {
00055     public:
00056         KPanelKbdSizerIcon() :
00057             QCursor(Qt::SizeAllCursor),
00058             isActive(false)
00059         {
00060             currentPos = QPoint(-1, -1);
00061         }
00062 
00063         ~KPanelKbdSizerIcon()
00064         {
00065             hide();
00066         }
00067 
00068         void show(const QPoint p) {
00069             if (!isActive) {
00070                 originalPos = QCursor::pos();
00071                 kapp->setOverrideCursor(*this);
00072                 isActive = true;
00073             }
00074             if (p != pos())
00075                 setPos(p);
00076             currentPos = p;
00077         }
00078 
00079         void hide() {
00080             if (isActive) {
00081                 kapp->restoreOverrideCursor();
00082                 QCursor::setPos(originalPos);
00083             }
00084             isActive = false;
00085         }
00086 
00087         void setShape(Qt::CursorShape shayp)
00088         {
00089             if (shayp != shape()) {
00090                 // Must restore and override to get the icon to refresh.
00091                 if (isActive) kapp->restoreOverrideCursor();
00092                 QCursor::setShape(shayp);
00093                 if (isActive) kapp->setOverrideCursor(*this);
00094             }
00095         }
00096 
00097         // Return the difference between a position and where icon is supposed to be.
00098         QSize delta(const QPoint p)
00099         {
00100             QPoint d = p - currentPos;
00101             return QSize(d.x(), d.y());
00102         }
00103 
00104         // Return the difference between where the icon is currently positioned and where
00105         // it is supposed to be.
00106         QSize delta() { return delta(pos()); }
00107 
00108         // True if the sizing icon is visible.
00109         bool isActive;
00110 
00111     private:
00112         // Icon's current position.
00113         QPoint currentPos;
00114         // Mouse cursor's original position when icon is shown.
00115         QPoint originalPos;
00116 };
00117 
00118 class KKbdAccessExtensionsPrivate
00119 {
00120     public:
00121         KKbdAccessExtensionsPrivate() :
00122             fwdAction(0),
00123             revAction(0),
00124             accessKeysAction(0),
00125             panel(0),
00126             handleNdx(0),
00127             icon(0),
00128             stepSize(10),
00129             accessKeyLabels(0) {};
00130 
00131         ~KKbdAccessExtensionsPrivate()
00132         {
00133             delete icon;
00134             // TODO: This crashes, but should delete in the event that KMainWindow is not deleted.
00135             if (accessKeyLabels) {
00136                 accessKeyLabels->setAutoDelete(false);
00137                 delete accessKeyLabels;
00138             }
00139         }
00140 
00141         // Action that starts panel sizing (defaults to F8), forward and reverse;
00142         KAction* fwdAction;
00143         KAction* revAction;
00144 
00145         // Action that starts access keys.
00146         KAction* accessKeysAction;
00147 
00148         // The splitter or dockwindow currently being sized.  If 0, sizing is not in progress.
00149         QWidget* panel;
00150 
00151         // Index of current handle of the panel.  When panel is a QDockWindow:
00152         //      1 = size horizontally
00153         //      2 = size vertically
00154         int handleNdx;
00155 
00156         // Sizing icon.
00157         KPanelKbdSizerIcon* icon;
00158 
00159         // Sizing increment.
00160         int stepSize;
00161 
00162         // List of the access key QLabels.  If not 0, access keys are onscreen.
00163         Q3PtrList<QLabel>* accessKeyLabels;
00164 
00165         // Pointer to the KMainWindow.
00166         KMainWindow* mainWindow;
00167 };
00168 
00169 KKbdAccessExtensions::KKbdAccessExtensions(KMainWindow* parent, const char* /*name*/) :
00170     QObject( parent )
00171 {
00172     // kDebug() << "KKbdAccessExtensions::KKbdAccessExtensions: running." << endl;
00173     d = new KKbdAccessExtensionsPrivate;
00174     d->mainWindow = parent;
00175     d->fwdAction = new KAction(i18n("Resize Panel Forward"),
00176                                parent->actionCollection(), "resize_panel_forward");
00177     d->fwdAction->setShortcut(KShortcut("F8"));
00178     d->revAction = new KAction(i18n("Resize Panel Reverse"),
00179                                parent->actionCollection(), "resize_panel_reverse");
00180     d->revAction->setShortcut(KShortcut("Shift+F8"));
00181     d->accessKeysAction = new KAction(i18n("Access Keys"),
00182                                       parent->actionCollection(), "access_keys");
00183     d->accessKeysAction->setShortcut(KShortcut("Alt+F8"));
00184     // "Disable" the shortcuts so we can see them in eventFilter.
00185     d->fwdAction->setEnabled(false);
00186     d->revAction->setEnabled(false);
00187     d->accessKeysAction->setEnabled(false);
00188     d->icon = new KPanelKbdSizerIcon();
00189     kapp->installEventFilter(this);
00190 }
00191 
00192 KKbdAccessExtensions::~KKbdAccessExtensions()
00193 {
00194     kapp->removeEventFilter(this);
00195     if (d->panel) exitSizing();
00196     delete d;
00197 }
00198 
00199 int KKbdAccessExtensions::stepSize() const { return d->stepSize; }
00200 
00201 void KKbdAccessExtensions::setStepSize(int s) { d->stepSize = s; }
00202 
00203 bool KKbdAccessExtensions::eventFilter( QObject *o, QEvent *e )
00204 {
00205     if ( e->type() == QEvent::KeyPress ) {
00206         // TODO: This permits only a single-key shortcut.  For example, Alt+S,R would not work.
00207         // If user configures a multi-key shortcut, it is undefined what will happen here.
00208         // It would be better to handle these as KShortcut activate() signals, but the problem
00209         // is that once a QDockWindow is undocked and has focus, the KShortcut activate() signals
00210         // don't fire anymore.
00211         KShortcut fwdSc = d->fwdAction->shortcut();
00212         KShortcut revSc = d->revAction->shortcut();
00213         KShortcut accessKeysSc = d->accessKeysAction->shortcut();
00214         QKeyEvent* kev = static_cast<QKeyEvent *>(e);
00215         KShortcut sc = KShortcut(kev->key());
00216         // kDebug() << "KKbdAccessExtensions::eventFilter: Key press " << sc << endl;
00217         if (!d->accessKeyLabels) {
00218             if (sc == fwdSc) {
00219                 nextHandle();
00220                 return true;
00221             }
00222             if (sc == revSc) {
00223                 prevHandle();
00224                 return true;
00225             }
00226         }
00227         if (d->panel) {
00228             if (kev->key() == Qt::Key_Escape)
00229                 exitSizing();
00230             else
00231                 resizePanelFromKey( kev->key(), kev->modifiers() );
00232             // Eat the key.
00233             return true;
00234         }
00235         if (sc == accessKeysSc && !d->panel) {
00236             if (d->accessKeyLabels) {
00237                 delete d->accessKeyLabels;
00238                 d->accessKeyLabels = 0;
00239             } else
00240                 displayAccessKeys();
00241             return true;
00242         }
00243         if (d->accessKeyLabels) {
00244             if (kev->key() == Qt::Key_Escape) {
00245                 delete d->accessKeyLabels;
00246                 d->accessKeyLabels = 0;
00247             } else
00248                 handleAccessKey(kev);
00249             return true;
00250         }
00251         return false;
00252     }
00253     else if (d->icon->isActive && e->type() == QEvent::MouseButtonPress) {
00254         exitSizing();
00255         return true;
00256     }
00257     else if (d->accessKeyLabels && e->type() == QEvent::MouseButtonPress) {
00258         delete d->accessKeyLabels;
00259         d->accessKeyLabels = 0;
00260         return true;
00261     }
00262 /*    else if (e->type() == QEvent::MouseMove && d->icon->isActive) {
00263         // Lock mouse cursor down.
00264         showIcon();
00265         dynamic_cast<QMouseEvent *>(e)->accept();
00266         return true;
00267     }*/
00268     else if (e->type() == QEvent::MouseMove && d->icon->isActive && d->panel) {
00269         // Resize according to mouse movement.
00270         QMouseEvent* me = static_cast<QMouseEvent *>(e);
00271         QSize s = d->icon->delta();
00272         int dx = s.width();
00273         int dy = s.height();
00274         resizePanel( dx, dy, me->button() );
00275         me->accept();
00276         showIcon();
00277         return true;
00278     }
00279     else if (e->type() == QEvent::Resize && d->panel && o == d->panel) {
00280         // TODO: This doesn't always work.
00281         showIcon();
00282     }
00283     return false;
00284 }
00285 
00286 QWidgetList* KKbdAccessExtensions::getAllPanels()
00287 {
00288     QWidgetList allWidgets = kapp->allWidgets();
00289     QWidgetList* allPanels = new QWidgetList;
00290     foreach ( QWidget* widget, allWidgets ) {
00291         if (widget->isVisible()) {
00292             if (qobject_cast<QSplitter*>( widget )) {
00293                 // Only size QSplitters with at least two handles (there is always one hidden).
00294                 if (dynamic_cast<QSplitter *>(widget)->sizes().count() >= 2)
00295                     allPanels->append(widget);
00296             } else if (qobject_cast<Q3DockWindow*>( widget )) {
00297                 if (dynamic_cast<Q3DockWindow *>(widget)->isResizeEnabled()) {
00298                     // kDebug() << "KKbdAccessExtensions::getAllPanels: QDockWindow = " << widget->name() << endl;
00299                     allPanels->append(widget);
00300                 }
00301             }
00302         }
00303     }
00304     return allPanels;
00305 }
00306 
00307 void KKbdAccessExtensions::nextHandle()
00308 {
00309     QWidget* panel = d->panel;
00310     // See if current panel has another handle.  If not, find next panel.
00311     if (panel) {
00312         bool advance = true;
00313         d->handleNdx++;
00314         if (qobject_cast<QSplitter*>( panel ))
00315             advance = (d->handleNdx >= dynamic_cast<QSplitter *>(panel)->sizes().count());
00316         else
00317             // Undocked windows have only one "handle" (center).
00318             advance = (d->handleNdx > 2 || !dynamic_cast<Q3DockWindow *>(panel)->area());
00319         if (advance) {
00320             QWidgetList* allWidgets = getAllPanels();
00321             int index = allWidgets->indexOf(panel);
00322             panel = 0;
00323             if (index > -1)
00324                 panel = allWidgets->at(index+1);
00325             delete allWidgets;
00326             d->handleNdx = 1;
00327         }
00328     } else {
00329         // Find first panel.
00330         QWidgetList* allWidgets = getAllPanels();
00331         panel = allWidgets->first();
00332         delete allWidgets;
00333         d->handleNdx = 1;
00334     }
00335     d->panel = panel;
00336     if (panel)
00337         showIcon();
00338     else
00339         exitSizing();
00340 }
00341 
00342 void KKbdAccessExtensions::prevHandle()
00343 {
00344     QWidget* panel = d->panel;
00345     // See if current panel has another handle.  If not, find previous panel.
00346     if (panel) {
00347         bool rewind = true;
00348         d->handleNdx--;
00349         rewind = (d->handleNdx < 1);
00350         if (rewind) {
00351             QWidgetList* allWidgets = getAllPanels();
00352             int index = allWidgets->indexOf(panel);
00353             panel = 0;
00354             if (index > 0)
00355                 panel = allWidgets->at(index-1);
00356             delete allWidgets;
00357             if (panel) {
00358                 if (qobject_cast<QSplitter*>( panel ))
00359                     d->handleNdx = dynamic_cast<QSplitter *>(panel)->sizes().count() - 1;
00360                 else {
00361                     if (dynamic_cast<Q3DockWindow *>(panel)->area())
00362                         d->handleNdx = 2;
00363                     else
00364                         d->handleNdx = 1;
00365                 }
00366             }
00367         }
00368     } else {
00369         // Find last panel.
00370         QWidgetList* allWidgets = getAllPanels();
00371         panel = allWidgets->last();
00372         delete allWidgets;
00373         if (panel) {
00374             if (qobject_cast<QSplitter*>( panel ))
00375                 d->handleNdx = dynamic_cast<QSplitter *>(panel)->sizes().count() - 1;
00376             else {
00377                 if (dynamic_cast<Q3DockWindow *>(panel)->area())
00378                     d->handleNdx = 2;
00379                 else
00380                     d->handleNdx = 1;
00381             }
00382         }
00383     }
00384     d->panel = panel;
00385     if (panel)
00386         showIcon();
00387     else
00388         exitSizing();
00389 }
00390 
00391 void KKbdAccessExtensions::exitSizing()
00392 {
00393     // kDebug() << "KKbdAccessExtensions::exiting sizing mode." << endl;
00394     hideIcon();
00395     d->handleNdx = 0;
00396     d->panel = 0;
00397 }
00398 
00399 void KKbdAccessExtensions::showIcon()
00400 {
00401     if (!d->panel) return;
00402     QPoint p;
00403     // kDebug() << "KKbdAccessExtensions::showIcon: topLevelWidget = " << d->panel->topLevelWidget()->name() << endl;
00404     QSplitter* splitter = qobject_cast<QSplitter *>(d->panel);
00405     if (splitter) {
00406         int handleNdx = d->handleNdx - 1;
00407         Q3ValueList<int> sizes = splitter->sizes();
00408         // kDebug() << "KKbdAccessExtensions::showIcon: sizes = " << sizes << endl;
00409         if (splitter->orientation() == Qt::Horizontal) {
00410             d->icon->setShape(Qt::SizeHorCursor);
00411             p.setX(sizes[handleNdx] + (splitter->handleWidth() / 2));
00412             p.setY(splitter->height() / 2);
00413         } else {
00414             d->icon->setShape(Qt::SizeVerCursor);
00415             p.setX(splitter->width() / 2);
00416             p.setY(sizes[handleNdx] + (splitter->handleWidth() / 2));
00417         }
00418         // kDebug() << "KKbdAccessExtensions::showIcon: p = " << p << endl;
00419         p = splitter->mapToGlobal(p);
00420         // kDebug() << "KKbdAccessExtensions::showIcon: mapToGlobal = " << p << endl;
00421     } else {
00422         Q3DockWindow* dockWindow = qobject_cast<Q3DockWindow *>(d->panel);
00423         if (!dockWindow) // assert
00424             return;
00425 
00426         p = dockWindow->pos();
00427         if (dockWindow->area()) {
00428             // kDebug() << "KKbdAccessExtensions::showIcon: pos = " << p << " of window = " << dockWindow->parentWidget()->name() << endl;
00429             p = dockWindow->parentWidget()->mapTo(dockWindow->topLevelWidget(), p);
00430             // kDebug() << "KKbdAccessExtensions::showIcon: mapTo = " << p << " of window = " << dockWindow->topLevelWidget()->name() << endl;
00431             // TODO: How to get the handle width?
00432             if (d->handleNdx == 1) {
00433                 d->icon->setShape(Qt::SizeHorCursor);
00434                 if (dockWindow->area()->orientation() == Qt::Vertical) {
00435                     if (dockWindow->area()->handlePosition() == Q3DockArea::Normal)
00436                         // Handle is to the right of the dock window.
00437                         p.setX(p.x() + dockWindow->width());
00438                         // else Handle is to the left of the dock window.
00439                 } else
00440                     // Handle is to the right of the dock window.
00441                     p.setX(p.x() + dockWindow->width());
00442                 p.setY(p.y() + (dockWindow->height() / 2));
00443             } else {
00444                 d->icon->setShape(Qt::SizeVerCursor);
00445                 p.setX(p.x() + (dockWindow->width() / 2));
00446                 if (dockWindow->area()->orientation() == Qt::Vertical)
00447                     // Handle is below the dock window.
00448                     p.setY(p.y() + dockWindow->height());
00449                 else {
00450                     if (dockWindow->area()->handlePosition() == Q3DockArea::Normal)
00451                         // Handle is below the dock window.
00452                         p.setY(p.y() + dockWindow->height());
00453                         // else Handle is above the dock window.
00454                 }
00455             }
00456             p = dockWindow->topLevelWidget()->mapToGlobal(p);
00457         } else {
00458             d->icon->setShape(Qt::SizeAllCursor);
00459             p = QPoint(dockWindow->width() / 2, dockWindow->height() / 2);
00460             p = dockWindow->mapToGlobal(p);       // Undocked.  Position in center of window.
00461         }
00462     }
00463     // kDebug() << "KKbdAccessExtensions::showIcon: show(p) = " << p << endl;
00464     d->icon->show(p);
00465 }
00466 
00467 void KKbdAccessExtensions::hideIcon()
00468 {
00469     d->icon->hide();
00470 }
00471 
00472 void KKbdAccessExtensions::resizePanel(int dx, int dy, int state)
00473 {
00474     int adj = dx + dy;
00475     if (adj == 0) return;
00476     // kDebug() << "KKbdAccessExtensions::resizePanel: panel = " << d->panel->name() << endl;
00477     QSplitter* splitter = qobject_cast<QSplitter*>( d->panel );
00478     if (splitter) {
00479         int handleNdx = d->handleNdx - 1;
00480         Q3ValueList<int> sizes = splitter->sizes();
00481         // kDebug() << "KKbdAccessExtensions::resizePanel: before sizes = " << sizes << endl;
00482         sizes[handleNdx] = sizes[handleNdx] + adj;
00483         // kDebug() << "KKbdAccessExtensions::resizePanel: setSizes = " << sizes << endl;
00484         splitter->setSizes(sizes);
00485         QApplication::postEvent(splitter, new QEvent(QEvent::LayoutRequest));
00486     } else {
00487         // TODO: How to get the handle width?
00488         Q3DockWindow* dockWindow = qobject_cast<Q3DockWindow *>(d->panel);
00489         if (!dockWindow)
00490             return;
00491 
00492         if (dockWindow->area()) {
00493             // kDebug() << "KKbdAccessExtensions::resizePanel: fixedExtent = " << dockWindow->fixedExtent() << endl;
00494             QSize fe = dockWindow->fixedExtent();
00495             if (d->handleNdx == 1) {
00496                 // When vertically oriented and dock area is on right side of screen, pressing
00497                 // left arrow increases size.
00498                 if (dockWindow->area()->orientation() == Qt::Vertical &&
00499                     dockWindow->area()->handlePosition() == Q3DockArea::Reverse) adj = -adj;
00500                 int w = fe.width();
00501                 if (w < 0) w = dockWindow->width();
00502                 w = w + adj;
00503                 if (w > 0 ) dockWindow->setFixedExtentWidth(w);
00504             } else {
00505                 // When horizontally oriented and dock area is at bottom of screen,
00506                 // pressing up arrow increases size.
00507                 if (dockWindow->area()->orientation() == Qt::Horizontal &&
00508                     dockWindow->area()->handlePosition() == Q3DockArea::Reverse) adj = -adj;
00509                 int h = fe.height();
00510                 if (h < 0) h = dockWindow->height();
00511                 h = h + adj;
00512                 if (h > 0) dockWindow->setFixedExtentHeight(h);
00513             }
00514             dockWindow->updateGeometry();
00515             QApplication::postEvent(dockWindow->area(), new QEvent(QEvent::LayoutRequest));
00516             // kDebug() << "KKbdAccessExtensions::resizePanel: fixedExtent = " << dockWindow->fixedExtent() << endl;
00517         } else {
00518             if (state == Qt::ShiftModifier) {
00519                 QSize s = dockWindow->size();
00520                 s.setWidth(s.width() + dx);
00521                 s.setHeight(s.height() + dy);
00522                 dockWindow->resize(s);
00523             } else {
00524                 QPoint p = dockWindow->pos();
00525                 p.setX(p.x() + dx);
00526                 p.setY(p.y() + dy);
00527                 dockWindow->move(p);
00528             }
00529         }
00530     }
00531 }
00532 
00533 void KKbdAccessExtensions::resizePanelFromKey(int key, int state)
00534 {
00535     // kDebug() << "KPanelKdbSizer::resizePanelFromKey: key = " << key << " state = " << state << endl;
00536     if (!d->panel) return;
00537     int dx = 0;
00538     int dy = 0;
00539     int stepSize = d->stepSize;
00540     switch (key) {
00541         case Qt::Key_Left:      dx = -stepSize;     break;
00542         case Qt::Key_Right:     dx = stepSize;      break;
00543         case Qt::Key_Up:        dy = -stepSize;     break;
00544         case Qt::Key_Down:      dy = stepSize;      break;
00545         case Qt::Key_PageUp:     dy = -5 * stepSize; break;
00546         case Qt::Key_PageDown:      dy = 5 * stepSize;  break;
00547     }
00548     int adj = dx + dy;
00549     // kDebug() << "KKbdAccessExtensions::resizePanelFromKey: adj = " << adj << endl;
00550     if (adj != 0)
00551         resizePanel(dx, dy, state);
00552     else {
00553         if (key == Qt::Key_Enter) {
00554             Q3DockWindow* dockWindow = qobject_cast<Q3DockWindow *>(d->panel);
00555             if (dockWindow && dockWindow->area())
00556                 dockWindow->undock();
00557             else if (dockWindow)
00558                 dockWindow->dock();
00559         }
00560     }
00561     showIcon();
00562 }
00563 
00564 void KKbdAccessExtensions::displayAccessKeys()
00565 {
00566     // Build a list of valid access keys that don't collide with shortcuts.
00567     QString availableAccessKeys = "ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890";
00568     QList<KXMLGUIClient*> allClients = d->mainWindow->factory()->clients();
00569     foreach ( KXMLGUIClient* client, allClients )
00570     {
00571         QList<KAction*> actions = client->actionCollection()->actions();
00572         for (int j = 0; j < (int)actions.count(); j++) {
00573             KAction* action = actions[j];
00574             KShortcut sc = action->shortcut();
00575             for (int i = 0; i < (int)sc.count(); i++) {
00576                 QKeySequence seq = sc.seq(i);
00577                 if (seq.count() == 1) {
00578                     QString s = seq.toString();
00579                     if (availableAccessKeys.contains(s))
00580                         availableAccessKeys.remove(s);
00581                 }
00582             }
00583         }
00584     }
00585     // Find all visible, focusable widgets and create a QLabel for each.  Don't exceed
00586     // available list of access keys.
00587     QWidgetList allWidgets = kapp->allWidgets();
00588     int accessCount = 0;
00589     int maxAccessCount = availableAccessKeys.length();
00590     int overlap = 20;
00591     QPoint prevGlobalPos = QPoint(-overlap, -overlap);
00592     foreach ( QWidget* widget, allWidgets ) {
00593         if (accessCount >= maxAccessCount)
00594             break;
00595         if (widget->isVisible() && widget->focusPolicy() != Qt::NoFocus ) {
00596             QRect r = widget->rect();
00597             QPoint p(r.x(), r.y());
00598             // Don't display an access key if within overlap pixels of previous one.
00599             QPoint globalPos = widget->mapToGlobal(p);
00600             QPoint diffPos = globalPos - prevGlobalPos;
00601             if (diffPos.manhattanLength() > overlap) {
00602                 accessCount++;
00603                 QLabel* lab = new QLabel( widget, Qt::WDestructiveClose );
00604                 lab->setBuddy( widget );
00605                 lab->setPalette(QToolTip::palette());
00606                 lab->setLineWidth(2);
00607                 lab->setFrameStyle(QFrame::Box | QFrame::Plain);
00608                 lab->setMargin(3);
00609                 lab->adjustSize();
00610                 lab->move(p);
00611                 if (!d->accessKeyLabels) {
00612                     d->accessKeyLabels = new Q3PtrList<QLabel>;
00613                     d->accessKeyLabels->setAutoDelete(true);
00614                 }
00615                 d->accessKeyLabels->append(lab);
00616                 prevGlobalPos = globalPos;
00617             }
00618         }
00619     }
00620     if (accessCount > 0) {
00621         // Sort the access keys from left to right and down the screen.
00622         Q3ValueList<KSortedLabel> sortedLabels;
00623         for (int i = 0; i < accessCount; i++)
00624             sortedLabels.append(KSortedLabel(d->accessKeyLabels->at(i)));
00625         qHeapSort( sortedLabels );
00626         // Assign access key labels.
00627         for (int i = 0; i < accessCount; i++) {
00628             QLabel* lab = sortedLabels[i].label();
00629             QChar s = availableAccessKeys[i];
00630             lab->setText(s);
00631             lab->adjustSize();
00632             lab->show();
00633         }
00634     }
00635 }
00636 
00637 // Handling of the HTML accesskey attribute.
00638 bool KKbdAccessExtensions::handleAccessKey( const QKeyEvent* ev )
00639 {
00640 // Qt interprets the keyevent also with the modifiers, and ev->text() matches that,
00641 // but this code must act as if the modifiers weren't pressed
00642     if (!d->accessKeyLabels) return false;
00643     QChar c;
00644     if( ev->key() >= Qt::Key_A && ev->key() <= Qt::Key_Z )
00645         c = 'A' + ev->key() - Qt::Key_A;
00646     else if( ev->key() >= Qt::Key_0 && ev->key() <= Qt::Key_9 )
00647         c = '0' + ev->key() - Qt::Key_0;
00648     else {
00649         // TODO fake XKeyEvent and XLookupString ?
00650         // This below seems to work e.g. for eacute though.
00651         if( ev->text().length() == 1 )
00652             c = ev->text()[ 0 ];
00653     }
00654     if( c.isNull())
00655         return false;
00656 
00657     QLabel* lab = d->accessKeyLabels->first();
00658     while (lab) {
00659         if (lab->text() == c) {
00660             lab->buddy()->setFocus();
00661             delete d->accessKeyLabels;
00662             d->accessKeyLabels = 0;
00663             return true;
00664         }
00665         lab = d->accessKeyLabels->next();
00666     }
00667     return false;
00668 }
00669 
00670 KSortedLabel::KSortedLabel(QLabel* l) :
00671     m_l(l) { }
00672 
00673 KSortedLabel::KSortedLabel() :
00674     m_l(0) { }
00675 
00676 bool KSortedLabel::operator<( const KSortedLabel& l ) const
00677 {
00678     QPoint p1 = m_l->mapToGlobal(m_l->pos());
00679     QPoint p2 = l.label()->mapToGlobal(l.label()->pos());
00680     return (p1.y() < p2.y() || (p1.y() == p2.y() && p1.x() < p2.x()));
00681 }

Généré le Wed Nov 22 23:41:01 2006 pour KPlato par  doxygen 1.5.1-p1