PDA

View Full Version : Enabling non English mnemonics (shortcuts for buttons etc.)



grin
25th March 2011, 16:22
Hello, the code below allows to apply not English mnemonics for standard widgets



// shortcuts.h
class QWidget; //forward declaration - for faster compilation
class QKeyEvent; //forward declaration- for faster compilation
bool checkWidgetShortcuts(QWidget*widget,QKeyEvent*ev);




// shortcuts.cpp
#include <QWidget>
#include <QKeyEvent>
#include <QAbstractButton>
#include <QLabel>
#include <QTabWidget>
#include "qglobal.h"
namespace {
struct SItem
{
QWidget*w;
enum EType {
BUTTON,
LABEL,
TAB
} type;
int data;
SItem(QWidget*_w,EType _t,int _d=0) : w(_w),type(_t),data(_d) {}
};
QList<QWidget*> visible_widgets(QWidget*w)
{
QList<QWidget*> list;
Q_ASSERT(w);
if(w->isVisible() && w->isEnabled()) {
list.append(w);
foreach(QObject*child,w->children())
if(child->isWidgetType())
list << visible_widgets(qobject_cast<QWidget*>(child));
}
return list;
}
} //anonymus namespace
bool checkWidgetShortcuts(QWidget*widget,QKeyEvent*ev)
{
Q_ASSERT(widget && ev);
bool ret_val = false;
int shift = (ev->modifiers() & Qt::ShiftModifier) ? (int)Qt::SHIFT : 0;
int ctrl = (ev->modifiers() & Qt::ControlModifier) ? (int)Qt::CTRL : 0;
int alt = (ev->modifiers() & Qt::AltModifier) ? (int)Qt::ALT : 0;
QKeySequence ks(ev->key() + shift + ctrl + alt);
QList<SItem>list;
foreach(QWidget*cw,visible_widgets(widget)) {
if(qobject_cast<QAbstractButton*>(cw)) {
QAbstractButton*but = qobject_cast<QAbstractButton*>(cw);
if(but->shortcut() == ks)
list.append(SItem(but,SItem::BUTTON));
} else if(qobject_cast<QLabel*>(cw)) {
QLabel*label = qobject_cast<QLabel*>(cw);
if(label->buddy() && label->buddy()->isVisible()
&& (ks == QKeySequence::mnemonic(label->text())))
{
list.append(SItem(label->buddy(),SItem::LABEL));
}
} else if(qobject_cast<QTabWidget*>(cw)) {
QTabWidget*tab = qobject_cast<QTabWidget*>(cw);
for(int i=0;i<tab->count();i++)
if(ks == QKeySequence::mnemonic(tab->tabText(i))) {
list.append(SItem(tab,SItem::TAB,i));
break;
}
}
}
if(list.count()) {
int index = 0;
int last = list.count()-1;
for(int i=last;i>=0;i--) {
if(list.at(i).w->hasFocus()) {
index = (i == last) ? 0 : (i+1);
break;
}
}
const SItem& item = list.at(index);
item.w->setFocus();
switch(item.type) {
case SItem::BUTTON: qobject_cast<QAbstractButton*>(item.w)->click(); break;
case SItem::LABEL: break; //do nothing - just check
case SItem::TAB: qobject_cast<QTabWidget*>(item.w)->setCurrentIndex(item.data); break;
default: Q_ASSERT(false); break;
}
ev->accept();
ret_val = true;
} else {
ev->ignore();
}
return ret_val;
}


Example:


void CMainWindow::keyPressEvent(QKeyEvent*event)
{
if(!checkWidgetShortcuts(this,event)) {
// do something with keyevent if needed
}
}


Profit =)