From 15318cad33835e4e2dc620d033e43cd930676cdd Mon Sep 17 00:00:00 2001 From: kergoth Date: Fri, 25 Jan 2002 22:14:26 +0000 Subject: Initial revision --- (limited to 'inputmethods/handwriting/qimpenhelp.cpp') diff --git a/inputmethods/handwriting/qimpenhelp.cpp b/inputmethods/handwriting/qimpenhelp.cpp new file mode 100644 index 0000000..5ee46a2 --- a/dev/null +++ b/inputmethods/handwriting/qimpenhelp.cpp @@ -0,0 +1,410 @@ +/********************************************************************** +** 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 "qimpencombining.h" +#include "qimpenmatch.h" +#include "qimpenhelp.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/* XPM */ +static const char * const left_xpm[] = { +"16 16 2 1", +" c None", +". c #000000", +" ", +" ", +" ", +" . ", +" .. ", +" ... ", +" .... ", +" ..... ", +" ...... ", +" ..... ", +" .... ", +" ... ", +" .. ", +" . ", +" ", +" "}; + + +/* XPM */ +static const char * const right_xpm[] = { +"16 16 2 1", +" c None", +". c #000000", +" ", +" ", +" ", +" . ", +" .. ", +" ... ", +" .... ", +" ..... ", +" ...... ", +" ..... ", +" .... ", +" ... ", +" .. ", +" . ", +" ", +" "}; + +class CharListItem : public QListBoxText +{ +public: + CharListItem( const QString &text, uint c ) + : QListBoxText( text ) + { + _code = c; + } + + uint code() const { return _code; } + +protected: + uint _code; +}; + +HandwritingHelp::HandwritingHelp( QIMPenProfile *p, QWidget *parent, const char *name, WFlags f ) + : QTabWidget( parent, name, f ) +{ + setCaption( tr("Handwriting Help") ); + QTextView *help = new QTextView( this ); + help->setFrameStyle( QFrame::NoFrame ); + help->setText( + tr( "
  • When you start to use the handwriting recogniser " + "write slowly, accurately and firmly." + "
  • Use the guide lines when drawing your characters." + "
  • When drawing a character with multiple strokes, each " + "successive stroke must be drawn before the grayed strokes are erased." + "
  • Practice your handwriting using the handwriting trainer." + "
  • When adding your own character templates make sure they " + "are sufficiently different from other characters' templates." + "
") ); + + addTab( help, tr("Tips") ); + + HandwritingTrainer *trainer = new HandwritingTrainer( p, this ); + addTab( trainer, tr("Trainer") ); +} + +void HandwritingHelp::showEvent( QShowEvent * ) +{ + Global::hideInputMethod(); +} + +void HandwritingHelp::hideEvent( QHideEvent * ) +{ + Global::showInputMethod(); +} + +//--------------------------------------------------------------------------- + +HandwritingTrainer::HandwritingTrainer( QIMPenProfile *p, QWidget *parent, const char *name ) + : QWidget( parent, name ), profile(p) +{ + QGridLayout *gl = new QGridLayout( this, 5, 2, 0, 4 ); + gl->setRowStretch( 1, 1 ); + gl->setRowStretch( 2, 1 ); + gl->setColStretch( 1, 1 ); + + charSetCombo = new QComboBox( this ); + gl->addMultiCellWidget( charSetCombo, 0, 0, 0, 1 ); + connect( charSetCombo, SIGNAL(activated(int)), SLOT(selectCharSet(int))); + QIMPenCharSetIterator it( profile->charSets() ); + for ( ; it.current(); ++it ) { + charSetCombo->insertItem( it.current()->description() ); + } + + charList = new QListBox( this ); + charList->setHScrollBarMode( QListBox::AlwaysOff ); + charList->setFixedWidth( 80 ); + connect( charList, SIGNAL(highlighted(int)), this, SLOT(selectChar(int)) ); + gl->addMultiCellWidget( charList, 1, 2, 0, 0 ); + + QLabel *help = new QLabel( this ); + help->setAlignment( AlignLeft | AlignVCenter | WordBreak ); + gl->addWidget( help, 1, 1 ); + help->setText( + tr( "Select a character from the list. The writing area on the left " + "shows the reference character. Practice writing in the area on " + "the right.") ); + + result = new QLabel( this ); + gl->addMultiCellWidget( result, 2, 3, 1, 1 ); + + matcher = new QIMPenMatch( this ); + matcher->setCharSet( currentSet ); + connect( matcher, SIGNAL(noMatch()), this, SLOT(noMatch()) ); + connect( matcher, SIGNAL(matchedCharacters(const QIMPenCharMatchList &)), + this, SLOT(matched(const QIMPenCharMatchList &)) ); + + QHBoxLayout *hb = new QHBoxLayout(); + gl->addLayout( hb, 3, 0 ); + prevBtn = new QPushButton( this ); + prevBtn->setPixmap( QPixmap( (const char **)left_xpm ) ); + connect( prevBtn, SIGNAL(clicked()), SLOT(prevChar())); + hb->addWidget( prevBtn ); + + nextBtn = new QPushButton( this ); + nextBtn->setPixmap( QPixmap( (const char **)right_xpm ) ); + connect( nextBtn, SIGNAL(clicked()), SLOT(nextChar())); + hb->addWidget( nextBtn ); + + refPw = new QIMPenWidget( this ); + refPw->setReadOnly( TRUE ); + gl->addWidget( refPw, 4, 0 ); + + pracPw = new QIMPenWidget( this ); + connect( matcher, SIGNAL(removeStroke()), pracPw, SLOT(removeStroke()) ); + connect( pracPw, SIGNAL(beginStroke()), + this, SLOT(beginStroke()) ); + connect( pracPw, SIGNAL(stroke( QIMPenStroke * )), + this, SLOT(strokeEntered( QIMPenStroke * )) ); + connect( pracPw, SIGNAL(beginStroke()), + matcher, SLOT(beginStroke()) ); + connect( pracPw, SIGNAL(stroke( QIMPenStroke * )), + matcher, SLOT(strokeEntered( QIMPenStroke * )) ); + gl->addWidget( pracPw, 4, 1 ); + + redrawTimer = new QTimer( this ); + connect( redrawTimer, SIGNAL(timeout()), this, SLOT(redrawChar()) ); + redrawTimer->start( 5000 ); + + currentSet = 0; + charSetCombo->setCurrentItem( 1 ); + selectCharSet( 1 ); +} + +HandwritingTrainer::~HandwritingTrainer() +{ +} + +void HandwritingTrainer::showEvent( QShowEvent * ) +{ + redrawChar(); + redrawTimer->start( 5000 ); +} + +void HandwritingTrainer::setCurrentChar( QIMPenChar *c ) +{ + currentChar = c; + refPw->showCharacter( currentChar ); + pracPw->clear(); + if ( currentChar ) { + prevBtn->setEnabled( findPrev() != 0 ); + nextBtn->setEnabled( findNext() != 0 ); + } + result->setText( "" ); + redrawTimer->start( 5000 ); +} + +void HandwritingTrainer::selectChar( int i ) +{ + currentChar = 0; + currentCode = ((CharListItem *)charList->item(i))->code(); + QIMPenCharIterator it(currentSet->characters() ); + for ( ; it.current(); ++it ) { + if ( it.current()->character() == currentCode && + !it.current()->testFlag( QIMPenChar::Deleted ) ) { + setCurrentChar( it.current() ); + break; + } + } + if ( !it.current() ) + setCurrentChar( 0 ); +} + +void HandwritingTrainer::selectCharSet( int i ) +{ + if ( currentSet ) { + refPw->removeCharSet( 0 ); + pracPw->removeCharSet( 0 ); + } + currentSet = profile->charSets().at( i ); + fillCharList(); + refPw->insertCharSet( currentSet ); + pracPw->insertCharSet( currentSet ); + matcher->setCharSet( currentSet ); + if ( charList->count() ) { + charList->setSelected( 0, TRUE ); + selectChar(0); + } +} + +void HandwritingTrainer::noMatch() +{ + result->setText( "No match" ); +} + +void HandwritingTrainer::matched( const QIMPenCharMatchList &ml ) +{ + int maxErr = 20000 + (*ml.begin()).penChar->strokeLength(0) * 1000; + int baseErr = (*ml.begin()).penChar->strokeLength(0) * 250; + unsigned int numStrokes = (*ml.begin()).penChar->strokeCount(); + QIMPenCharMatchList::ConstIterator it; + /* + for ( it = ml.begin(); it != ml.end(); ++it ) { + if ( (*it).penChar->strokeCount() == numStrokes ) { + if ( (*it).error > maxErr ) + maxErr = (*it).error; + } + } + */ + int i; + QString res; + QTextStream ts(&res, IO_WriteOnly); + ts << "" << tr("Matched: "); + for ( i = 0, it = ml.begin(); it != ml.end() && i < 4; ++it, i++ ) { + if ( (*it).penChar->strokeCount() == numStrokes ) { + int rate = 100 - ( ((*it).error - baseErr) * 100 ) / maxErr; + if ( it != ml.begin() ) { + if ( rate < -10 ) + continue; + ts << "
"; + ts << tr("Similar to: "); + } + ts << ""; + if ( (*it).penChar->character() == currentChar->character() ) + ts << ""; + ts << Qtopia::escapeString((*it).penChar->name()); + ts << " (" << rateString(rate) << ")"; + if ( (*it).penChar->character() == currentChar->character() ) + ts << ""; + ts << ""; + } + } + ts << "
"; + result->setText( res ); +} + +QString HandwritingTrainer::rateString( int rate ) const +{ + if ( rate < 1 ) + rate = 1; + if ( rate > 100 ) + rate = 100; + return tr("%1%").arg(rate); +} + +void HandwritingTrainer::prevChar() +{ + QIMPenChar *pc = findPrev(); + if ( pc ) + setCurrentChar( pc ); +} + +void HandwritingTrainer::nextChar() +{ + QIMPenChar *pc = findNext(); + if ( pc ) + setCurrentChar( pc ); +} + +void HandwritingTrainer::redrawChar() +{ + if ( currentChar ) + refPw->showCharacter( currentChar ); +} + +void HandwritingTrainer::beginStroke() +{ + redrawTimer->start( 5000 ); +} + +void HandwritingTrainer::strokeEntered( QIMPenStroke * ) +{ + pracPw->greyStroke(); +} + +QIMPenChar *HandwritingTrainer::findPrev() +{ + if ( !currentChar ) + return 0; + QIMPenCharIterator it( currentSet->characters() ); + bool found = FALSE; + for ( it.toLast(); it.current(); --it ) { + if ( !found && it.current() == currentChar ) + found = TRUE; + else if ( found && it.current()->character() == currentCode && + !it.current()->testFlag( QIMPenChar::Deleted ) ) { + return it.current(); + } + } + + return 0; +} + +QIMPenChar *HandwritingTrainer::findNext() +{ + if ( !currentChar ) + return 0; + QIMPenCharIterator it( currentSet->characters() ); + bool found = FALSE; + for ( ; it.current(); ++it ) { + if ( !found && it.current() == currentChar ) + found = TRUE; + else if ( found && it.current()->character() == currentCode && + !it.current()->testFlag( QIMPenChar::Deleted ) ) { + return it.current(); + } + } + + return 0; +} + +void HandwritingTrainer::fillCharList() +{ + charList->clear(); + QIMPenCharIterator it( currentSet->characters() ); + CharListItem *li = 0; + for ( ; it.current(); ++it ) { + uint ch = it.current()->character(); + QString n = it.current()->name(); + if ( !n.isEmpty() ) + li = new CharListItem( n, ch ); + if ( li ) { + CharListItem *i = (CharListItem *)charList->findItem( li->text() ); + if ( !i || i->code() != ch ) { + charList->insertItem( li ); + } else { + delete li; + li = 0; + } + } + } + currentChar = 0; +} + -- cgit v0.9.0.2