-rw-r--r-- | libopie2/opieui/okeyconfigwidget.cpp | 242 | ||||
-rw-r--r-- | libopie2/opieui/okeyconfigwidget.h | 11 | ||||
-rw-r--r-- | libopie2/opieui/okeyconfigwidget_p.h | 33 |
3 files changed, 216 insertions, 70 deletions
diff --git a/libopie2/opieui/okeyconfigwidget.cpp b/libopie2/opieui/okeyconfigwidget.cpp index 41be1be..3e08416 100644 --- a/libopie2/opieui/okeyconfigwidget.cpp +++ b/libopie2/opieui/okeyconfigwidget.cpp @@ -1,49 +1,51 @@ #include "okeyconfigwidget.h" +#include "okeyconfigwidget_p.h" -#include <opie2/olistview.h> #include <qgroupbox.h> #include <qradiobutton.h> #include <qpushbutton.h> #include <qbuttongroup.h> #include <qaccel.h> #include <qlayout.h> #include <qlabel.h> +#include <qtimer.h> using namespace Opie::Ui; + /** * The default Constructor of a OKeyPair. * A Key and a Modifier ( Alt/Shift/Ctrl ) * needs to be supplied. * Use Qt::Key for the information. * The default arguments create an Empty OKeyPair. If you * want to get an empty OKeyPair use the static method for getting * the emptyKey() * * @see OKeyPair OKeyPair::emptyKey() */ OKeyPair::OKeyPair( int key, int mod ) : m_key( key ), m_mod( mod ) {} /** * The destructor */ OKeyPair::~OKeyPair() {} /** * Is this OKeyPair empty/valid? */ bool OKeyPair::isEmpty()const { return ( ( m_key == -1 )&& ( m_mod == -1 ) ); } /** * get the keycode for this OKeyPair. The Key relates to Qt::Key. * * @see Qt::Key @@ -510,86 +512,66 @@ void OKeyConfigManager::save() { continue; OKeyPair pair = (*it).keyPair(); OKeyPair deft = (*it).defaultKeyPair(); /* * don't write if it is the default setting * FIXME allow to remove Keys if ( (pair.keycode() == deft.keycode()) && (pair.modifier()== deft.modifier() ) ) return; */ m_conf->writeEntry((*it).configKey()+"key", pair.keycode() ); m_conf->writeEntry((*it).configKey()+"mod", pair.modifier() ); } } /** * This is function uses a QMap internally but you can have the same keycode * with different modifier key. The behaviour is undefined if you add a OKeyConfigItem * with same keycode and modifier key. The GUI takes care that a user can't * cofigure two keys. * * Make sure you call e->ignore if you don't want to handle this event */ OKeyConfigItem OKeyConfigManager::handleKeyEvent( QKeyEvent* e ) { /* * Fix Up issues with Qt/E, my keybard, and virtual input * methods * First my Keyboard delivers 256,512,1024 for shift/ctrl/alt instead of the button state * Also key() on virtual inputmethods are zero and only ascii. We need to fix upper and lower * case ascii */ - int key = e->key(); - int mod = e->state(); - -/* - * virtual keyboard - * else change the button mod only - */ - if ( key == 0 ) { - key = e->ascii(); - if ( key > 96 && key < 123) - key -= 32; - }else{ - int new_mod = 0; - if ( mod & 256 ) - new_mod |= Qt::ShiftButton; - else if ( mod & 512 ) - new_mod |= Qt::ControlButton; - else if ( mod & 1024 ) - new_mod |= Qt::AltButton; - - mod = new_mod == 0? mod : new_mod; - } + int key, mod; + Opie::Ui::Private::fixupKeys( key, mod, e ); OKeyConfigItem::List _keyList = keyList( key ); if ( _keyList.isEmpty() ) return OKeyConfigItem(); OKeyConfigItem item; for ( OKeyConfigItem::List::Iterator it = _keyList.begin(); it != _keyList.end(); ++it ) { if ( (*it).keyPair().modifier() == mod ) { item = *it; break; } } return item; } /** * Return the associated id of the item or -1 if no item * matched the key * * @see handleKeyEvent */ int OKeyConfigManager::handleKeyEventId( QKeyEvent* ev) { return handleKeyEvent( ev ).id(); } /** * Add Key Config to the List of items */ void OKeyConfigManager::addKeyConfig( const OKeyConfigItem& item ) { @@ -703,160 +685,162 @@ bool OKeyConfigManager::eventFilter( QObject* obj, QEvent* ev) { * @internal */ OKeyConfigItem::List OKeyConfigManager::keyList( int keycode) { /* * Create the map if not existing anymore */ if ( !m_map ) { m_map = new OKeyMapConfigPrivate; /* for every key */ for ( OKeyConfigItem::List::Iterator it = m_keys.begin(); it!= m_keys.end(); ++it ) { bool add = true; /* see if this key is blocked */ OKeyPair pair = (*it).keyPair(); for ( OKeyPair::List::Iterator pairIt = m_blackKeys.begin(); pairIt != m_blackKeys.end(); ++pairIt ) { if ( (*pairIt).keycode() == pair.keycode() && (*pairIt).modifier() == pair.modifier() ) { add = false; break; } } /* check if we added it */ if ( add ) (*m_map)[pair.keycode()].append( *it ); } } return (*m_map)[keycode]; } - -///////////////////////// -//////// Widget Starts Here namespace Opie { namespace Ui { namespace Private { - static QString keyToString( const OKeyPair& ); - class OKeyListViewItem : public Opie::Ui::OListViewItem { - public: - OKeyListViewItem( const OKeyConfigItem& item, OKeyConfigManager*, Opie::Ui::OListViewItem* parent); - ~OKeyListViewItem(); - - void setDefault(); - - OKeyConfigItem& item(); - OKeyConfigItem origItem()const; - void setItem( const OKeyConfigItem& item ); - void updateText(); - - OKeyConfigManager *manager(); - private: - OKeyConfigItem m_item; - OKeyConfigItem m_origItem; - OKeyConfigManager* m_manager; - - }; OKeyListViewItem::OKeyListViewItem( const OKeyConfigItem& item, OKeyConfigManager* man, OListViewItem* parent) : Opie::Ui::OListViewItem( parent ), m_manager( man ) { m_origItem = item; setItem( item ); } OKeyListViewItem::~OKeyListViewItem() {} OKeyConfigItem &OKeyListViewItem::item(){ return m_item; } OKeyConfigItem OKeyListViewItem::origItem() const{ return m_origItem; } OKeyConfigManager* OKeyListViewItem::manager() { return m_manager; } void OKeyListViewItem::setItem( const OKeyConfigItem& item ) { m_item = item; setPixmap( 0, m_item.pixmap() ); setText ( 1, m_item.text() ); m_item.keyPair().isEmpty() ? setText( 2, QObject::tr( "None" ) ) : setText( 2, keyToString( m_item.keyPair() ) ); m_item.defaultKeyPair().isEmpty() ? setText( 3, QObject::tr( "None" ) ) : setText ( 3, keyToString( m_item.defaultKeyPair() ) ); } void OKeyListViewItem::updateText() { m_item.keyPair().isEmpty() ? setText( 2, QObject::tr( "None" ) ) : setText( 2, keyToString( m_item.keyPair() ) ); } QString keyToString( const OKeyPair& pair ) { int mod = 0; if ( pair.modifier() & Qt::ShiftButton ) mod |= Qt::SHIFT; if ( pair.modifier() & Qt::ControlButton ) mod |= Qt::CTRL; if ( pair.modifier() & Qt::AltButton ) mod |= Qt::ALT; return QAccel::keyToString( mod + pair.keycode() ); } + void fixupKeys( int& key, int &mod, QKeyEvent* e ) { + key = e->key(); + mod = e->state(); + /* + * virtual keyboard + * else change the button mod only + */ + if ( key == 0 ) { + key = e->ascii(); + if ( key > 96 && key < 123) + key -= 32; + }else{ + int new_mod = 0; + if ( mod & 256 ) + new_mod |= Qt::ShiftButton; + else if ( mod & 512 ) + new_mod |= Qt::ControlButton; + else if ( mod & 1024 ) + new_mod |= Qt::AltButton; + + mod = new_mod == 0? mod : new_mod; + } + } + struct OKeyConfigWidgetPrivate{ OKeyConfigWidgetPrivate(const QString& = QString::null, OKeyConfigManager* = 0); bool operator==( const OKeyConfigWidgetPrivate& ); QString name; OKeyConfigManager *manager; }; OKeyConfigWidgetPrivate::OKeyConfigWidgetPrivate( const QString& _name, OKeyConfigManager* man ) : name( _name ), manager( man ){} bool OKeyConfigWidgetPrivate::operator==( const OKeyConfigWidgetPrivate& item) { if ( manager != item.manager) return false; if ( name != item.name ) return false; return true; } } } } //////////////////////// - +//////////////////////// +//////// Widget Starts Here /** * * This is a c'tor. You still need to pass the OKeyConfigManager * and then issue a load. * The default mode is Immediate * */ OKeyConfigWidget::OKeyConfigWidget( QWidget* parent, const char *name, WFlags fl ) : QWidget( parent, name, fl ) { initUi(); } /** * c'tor */ OKeyConfigWidget::~OKeyConfigWidget() { } /** * @internal */ void OKeyConfigWidget::initUi() { QBoxLayout *layout = new QVBoxLayout( this ); QGridLayout *gridLay = new QGridLayout( 2, 2 ); layout->addLayout( gridLay, 10 ); @@ -1010,100 +994,218 @@ void OKeyConfigWidget::slotListViewItem( QListViewItem* _item) { OKeyConfigItem keyItem= item->item(); m_lbl->setText( tr("Default: " )+ item->text( 3 ) ); if ( keyItem.keyPair().isEmpty() ) { m_none->setChecked( true ); m_btn ->setEnabled( false ); m_def ->setChecked( false ); m_cus ->setChecked( false ); }else { m_none->setChecked( false ); m_cus ->setChecked( true ); m_btn ->setEnabled( true ); m_def ->setChecked( false ); } } } void OKeyConfigWidget::slotNoKey() { qWarning( "No Key" ); m_none->setChecked( true ); m_cus ->setChecked( false ); m_btn ->setEnabled( false ); m_def ->setChecked( false ); if ( !m_view->currentItem() || !m_view->currentItem()->parent() ) return; /* * If immediate we need to remove and readd the key */ Opie::Ui::Private::OKeyListViewItem *item = static_cast<Opie::Ui::Private::OKeyListViewItem*>(m_view->currentItem()); - if ( m_mode == Imediate ) - item->manager()->removeKeyConfig( item->item() ); - item->item().setKeyPair( OKeyPair::emptyKey() ); - item->updateText(); - - if ( m_mode == Imediate ) - item->manager()->addKeyConfig( item->item() ); - + updateItem( item, OKeyPair::emptyKey() ); } void OKeyConfigWidget::slotDefaultKey() { m_none->setChecked( false ); m_cus ->setChecked( false ); m_btn ->setEnabled( false ); m_def ->setChecked( true ); if ( !m_view->currentItem() || !m_view->currentItem()->parent() ) return; Opie::Ui::Private::OKeyListViewItem *item = static_cast<Opie::Ui::Private::OKeyListViewItem*>(m_view->currentItem()); - - /* - * If immediate we need to remove and readd the key - */ - if ( m_mode == Imediate ) - item->manager()->removeKeyConfig( item->item() ); - - item->item().setKeyPair( item->item().defaultKeyPair() ); - item->updateText(); - - if ( m_mode == Imediate ) - item->manager()->addKeyConfig( item->item() ); + updateItem( item, item->item().defaultKeyPair() ); } void OKeyConfigWidget::slotCustomKey() { m_cus ->setChecked( true ); m_btn ->setEnabled( true ); m_def ->setChecked( false ); m_none->setChecked( false ); if ( !m_view->currentItem() || !m_view->currentItem()->parent() ) return; + } void OKeyConfigWidget::slotConfigure() { + if ( !m_view->currentItem() || !m_view->currentItem()->parent() ) + return; + + /* FIXME make use of OModalHelper */ + OKeyChooserConfigDialog dlg( this, "Dialog Name", true ); + dlg.setCaption(tr("Configure Key")); + connect(&dlg, SIGNAL(keyCaptured()), &dlg, SLOT(accept()) ); + + if ( QPEApplication::execDialog( &dlg ) == QDialog::Accepted ) { + Opie::Ui::Private::OKeyListViewItem *item = static_cast<Opie::Ui::Private::OKeyListViewItem*>(m_view->currentItem()); + updateItem( item, dlg.keyPair() ); + } + + +} + +void OKeyConfigWidget::updateItem( Opie::Ui::Private::OKeyListViewItem *item, + const OKeyPair& newItem) { + /* sanity check + * check against the blacklist of the manager + * check if another item uses this key which is o(n) at least + */ + if ( !newItem.isEmpty() ) { + + } + /* + * If immediate we need to remove and readd the key + */ + if ( m_mode == Imediate ) + item->manager()->removeKeyConfig( item->item() ); + + item->item().setKeyPair( newItem ); + item->updateText(); + + if ( m_mode == Imediate ) + item->manager()->addKeyConfig( item->item() ); } + +///// OKeyChooserConfigDialog::OKeyChooserConfigDialog( QWidget* par, const char* nam, bool mod, WFlags fl ) - : QDialog( par, nam, mod, fl ) { + : QDialog( par, nam, mod, fl ), m_virtKey( false ), m_keyPair( OKeyPair::emptyKey() ) , + m_key( 0 ), m_mod( 0 ) { + setFocusPolicy( StrongFocus ); + + QHBoxLayout *lay = new QHBoxLayout( this ); + + QLabel *lbl = new QLabel( tr("Configure Key" ), this ); + lay->addWidget( lbl ); + lbl->setFocusPolicy( NoFocus ); + + m_lbl = new QLabel( this ); + lay->addWidget( m_lbl ); + m_lbl->setFocusPolicy( NoFocus ); + + m_timer = new QTimer( this ); + connect(m_timer, SIGNAL(timeout()), + this, SLOT(slotTimeUp()) ); } OKeyChooserConfigDialog::~OKeyChooserConfigDialog() { } Opie::Ui::OKeyPair OKeyChooserConfigDialog::keyPair()const{ + return m_keyPair; } void OKeyChooserConfigDialog::keyPressEvent( QKeyEvent* ev ) { - ev->ignore(); + QDialog::keyPressEvent( ev ); + + if ( ev->isAutoRepeat() ) + return; + + qWarning( "Key Press Event" ); + int mod, key; + Opie::Ui::Private::fixupKeys( key,mod, ev ); + + /* either we used software keyboard + * or we've true support + */ + if ( !m_virtKey && !ev->key()) { + m_virtKey = true; + m_keyPair = OKeyPair( key, mod ); + }else{ + mod = 0; + switch( key ) { + case Qt::Key_Control: + mod = Qt::ControlButton; + break; + case Qt::Key_Shift: + mod = Qt::ShiftButton; + break; + case Qt::Key_Alt: + mod = Qt::AltButton; + break; + default: + break; + } + if (mod ) { + m_mod |= mod; + }else + m_key = key; + + if ( ( !mod || m_key ) && !m_timer->isActive() ) + m_timer->start( 50, true ); + + m_keyPair = OKeyPair( m_key, m_mod ); + } + + m_lbl->setText( Opie::Ui::Private::keyToString( m_keyPair ) ); + } void OKeyChooserConfigDialog::keyReleaseEvent( QKeyEvent* ev ) { - ev->ignore(); + m_timer->stop(); + QDialog::keyPressEvent( ev ); + + if ( ev->isAutoRepeat() ) + return; + + + if ( m_virtKey && !ev->key()) { + m_virtKey = false; + slotTimeUp(); + }else { + int mod = 0; + int key = ev->key(); + switch( key ) { + case Qt::Key_Control: + mod = Qt::ControlButton; + break; + case Qt::Key_Shift: + mod = Qt::ShiftButton; + break; + case Qt::Key_Alt: + mod = Qt::AltButton; + break; + default: + break; + } + if (mod ) + m_mod &= ~mod; + else + m_key = key; + m_keyPair = OKeyPair( m_key, m_mod ); + m_lbl->setText( Opie::Ui::Private::keyToString( m_keyPair ) ); + } +} + + +void OKeyChooserConfigDialog::slotTimeUp() { + m_mod = m_key = 0; + QTimer::singleShot(0, this, SIGNAL(keyCaptured()) ); } diff --git a/libopie2/opieui/okeyconfigwidget.h b/libopie2/opieui/okeyconfigwidget.h index 8d2a1ef..9e26719 100644 --- a/libopie2/opieui/okeyconfigwidget.h +++ b/libopie2/opieui/okeyconfigwidget.h @@ -1,61 +1,63 @@ /* * Copyright (C) 2004 * LGPL v2 zecke@handhelds.org */ #ifndef ODP_KEY_CONFIG_WIDGET_H #define ODP_KEY_CONFIG_WIDGET_H #include <opie2/oconfig.h> #include <opie2/odevice.h> #include <qstring.h> #include <qpixmap.h> #include <qcstring.h> #include <qhbox.h> #include <qvaluelist.h> class QKeyEvent; class QLabel; class QPushButton; class QListViewItem; class QRadioButton; +class QTimer; namespace Opie { namespace Ui { namespace Private { class OKeyConfigWidgetPrivate; typedef QValueList<OKeyConfigWidgetPrivate> OKeyConfigWidgetPrivateList; + class OKeyListViewItem; } class OListViewItem; class OListView; /** * \brief small class representing a Key with possible modifiers * This class holds information about key code and possible * modifier state. That is the lowest level of the key input * functions. * There are also static methods to get special keys. * OKeyPair will be used with \see OKeyConfigItem * * @since 1.2 */ class OKeyPair { public: typedef QValueList<OKeyPair> List; OKeyPair( int key = -1, int modifier = -1); ~OKeyPair(); bool operator==( const OKeyPair& ); bool operator!=( const OKeyPair& ); bool isEmpty()const; int keycode()const; int modifier()const; void setKeycode( int ); void setModifier( int ); static OKeyPair returnKey(); @@ -222,88 +224,97 @@ private: * it to the OKeyConfigManager * * @since 1.2 */ class OKeyConfigWidget : public QWidget { Q_OBJECT public: /** * Immediate Apply the change directly to the underlying OKeyConfigManager * Queue Save all items and then apply when you save() */ enum ChangeMode { Imediate, Queue }; OKeyConfigWidget( QWidget* parent = 0, const char* name = 0, WFlags fl = 0 ); ~OKeyConfigWidget(); void setChangeMode( enum ChangeMode ); ChangeMode changeMode()const; void insert( const QString& name, OKeyConfigManager* ); void load(); void save(); private slots: void slotListViewItem( QListViewItem* ); void slotNoKey(); void slotDefaultKey(); void slotCustomKey(); void slotConfigure(); private: + void updateItem( Opie::Ui::Private::OKeyListViewItem* man, + const OKeyPair& newItem); void initUi(); Opie::Ui::OListView *m_view; Opie::Ui::Private::OKeyConfigWidgetPrivateList m_list; QLabel *m_lbl; QPushButton *m_btn; QRadioButton *m_def, *m_cus, *m_none; QWidget* m_box; ChangeMode m_mode; class Private; Private *d; }; /** * This is a small dialog that allows you to * capture a key sequence. * If you want it to close after a key was captured you * can use this code snippet. * * \code * OKeyChooserConfigDialog diag(0,0,true); * connect(&diag,SIGNAL(keyCaptured()), * this,SLOT(accept())); * if( QPEApplication::execDialog(&diag) == QDialog::Accept ){ * take_the_key_and_do_something * } * * \endcode * */ class OKeyChooserConfigDialog : public QDialog { Q_OBJECT public: OKeyChooserConfigDialog( QWidget* parent = 0, const char* name = 0, bool modal = false, WFlags fl = 0 ); ~OKeyChooserConfigDialog(); OKeyPair keyPair()const; protected: void keyPressEvent( QKeyEvent* ); void keyReleaseEvent( QKeyEvent* ); signals: void keyCaptured(); +private slots: + void slotTimeUp(); + private: + QTimer *m_timer; + QLabel *m_lbl; + bool m_virtKey : 1; OKeyPair m_keyPair; + int m_key, m_mod; class Private; Private *d; }; } } #endif diff --git a/libopie2/opieui/okeyconfigwidget_p.h b/libopie2/opieui/okeyconfigwidget_p.h new file mode 100644 index 0000000..e7eaba6 --- a/dev/null +++ b/libopie2/opieui/okeyconfigwidget_p.h @@ -0,0 +1,33 @@ +/* + * Only Internal implemented in the same .cpp file anyway + */ +#include <opie2/olistview.h> + + +namespace Opie { +namespace Ui { +namespace Private { + static QString keyToString( const OKeyPair& ); + static void fixupKeys( int&, int&, QKeyEvent* ); + class OKeyListViewItem : public Opie::Ui::OListViewItem { + public: + OKeyListViewItem( const OKeyConfigItem& item, OKeyConfigManager*, Opie::Ui::OListViewItem* parent); + ~OKeyListViewItem(); + + void setDefault(); + + OKeyConfigItem& item(); + OKeyConfigItem origItem()const; + void setItem( const OKeyConfigItem& item ); + void updateText(); + + OKeyConfigManager *manager(); + private: + OKeyConfigItem m_item; + OKeyConfigItem m_origItem; + OKeyConfigManager* m_manager; + + }; +} +} +} |