summaryrefslogtreecommitdiff
path: root/inputmethods/handwriting/qimpenhelp.cpp
authorkergoth <kergoth>2002-01-25 22:14:26 (UTC)
committer kergoth <kergoth>2002-01-25 22:14:26 (UTC)
commit15318cad33835e4e2dc620d033e43cd930676cdd (patch) (side-by-side diff)
treec2fa0399a2c47fda8e2cd0092c73a809d17f68eb /inputmethods/handwriting/qimpenhelp.cpp
downloadopie-15318cad33835e4e2dc620d033e43cd930676cdd.zip
opie-15318cad33835e4e2dc620d033e43cd930676cdd.tar.gz
opie-15318cad33835e4e2dc620d033e43cd930676cdd.tar.bz2
Initial revision
Diffstat (limited to 'inputmethods/handwriting/qimpenhelp.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--inputmethods/handwriting/qimpenhelp.cpp410
1 files changed, 410 insertions, 0 deletions
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 <qpe/qpeapplication.h>
+#include <qpe/global.h>
+#include <qpe/config.h>
+#include <qpe/stringutil.h>
+
+#include <qtextview.h>
+#include <qlabel.h>
+#include <qlistbox.h>
+#include <qcombobox.h>
+#include <qpushbutton.h>
+#include <qlayout.h>
+#include <qtimer.h>
+#include <qtextstream.h>
+
+/* 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( "<ul><li>When you start to use the handwriting recogniser "
+ "write slowly, accurately and firmly."
+ "<li>Use the guide lines when drawing your characters."
+ "<li>When drawing a character with multiple strokes, each "
+ "successive stroke must be drawn before the grayed strokes are erased."
+ "<li>Practice your handwriting using the handwriting trainer."
+ "<li>When adding your own character templates make sure they "
+ "are sufficiently different from other characters' templates."
+ "</ul>") );
+
+ 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 << "<qt>" << 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 << "<br>";
+ ts << tr("Similar to: ");
+ }
+ ts << "<big>";
+ if ( (*it).penChar->character() == currentChar->character() )
+ ts << "<b>";
+ ts << Qtopia::escapeString((*it).penChar->name());
+ ts << " (" << rateString(rate) << ")";
+ if ( (*it).penChar->character() == currentChar->character() )
+ ts << "</b>";
+ ts << "</big>";
+ }
+ }
+ ts << "</qt>";
+ 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;
+}
+