Diffstat (limited to 'inputmethods/handwriting/qimpeninput.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r-- | inputmethods/handwriting/qimpeninput.cpp | 515 |
1 files changed, 515 insertions, 0 deletions
diff --git a/inputmethods/handwriting/qimpeninput.cpp b/inputmethods/handwriting/qimpeninput.cpp new file mode 100644 index 0000000..6718b26 --- a/dev/null +++ b/inputmethods/handwriting/qimpeninput.cpp @@ -0,0 +1,515 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "qimpenwidget.h" +#include "qimpensetup.h" +#include "qimpeninput.h" +#include "qimpencombining.h" +#include "qimpenwordpick.h" +#include "qimpenmatch.h" +#include "qimpenhelp.h" + +#include <qpe/qpeapplication.h> +#include <qpe/qdawg.h> +#include <qpe/config.h> +#include <qpe/global.h> + +#include <qlayout.h> +#include <qpushbutton.h> +#include <qlabel.h> +#include <qtimer.h> +#include <qdir.h> + +#include <limits.h> + +// We'll use little pixmaps for the buttons to save screen space. + +/* XPM */ +static const char * const pen_xpm[] = { +"12 12 4 1", +" c None", +". c #000000", +"+ c #FFFFFF", +"@ c #808080", +" . ", +" .+. ", +" ..@@.", +" .+@.. ", +" .+@@. ", +" .+@@. ", +" .+@@. ", +" .@.@. ", +" .@@. ", +" .... ", +" .. ", +" "}; + + +/* XPM */ +static char * bs_xpm[] = { +"12 12 5 1", +" c None", +". c #333333", +"+ c #000000", +"@ c #FFFFFF", +"# c #666666", +" ", +" ", +" ", +" . ", +" ++ ", +" +@#+++++. ", +" +@@@@@@@@+ ", +" +@#+++++. ", +" ++ ", +" . ", +" ", +" "}; + + +/* XPM */ +static char * enter_xpm[] = { +"12 12 5 1", +" c None", +". c #333333", +"+ c #000000", +"@ c #FFFFFF", +"# c #666666", +" ", +" .+. ", +" +@+ ", +" . +@+ ", +" ++ +@+ ", +" +@#++++@+ ", +" +@@@@@@@@+ ", +" +@#+++++. ", +" ++ ", +" . ", +" ", +" "}; + + + +/* XPM */ +static char * help_xpm[] = { +"12 12 5 1", +" c None", +". c #000000", +"+ c #FFFFFF", +"@ c #666666", +"# c #333333", +" ", +" ... ", +" .+++. ", +" .+..@+. ", +" #.# .+. ", +" .+. ", +" .+. ", +" .+. ", +" .+. ", +" #.# ", +" .+. ", +" #.# "}; + + +/*! + \class QIMPenInput qimpeninput.h + + Pen input widget. +*/ +QIMPenInput::QIMPenInput( QWidget *parent, const char *name, WFlags f ) + : QFrame( parent, name, f ), helpDlg(0), profile(0) +{ + setFrameStyle( Box | Plain ); + + profileList.setAutoDelete( true ); + + matcher = new QIMPenMatch( this ); + connect( matcher, SIGNAL(keypress(uint)), this, SLOT(keypress(uint)) ); + connect( matcher, SIGNAL(erase()), this, SLOT(erase()) ); + + QGridLayout *gl = new QGridLayout( this, 5, 2, 1, 0 ); + gl->setColStretch( 0, 1 ); + + wordPicker = new QIMPenWordPick( this ); + connect( wordPicker, SIGNAL(wordClicked(const QString &)), + this, SLOT(wordPicked(const QString &)) ); + connect( matcher, SIGNAL(matchedCharacters(const QIMPenCharMatchList &)), + this, SLOT(matchedCharacters(const QIMPenCharMatchList &)) ); + connect( matcher, SIGNAL(matchedWords(const QIMPenMatch::MatchWordList&)), + wordPicker, SLOT(setWords(const QIMPenMatch::MatchWordList&)) ); + QFont f("smallsmooth",9); + QFontInfo fi( f ); + wordPicker->setFont( f ); + wordPicker->setBackgroundColor( white ); + gl->addMultiCellWidget( wordPicker, 0, 0, 0, 1 ); + if ( !Global::fixedDawg().root() || !matcher->isWordMatchingEnabled() ) + wordPicker->hide(); + + pw = new QIMPenWidget( this ); + gl->addMultiCellWidget( pw, 1, 4, 0, 0 ); + + int bh = pw->sizeHint().height()/4; + + QPushButton *b = new QPushButton( this ); + b->setFocusPolicy( NoFocus ); + b->setPixmap( QPixmap( (const char **)bs_xpm ) ); + b->setFixedHeight(pw->sizeHint().height()-3*bh); // left-over space goes here + b->setAutoRepeat( TRUE ); + gl->addWidget( b, 1, 1 ); + connect( b, SIGNAL(clicked()), SLOT(backspace())); + + b = new QPushButton( this ); + b->setFocusPolicy( NoFocus ); + b->setPixmap( QPixmap( (const char **)enter_xpm ) ); + b->setFixedHeight(bh); + b->setAutoRepeat( TRUE ); + gl->addWidget( b, 2, 1 ); + connect( b, SIGNAL(clicked()), SLOT(enter())); + + helpBtn = new QPushButton( this ); + helpBtn->setFocusPolicy( NoFocus ); + helpBtn->setPixmap( QPixmap( (const char **)help_xpm ) ); + helpBtn->setFixedHeight(bh); + gl->addWidget( helpBtn, 3, 1 ); + connect( helpBtn, SIGNAL(clicked()), SLOT(help())); + + QPixmap pm( (const char **)pen_xpm ); + setupBtn = new QPushButton( this ); + setupBtn->setFocusPolicy( NoFocus ); + setupBtn->setPixmap( pm ); + setupBtn->setFixedHeight(bh); + gl->addWidget( setupBtn, 4, 1 ); + connect( setupBtn, SIGNAL(clicked()), SLOT(setup())); + + connect( matcher, SIGNAL(removeStroke()), pw, SLOT(removeStroke()) ); + connect( pw, SIGNAL(changeCharSet( QIMPenCharSet * )), + matcher, SLOT(setCharSet( QIMPenCharSet * )) ); + connect( pw, SIGNAL(changeCharSet( int )), + this, SLOT(selectCharSet( int )) ); + connect( pw, SIGNAL(beginStroke()), + matcher, SLOT(beginStroke()) ); + connect( pw, SIGNAL(stroke( QIMPenStroke * )), + this, SLOT(strokeEntered( QIMPenStroke * )) ); + connect( pw, SIGNAL(stroke( QIMPenStroke * )), + matcher, SLOT(strokeEntered( QIMPenStroke * )) ); + + shortcutCharSet = 0; + currCharSet = 0; + setupDlg = 0; + profile = 0; + mode = Normal; + + loadProfiles(); +} + +QIMPenInput::~QIMPenInput() +{ + delete (HandwritingHelp*) helpDlg; +} + +QSize QIMPenInput::sizeHint() const +{ + int fw = frameWidth(); + int ps = wordPicker->isHidden() ? 0 : wordPicker->sizeHint().height(); + return pw->sizeHint() + QSize( fw*2, fw*2+ps ); +} + +void QIMPenInput::loadProfiles() +{ + profileList.clear(); + profile = 0; + delete shortcutCharSet; + shortcutCharSet = new QIMPenCharSet(); + shortcutCharSet->setTitle( "Shortcut" ); + QString path = QPEApplication::qpeDir() + "etc/qimpen"; + QDir dir( path, "*.conf" ); + QStringList list = dir.entryList(); + QStringList::Iterator it; + for ( it = list.begin(); it != list.end(); ++it ) { + QIMPenProfile *p = new QIMPenProfile( path + "/" + *it ); + profileList.append( p ); + if ( p->shortcut() ) { + QIMPenCharIterator it( p->shortcut()->characters() ); + for ( ; it.current(); ++it ) { + shortcutCharSet->addChar( new QIMPenChar(*it.current()) ); + } + } + } + + Config config( "handwriting" ); + config.setGroup( "Settings" ); + QString prof = config.readEntry( "Profile", "Default" ); + selectProfile( prof ); +} + +void QIMPenInput::selectProfile( const QString &name ) +{ + QListIterator<QIMPenProfile> it( profileList ); + for ( ; it.current(); ++it ) { + if ( it.current()->name() == name ) { + profile = it.current(); + break; + } + } + + if ( !it.current() ) + return; + + pw->clearCharSets(); + baseSets.clear(); + + matcher->setMultiStrokeTimeout( profile->multiStrokeTimeout() ); + matcher->setWordMatchingEnabled( profile->matchWords() ); + + if ( !Global::fixedDawg().root() || !matcher->isWordMatchingEnabled() ) + wordPicker->hide(); + else + wordPicker->show(); + + if ( profile->uppercase() && profile->style() == QIMPenProfile::BothCases ) { + baseSets.append( profile->uppercase() ); + pw->insertCharSet( profile->uppercase() ); + } + + if ( profile->lowercase() ) { + baseSets.append( profile->lowercase() ); + pw->insertCharSet( profile->lowercase(), profile->style() == QIMPenProfile::BothCases ? 1 : 2 ); + } + + if ( profile->numeric() ) { + baseSets.append( profile->numeric() ); + pw->insertCharSet( profile->numeric() ); + } + + if ( helpDlg ) + delete (HandwritingHelp*) helpDlg; +} + +void QIMPenInput::wordPicked( const QString &w ) +{ + int bs = matcher->word().length(); + for ( int i = 0; i < bs; i++ ) + keypress( Qt::Key_Backspace << 16 ); + + for ( unsigned int i = 0; i < w.length(); i++ ) + keypress( w[i].unicode() ); + + matcher->resetState(); + wordPicker->clear(); +} + +void QIMPenInput::selectCharSet( int idx ) +{ + if ( mode == Switch ) { + //qDebug( "Switch back to normal" ); + pw->changeCharSet( baseSets.at(currCharSet), currCharSet ); + mode = Normal; + } + currCharSet = idx; +} + +void QIMPenInput::beginStroke() +{ +} + +void QIMPenInput::strokeEntered( QIMPenStroke * ) +{ + pw->greyStroke(); +} + +void QIMPenInput::erase() +{ + keypress( Qt::Key_Backspace << 16 ); +} + +void QIMPenInput::matchedCharacters( const QIMPenCharMatchList &cl ) +{ + const QIMPenChar *ch = cl.first().penChar; + int scan = ch->character() >> 16; + + if ( scan < QIMPenChar::ModeBase ) + return; + + // We matched a special character... + + switch ( scan ) { + case QIMPenChar::Caps: + if ( profile->style() == QIMPenProfile::ToggleCases ) { +// qDebug( "Caps" ); + if ( mode == SwitchLock ) { +// qDebug( "Switch to normal" ); + pw->changeCharSet( profile->lowercase(), currCharSet ); + mode = Switch; + } else { +// qDebug( "Switch to upper" ); + pw->changeCharSet( profile->uppercase(), currCharSet ); + mode = Switch; + } + } + break; + case QIMPenChar::CapsLock: + if ( profile->style() == QIMPenProfile::ToggleCases ) { +// qDebug( "CapsLock" ); + if ( mode == Switch && + baseSets.at(currCharSet) == profile->uppercase() ) { +// qDebug( "Switch to normal" ); + pw->changeCharSet( profile->lowercase(), currCharSet ); + // change our base set back to lower. + baseSets.remove( currCharSet ); + baseSets.insert( currCharSet, profile->lowercase() ); + mode = Normal; + } else { +// qDebug( "Switch to caps lock" ); + pw->changeCharSet( profile->uppercase(), currCharSet ); + // change our base set to upper. + baseSets.remove( currCharSet ); + baseSets.insert( currCharSet, profile->uppercase() ); + mode = SwitchLock; + } + } + break; + case QIMPenChar::Punctuation: + if ( profile->punctuation() ) { + //qDebug( "Switch to punctuation" ); + pw->changeCharSet( profile->punctuation(), currCharSet ); + mode = Switch; + } + break; + case QIMPenChar::Symbol: + if ( profile->symbol() ) { + //qDebug( "Switch to symbol" ); + pw->changeCharSet( profile->symbol(), currCharSet ); + mode = Switch; + } + break; + case QIMPenChar::Shortcut: + if ( shortcutCharSet ) { + pw->changeCharSet( shortcutCharSet, currCharSet ); + mode = Switch; + } + break; + case QIMPenChar::Extended: + handleExtended( ch->data() ); + break; + } +} + +void QIMPenInput::keypress( uint scan_uni ) +{ + int scan = scan_uni >> 16; + if ( !scan ) { + if ( scan_uni >= 'a' && scan_uni <= 'z' ) { + scan = Qt::Key_A + scan_uni - 'a'; + } else if ( scan_uni >= 'A' && scan_uni <= 'Z' ) { + scan = Qt::Key_A + scan_uni - 'A'; + } else if ( scan_uni == ' ' ) { + scan = Qt::Key_Space; + } + } + + switch ( scan ) { + case Key_Tab: + scan_uni = 9; + break; + case Key_Return: + scan_uni = 13; + break; + case Key_Backspace: + scan_uni = 8; + break; + case Key_Escape: + scan_uni = 27; + break; + default: + break; + } + + if ( mode == Switch ) { +// qDebug( "Switch back to normal" ); + pw->changeCharSet( baseSets.at(currCharSet), currCharSet ); + if ( baseSets.at(currCharSet) == profile->uppercase() ) + mode = SwitchLock; + else + mode = Normal; + } + + emit key( scan_uni&0xffff, scan, 0, true, false ); + emit key( scan_uni&0xffff, scan, 0, false, false ); +} + +void QIMPenInput::handleExtended( const QString &ex ) +{ + if ( ex.find( "Select" ) == 0 ) { + QString set = ex.mid( 7 ); + qDebug( "Select new profile: %s", set.latin1() ); + selectProfile( set ); + } +} + +void QIMPenInput::help() +{ + if ( helpDlg ) + delete (HandwritingHelp*) helpDlg; + helpDlg = new HandwritingHelp( profile, 0, 0, WDestructiveClose ); + helpDlg->showMaximized(); + helpDlg->show(); + helpDlg->raise(); +} + +/*! + Open the setup dialog +*/ +void QIMPenInput::setup() +{ + if ( !setupDlg ) { + // We are working with our copy of the char sets here. + setupDlg = new QIMPenSetup( profile, 0, 0, TRUE ); + setupDlg->editor()->selectCharSet( profile->charSets().at(1) ); // lower case? This is crap. + if ( qApp->desktop()->width() < 640 ) + setupDlg->showMaximized(); + Global::hideInputMethod(); + setupDlg->exec(); + loadProfiles(); + delete setupDlg; + setupDlg = 0; + Global::showInputMethod(); + } else { + setupDlg->raise(); + } +} + +void QIMPenInput::backspace() +{ + keypress( Qt::Key_Backspace << 16 ); + matcher->backspace(); +} + +void QIMPenInput::enter() +{ + keypress( Qt::Key_Return << 16 ); + matcher->resetState(); +} + + +void QIMPenInput::resetState() +{ + matcher->resetState(); +} |