summaryrefslogtreecommitdiffstats
path: root/lib/kofficecore/kkbdaccessextensions.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/kofficecore/kkbdaccessextensions.cpp')
-rw-r--r--lib/kofficecore/kkbdaccessextensions.cpp667
1 files changed, 667 insertions, 0 deletions
diff --git a/lib/kofficecore/kkbdaccessextensions.cpp b/lib/kofficecore/kkbdaccessextensions.cpp
new file mode 100644
index 000000000..aae372039
--- /dev/null
+++ b/lib/kofficecore/kkbdaccessextensions.cpp
@@ -0,0 +1,667 @@
+/* This file is part of the KDE project
+ Copyright (C) 2005, Gary Cramblitt <garycramblitt@comcast.net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+// Qt includes
+#include <qsplitter.h>
+#include <qdockwindow.h>
+#include <qdockarea.h>
+#include <qevent.h>
+#include <qcursor.h>
+#include <qobjectlist.h>
+#include <qwidgetlist.h>
+#include <qlabel.h>
+#include <qtooltip.h>
+
+// KDE includes
+#include <klocale.h>
+#include <kglobal.h>
+#include <kapplication.h>
+#include <kmainwindow.h>
+#include <kaction.h>
+#include <kdebug.h>
+
+// KKbdAccessExtensions includes
+#include "kkbdaccessextensions.h"
+// TODO: See eventFilter method.
+//#include "kkbdaccessextensions.moc"
+
+class KPanelKbdSizerIcon : public QCursor
+{
+ public:
+ KPanelKbdSizerIcon() :
+ QCursor(Qt::SizeAllCursor),
+ isActive(false)
+ {
+ currentPos = QPoint(-1, -1);
+ }
+
+ ~KPanelKbdSizerIcon()
+ {
+ hide();
+ }
+
+ void show(const QPoint p) {
+ if (!isActive) {
+ originalPos = QCursor::pos();
+ kapp->setOverrideCursor(*this);
+ isActive = true;
+ }
+ if (p != pos())
+ setPos(p);
+ currentPos = p;
+ }
+
+ void hide() {
+ if (isActive) {
+ kapp->restoreOverrideCursor();
+ QCursor::setPos(originalPos);
+ }
+ isActive = false;
+ }
+
+ void setShape(int shayp)
+ {
+ if (shayp != shape()) {
+ // Must restore and override to get the icon to refresh.
+ if (isActive) kapp->restoreOverrideCursor();
+ QCursor::setShape(shayp);
+ if (isActive) kapp->setOverrideCursor(*this);
+ }
+ }
+
+ // Return the difference between a position and where icon is supposed to be.
+ QSize delta(const QPoint p)
+ {
+ QPoint d = p - currentPos;
+ return QSize(d.x(), d.y());
+ }
+
+ // Return the difference between where the icon is currently positioned and where
+ // it is supposed to be.
+ QSize delta() { return delta(pos()); }
+
+ // True if the sizing icon is visible.
+ bool isActive;
+
+ private:
+ // Icon's current position.
+ QPoint currentPos;
+ // Mouse cursor's original position when icon is shown.
+ QPoint originalPos;
+};
+
+class KKbdAccessExtensionsPrivate
+{
+ public:
+ KKbdAccessExtensionsPrivate() :
+ fwdAction(0),
+ revAction(0),
+ accessKeysAction(0),
+ panel(0),
+ handleNdx(0),
+ icon(0),
+ stepSize(10),
+ accessKeyLabels(0) {};
+
+ ~KKbdAccessExtensionsPrivate()
+ {
+ delete icon;
+ // TODO: This crashes, but should delete in the event that KMainWindow is not deleted.
+ if (accessKeyLabels) {
+ accessKeyLabels->setAutoDelete(false);
+ delete accessKeyLabels;
+ }
+ }
+
+ // Action that starts panel sizing (defaults to F8), forward and reverse;
+ KAction* fwdAction;
+ KAction* revAction;
+
+ // Action that starts access keys.
+ KAction* accessKeysAction;
+
+ // The splitter or dockwindow currently being sized. If 0, sizing is not in progress.
+ QWidget* panel;
+
+ // Index of current handle of the panel. When panel is a QDockWindow:
+ // 1 = size horizontally
+ // 2 = size vertically
+ uint handleNdx;
+
+ // Sizing icon.
+ KPanelKbdSizerIcon* icon;
+
+ // Sizing increment.
+ int stepSize;
+
+ // List of the access key QLabels. If not 0, access keys are onscreen.
+ QPtrList<QLabel>* accessKeyLabels;
+
+ // Pointer to the KMainWindow.
+ KMainWindow* mainWindow;
+};
+
+KKbdAccessExtensions::KKbdAccessExtensions(KMainWindow* parent, const char* name) :
+ QObject(parent, name)
+{
+ // kdDebug() << "KKbdAccessExtensions::KKbdAccessExtensions: running." << endl;
+ d = new KKbdAccessExtensionsPrivate;
+ d->mainWindow = parent;
+ d->fwdAction = new KAction(i18n("Resize Panel Forward"), KShortcut("F8"),
+ 0, 0, parent->actionCollection(), "resize_panel_forward");
+ d->revAction = new KAction(i18n("Resize Panel Reverse"), KShortcut("Shift+F8"),
+ 0, 0, parent->actionCollection(), "resize_panel_reverse");
+ d->accessKeysAction = new KAction(i18n("Access Keys"), KShortcut("Alt+F8"),
+ 0, 0, parent->actionCollection(), "access_keys");
+ // "Disable" the shortcuts so we can see them in eventFilter.
+ d->fwdAction->setEnabled(false);
+ d->revAction->setEnabled(false);
+ d->accessKeysAction->setEnabled(false);
+ d->icon = new KPanelKbdSizerIcon();
+ kapp->installEventFilter(this);
+}
+
+KKbdAccessExtensions::~KKbdAccessExtensions()
+{
+ kapp->removeEventFilter(this);
+ if (d->panel) exitSizing();
+ delete d;
+}
+
+int KKbdAccessExtensions::stepSize() const { return d->stepSize; }
+
+void KKbdAccessExtensions::setStepSize(int s) { d->stepSize = s; }
+
+bool KKbdAccessExtensions::eventFilter( QObject *o, QEvent *e )
+{
+ if ( e->type() == QEvent::KeyPress ) {
+ // TODO: This permits only a single-key shortcut. For example, Alt+S,R would not work.
+ // If user configures a multi-key shortcut, it is undefined what will happen here.
+ // It would be better to handle these as KShortcut activate() signals, but the problem
+ // is that once a QDockWindow is undocked and has focus, the KShortcut activate() signals
+ // don't fire anymore.
+ KShortcut fwdSc = d->fwdAction->shortcut();
+ KShortcut revSc = d->revAction->shortcut();
+ KShortcut accessKeysSc = d->accessKeysAction->shortcut();
+ QKeyEvent* kev = dynamic_cast<QKeyEvent *>(e);
+ KKey k = KKey(kev);
+ KShortcut sc = KShortcut(k);
+ // kdDebug() << "KKbdAccessExtensions::eventFilter: Key press " << sc << endl;
+ if (!d->accessKeyLabels) {
+ if (sc == fwdSc) {
+ nextHandle();
+ return true;
+ }
+ if (sc == revSc) {
+ prevHandle();
+ return true;
+ }
+ }
+ if (d->panel) {
+ if (k == KKey(Key_Escape))
+ exitSizing();
+ else
+ resizePanelFromKey(kev->key(), kev->state());
+ // Eat the key.
+ return true;
+ }
+ if (sc == accessKeysSc && !d->panel) {
+ if (d->accessKeyLabels) {
+ delete d->accessKeyLabels;
+ d->accessKeyLabels = 0;
+ } else
+ displayAccessKeys();
+ return true;
+ }
+ if (d->accessKeyLabels) {
+ if (k == KKey(Key_Escape)) {
+ delete d->accessKeyLabels;
+ d->accessKeyLabels = 0;
+ } else
+ handleAccessKey(kev);
+ return true;
+ }
+ return false;
+ }
+ else if (d->icon->isActive && e->type() == QEvent::MouseButtonPress) {
+ exitSizing();
+ return true;
+ }
+ else if (d->accessKeyLabels && e->type() == QEvent::MouseButtonPress) {
+ delete d->accessKeyLabels;
+ d->accessKeyLabels = 0;
+ return true;
+ }
+/* else if (e->type() == QEvent::MouseMove && d->icon->isActive) {
+ // Lock mouse cursor down.
+ showIcon();
+ dynamic_cast<QMouseEvent *>(e)->accept();
+ return true;
+ }*/
+ else if (e->type() == QEvent::MouseMove && d->icon->isActive && d->panel) {
+ // Resize according to mouse movement.
+ QMouseEvent* me = dynamic_cast<QMouseEvent *>(e);
+ QSize s = d->icon->delta();
+ int dx = s.width();
+ int dy = s.height();
+ resizePanel(dx, dy, me->state());
+ me->accept();
+ showIcon();
+ return true;
+ }
+ else if (e->type() == QEvent::Resize && d->panel && o == d->panel) {
+ // TODO: This doesn't always work.
+ showIcon();
+ }
+ return false;
+}
+
+QWidgetList* KKbdAccessExtensions::getAllPanels()
+{
+ QWidgetList* allWidgets = kapp->allWidgets();
+ QWidgetList* allPanels = new QWidgetList;
+ QWidget* widget = allWidgets->first();
+ while (widget) {
+ if (widget->isVisible()) {
+ if (::qt_cast<QSplitter*>( widget )) {
+ // Only size QSplitters with at least two handles (there is always one hidden).
+ if (dynamic_cast<QSplitter *>(widget)->sizes().count() >= 2)
+ allPanels->append(widget);
+ } else if (::qt_cast<QDockWindow*>( widget )) {
+ if (dynamic_cast<QDockWindow *>(widget)->isResizeEnabled()) {
+ // kdDebug() << "KKbdAccessExtensions::getAllPanels: QDockWindow = " << widget->name() << endl;
+ allPanels->append(widget);
+ }
+ }
+ }
+ widget = allWidgets->next();
+ }
+ delete allWidgets;
+ return allPanels;
+}
+
+void KKbdAccessExtensions::nextHandle()
+{
+ QWidget* panel = d->panel;
+ // See if current panel has another handle. If not, find next panel.
+ if (panel) {
+ bool advance = true;
+ d->handleNdx++;
+ if (::qt_cast<QSplitter*>( panel ))
+ advance = (d->handleNdx >= dynamic_cast<QSplitter *>(panel)->sizes().count());
+ else
+ // Undocked windows have only one "handle" (center).
+ advance = (d->handleNdx > 2 || !dynamic_cast<QDockWindow *>(panel)->area());
+ if (advance) {
+ QWidgetList* allWidgets = getAllPanels();
+ allWidgets->findRef(panel);
+ panel = 0;
+ if (allWidgets->current()) panel = allWidgets->next();
+ delete allWidgets;
+ d->handleNdx = 1;
+ }
+ } else {
+ // Find first panel.
+ QWidgetList* allWidgets = getAllPanels();
+ panel = allWidgets->first();
+ delete allWidgets;
+ d->handleNdx = 1;
+ }
+ d->panel = panel;
+ if (panel)
+ showIcon();
+ else
+ exitSizing();
+}
+
+void KKbdAccessExtensions::prevHandle()
+{
+ QWidget* panel = d->panel;
+ // See if current panel has another handle. If not, find previous panel.
+ if (panel) {
+ bool rewind = true;
+ d->handleNdx--;
+ rewind = (d->handleNdx < 1);
+ if (rewind) {
+ QWidgetList* allWidgets = getAllPanels();
+ allWidgets->findRef(panel);
+ panel = 0;
+ if (allWidgets->current()) panel = allWidgets->prev();
+ delete allWidgets;
+ if (panel) {
+ if (::qt_cast<QSplitter*>( panel ))
+ d->handleNdx = dynamic_cast<QSplitter *>(panel)->sizes().count() - 1;
+ else {
+ if (dynamic_cast<QDockWindow *>(panel)->area())
+ d->handleNdx = 2;
+ else
+ d->handleNdx = 1;
+ }
+ }
+ }
+ } else {
+ // Find last panel.
+ QWidgetList* allWidgets = getAllPanels();
+ panel = allWidgets->last();
+ delete allWidgets;
+ if (panel) {
+ if (::qt_cast<QSplitter*>( panel ))
+ d->handleNdx = dynamic_cast<QSplitter *>(panel)->sizes().count() - 1;
+ else {
+ if (dynamic_cast<QDockWindow *>(panel)->area())
+ d->handleNdx = 2;
+ else
+ d->handleNdx = 1;
+ }
+ }
+ }
+ d->panel = panel;
+ if (panel)
+ showIcon();
+ else
+ exitSizing();
+}
+
+void KKbdAccessExtensions::exitSizing()
+{
+ // kdDebug() << "KKbdAccessExtensions::exiting sizing mode." << endl;
+ hideIcon();
+ d->handleNdx = 0;
+ d->panel = 0;
+}
+
+void KKbdAccessExtensions::showIcon()
+{
+ if (!d->panel) return;
+ QPoint p;
+ // kdDebug() << "KKbdAccessExtensions::showIcon: topLevelWidget = " << d->panel->topLevelWidget()->name() << endl;
+ if (::qt_cast<QSplitter*>( d->panel )) {
+ QSplitter* splitter = dynamic_cast<QSplitter *>(d->panel);
+ int handleNdx = d->handleNdx - 1;
+ QValueList<int> sizes = splitter->sizes();
+ // kdDebug() << "KKbdAccessExtensions::showIcon: sizes = " << sizes << endl;
+ if (splitter->orientation() == Qt::Horizontal) {
+ d->icon->setShape(Qt::SizeHorCursor);
+ p.setX(sizes[handleNdx] + (splitter->handleWidth() / 2));
+ p.setY(splitter->height() / 2);
+ } else {
+ d->icon->setShape(Qt::SizeVerCursor);
+ p.setX(splitter->width() / 2);
+ p.setY(sizes[handleNdx] + (splitter->handleWidth() / 2));
+ }
+ // kdDebug() << "KKbdAccessExtensions::showIcon: p = " << p << endl;
+ p = splitter->mapToGlobal(p);
+ // kdDebug() << "KKbdAccessExtensions::showIcon: mapToGlobal = " << p << endl;
+ } else {
+ QDockWindow* dockWindow = dynamic_cast<QDockWindow *>(d->panel);
+ p = dockWindow->pos();
+ if (dockWindow->area()) {
+ // kdDebug() << "KKbdAccessExtensions::showIcon: pos = " << p << " of window = " << dockWindow->parentWidget()->name() << endl;
+ p = dockWindow->parentWidget()->mapTo(dockWindow->topLevelWidget(), p);
+ // kdDebug() << "KKbdAccessExtensions::showIcon: mapTo = " << p << " of window = " << dockWindow->topLevelWidget()->name() << endl;
+ // TODO: How to get the handle width?
+ if (d->handleNdx == 1) {
+ d->icon->setShape(Qt::SizeHorCursor);
+ if (dockWindow->area()->orientation() == Qt::Vertical) {
+ if (dockWindow->area()->handlePosition() == QDockArea::Normal)
+ // Handle is to the right of the dock window.
+ p.setX(p.x() + dockWindow->width());
+ // else Handle is to the left of the dock window.
+ } else
+ // Handle is to the right of the dock window.
+ p.setX(p.x() + dockWindow->width());
+ p.setY(p.y() + (dockWindow->height() / 2));
+ } else {
+ d->icon->setShape(Qt::SizeVerCursor);
+ p.setX(p.x() + (dockWindow->width() / 2));
+ if (dockWindow->area()->orientation() == Qt::Vertical)
+ // Handle is below the dock window.
+ p.setY(p.y() + dockWindow->height());
+ else {
+ if (dockWindow->area()->handlePosition() == QDockArea::Normal)
+ // Handle is below the dock window.
+ p.setY(p.y() + dockWindow->height());
+ // else Handle is above the dock window.
+ }
+ }
+ p = dockWindow->topLevelWidget()->mapToGlobal(p);
+ } else {
+ d->icon->setShape(Qt::SizeAllCursor);
+ p = QPoint(dockWindow->width() / 2, dockWindow->height() / 2);
+ p = dockWindow->mapToGlobal(p); // Undocked. Position in center of window.
+ }
+ }
+ // kdDebug() << "KKbdAccessExtensions::showIcon: show(p) = " << p << endl;
+ d->icon->show(p);
+}
+
+void KKbdAccessExtensions::hideIcon()
+{
+ d->icon->hide();
+}
+
+void KKbdAccessExtensions::resizePanel(int dx, int dy, int state)
+{
+ int adj = dx + dy;
+ if (adj == 0) return;
+ // kdDebug() << "KKbdAccessExtensions::resizePanel: panel = " << d->panel->name() << endl;
+ if (::qt_cast<QSplitter*>( d->panel )) {
+ QSplitter* splitter = dynamic_cast<QSplitter *>(d->panel);
+ int handleNdx = d->handleNdx - 1;
+ QValueList<int> sizes = splitter->sizes();
+ // kdDebug() << "KKbdAccessExtensions::resizePanel: before sizes = " << sizes << endl;
+ sizes[handleNdx] = sizes[handleNdx] + adj;
+ // kdDebug() << "KKbdAccessExtensions::resizePanel: setSizes = " << sizes << endl;
+ splitter->setSizes(sizes);
+ QApplication::postEvent(splitter, new QEvent(QEvent::LayoutHint));
+ } else {
+ // TODO: How to get the handle width?
+ QDockWindow* dockWindow = dynamic_cast<QDockWindow *>(d->panel);
+ if (dockWindow->area()) {
+ // kdDebug() << "KKbdAccessExtensions::resizePanel: fixedExtent = " << dockWindow->fixedExtent() << endl;
+ QSize fe = dockWindow->fixedExtent();
+ if (d->handleNdx == 1) {
+ // When vertically oriented and dock area is on right side of screen, pressing
+ // left arrow increases size.
+ if (dockWindow->area()->orientation() == Qt::Vertical &&
+ dockWindow->area()->handlePosition() == QDockArea::Reverse) adj = -adj;
+ int w = fe.width();
+ if (w < 0) w = dockWindow->width();
+ w = w + adj;
+ if (w > 0 ) dockWindow->setFixedExtentWidth(w);
+ } else {
+ // When horizontally oriented and dock area is at bottom of screen,
+ // pressing up arrow increases size.
+ if (dockWindow->area()->orientation() == Qt::Horizontal &&
+ dockWindow->area()->handlePosition() == QDockArea::Reverse) adj = -adj;
+ int h = fe.height();
+ if (h < 0) h = dockWindow->height();
+ h = h + adj;
+ if (h > 0) dockWindow->setFixedExtentHeight(h);
+ }
+ dockWindow->updateGeometry();
+ QApplication::postEvent(dockWindow->area(), new QEvent(QEvent::LayoutHint));
+ // kdDebug() << "KKbdAccessExtensions::resizePanel: fixedExtent = " << dockWindow->fixedExtent() << endl;
+ } else {
+ if (state == Qt::ShiftButton) {
+ QSize s = dockWindow->size();
+ s.setWidth(s.width() + dx);
+ s.setHeight(s.height() + dy);
+ dockWindow->resize(s);
+ } else {
+ QPoint p = dockWindow->pos();
+ p.setX(p.x() + dx);
+ p.setY(p.y() + dy);
+ dockWindow->move(p);
+ }
+ }
+ }
+}
+
+void KKbdAccessExtensions::resizePanelFromKey(int key, int state)
+{
+ // kdDebug() << "KPanelKdbSizer::resizePanelFromKey: key = " << key << " state = " << state << endl;
+ if (!d->panel) return;
+ int dx = 0;
+ int dy = 0;
+ int stepSize = d->stepSize;
+ switch (key) {
+ case Qt::Key_Left: dx = -stepSize; break;
+ case Qt::Key_Right: dx = stepSize; break;
+ case Qt::Key_Up: dy = -stepSize; break;
+ case Qt::Key_Down: dy = stepSize; break;
+ case Qt::Key_Prior: dy = -5 * stepSize; break;
+ case Qt::Key_Next: dy = 5 * stepSize; break;
+ }
+ int adj = dx + dy;
+ // kdDebug() << "KKbdAccessExtensions::resizePanelFromKey: adj = " << adj << endl;
+ if (adj != 0)
+ resizePanel(dx, dy, state);
+ else {
+ if (key == Qt::Key_Enter && ::qt_cast<QDockWindow*>( d->panel )) {
+ QDockWindow* dockWindow = dynamic_cast<QDockWindow *>(d->panel);
+ if (dockWindow->area())
+ dockWindow->undock();
+ else
+ dockWindow->dock();
+ }
+ }
+ showIcon();
+}
+
+void KKbdAccessExtensions::displayAccessKeys()
+{
+ // Build a list of valid access keys that don't collide with shortcuts.
+ QString availableAccessKeys = "ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890";
+ QPtrList<KXMLGUIClient> allClients = d->mainWindow->factory()->clients();
+ QPtrListIterator<KXMLGUIClient> it( allClients );
+ KXMLGUIClient *client;
+ while( (client=it.current()) !=0 )
+ {
+ ++it;
+ KActionPtrList actions = client->actionCollection()->actions();
+ for (int j = 0; j < (int)actions.count(); j++) {
+ KAction* action = actions[j];
+ KShortcut sc = action->shortcut();
+ for (int i = 0; i < (int)sc.count(); i++) {
+ KKeySequence seq = sc.seq(i);
+ if (seq.count() == 1) {
+ QString s = seq.toString();
+ if (availableAccessKeys.contains(s))
+ availableAccessKeys.remove(s);
+ }
+ }
+ }
+ }
+ // Find all visible, focusable widgets and create a QLabel for each. Don't exceed
+ // available list of access keys.
+ QWidgetList* allWidgets = kapp->allWidgets();
+ QWidget* widget = allWidgets->first();
+ int accessCount = 0;
+ int maxAccessCount = availableAccessKeys.length();
+ int overlap = 20;
+ QPoint prevGlobalPos = QPoint(-overlap, -overlap);
+ while (widget && (accessCount < maxAccessCount)) {
+ if (widget->isVisible() && widget->isFocusEnabled() ) {
+ QRect r = widget->rect();
+ QPoint p(r.x(), r.y());
+ // Don't display an access key if within overlap pixels of previous one.
+ QPoint globalPos = widget->mapToGlobal(p);
+ QPoint diffPos = globalPos - prevGlobalPos;
+ if (diffPos.manhattanLength() > overlap) {
+ accessCount++;
+ QLabel* lab=new QLabel(widget, "", widget, 0, Qt::WDestructiveClose);
+ lab->setPalette(QToolTip::palette());
+ lab->setLineWidth(2);
+ lab->setFrameStyle(QFrame::Box | QFrame::Plain);
+ lab->setMargin(3);
+ lab->adjustSize();
+ lab->move(p);
+ if (!d->accessKeyLabels) {
+ d->accessKeyLabels = new QPtrList<QLabel>;
+ d->accessKeyLabels->setAutoDelete(true);
+ }
+ d->accessKeyLabels->append(lab);
+ prevGlobalPos = globalPos;
+ }
+ }
+ widget = allWidgets->next();
+ }
+ if (accessCount > 0) {
+ // Sort the access keys from left to right and down the screen.
+ QValueList<KSortedLabel> sortedLabels;
+ for (int i = 0; i < accessCount; i++)
+ sortedLabels.append(KSortedLabel(d->accessKeyLabels->at(i)));
+ qHeapSort( sortedLabels );
+ // Assign access key labels.
+ for (int i = 0; i < accessCount; i++) {
+ QLabel* lab = sortedLabels[i].label();
+ QChar s = availableAccessKeys[i];
+ lab->setText(s);
+ lab->adjustSize();
+ lab->show();
+ }
+ }
+}
+
+// Handling of the HTML accesskey attribute.
+bool KKbdAccessExtensions::handleAccessKey( const QKeyEvent* ev )
+{
+// Qt interprets the keyevent also with the modifiers, and ev->text() matches that,
+// but this code must act as if the modifiers weren't pressed
+ if (!d->accessKeyLabels) return false;
+ QChar c;
+ if( ev->key() >= Key_A && ev->key() <= Key_Z )
+ c = 'A' + ev->key() - Key_A;
+ else if( ev->key() >= Key_0 && ev->key() <= Key_9 )
+ c = '0' + ev->key() - Key_0;
+ else {
+ // TODO fake XKeyEvent and XLookupString ?
+ // This below seems to work e.g. for eacute though.
+ if( ev->text().length() == 1 )
+ c = ev->text()[ 0 ];
+ }
+ if( c.isNull())
+ return false;
+
+ QLabel* lab = d->accessKeyLabels->first();
+ while (lab) {
+ if (lab->text() == c) {
+ lab->buddy()->setFocus();
+ delete d->accessKeyLabels;
+ d->accessKeyLabels = 0;
+ return true;
+ }
+ lab = d->accessKeyLabels->next();
+ }
+ return false;
+}
+
+KSortedLabel::KSortedLabel(QLabel* l) :
+ m_l(l) { }
+
+KSortedLabel::KSortedLabel() :
+ m_l(0) { }
+
+bool KSortedLabel::operator<( KSortedLabel l )
+{
+ QPoint p1 = m_l->mapToGlobal(m_l->pos());
+ QPoint p2 = l.label()->mapToGlobal(l.label()->pos());
+ return (p1.y() < p2.y() || (p1.y() == p2.y() && p1.x() < p2.x()));
+}