summaryrefslogtreecommitdiff
path: root/inputmethods/handwriting/qimpenhelp.cpp
Unidiff
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 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia Environment.
5**
6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file.
10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13**
14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20
21#include "qimpenwidget.h"
22#include "qimpencombining.h"
23#include "qimpenmatch.h"
24#include "qimpenhelp.h"
25
26#include <qpe/qpeapplication.h>
27#include <qpe/global.h>
28#include <qpe/config.h>
29#include <qpe/stringutil.h>
30
31#include <qtextview.h>
32#include <qlabel.h>
33#include <qlistbox.h>
34#include <qcombobox.h>
35#include <qpushbutton.h>
36#include <qlayout.h>
37#include <qtimer.h>
38#include <qtextstream.h>
39
40/* XPM */
41static const char * const left_xpm[] = {
42"16 16 2 1",
43" c None",
44". c #000000",
45" ",
46" ",
47" ",
48" . ",
49" .. ",
50" ... ",
51" .... ",
52" ..... ",
53" ...... ",
54" ..... ",
55" .... ",
56" ... ",
57" .. ",
58" . ",
59" ",
60" "};
61
62
63/* XPM */
64static const char * const right_xpm[] = {
65"16 16 2 1",
66" c None",
67". c #000000",
68" ",
69" ",
70" ",
71" . ",
72" .. ",
73" ... ",
74" .... ",
75" ..... ",
76" ...... ",
77" ..... ",
78" .... ",
79" ... ",
80" .. ",
81" . ",
82" ",
83" "};
84
85class CharListItem : public QListBoxText
86{
87public:
88 CharListItem( const QString &text, uint c )
89 : QListBoxText( text )
90 {
91 _code = c;
92 }
93
94 uint code() const { return _code; }
95
96protected:
97 uint _code;
98};
99
100HandwritingHelp::HandwritingHelp( QIMPenProfile *p, QWidget *parent, const char *name, WFlags f )
101 : QTabWidget( parent, name, f )
102{
103 setCaption( tr("Handwriting Help") );
104 QTextView *help = new QTextView( this );
105 help->setFrameStyle( QFrame::NoFrame );
106 help->setText(
107 tr( "<ul><li>When you start to use the handwriting recogniser "
108 "write slowly, accurately and firmly."
109 "<li>Use the guide lines when drawing your characters."
110 "<li>When drawing a character with multiple strokes, each "
111 "successive stroke must be drawn before the grayed strokes are erased."
112 "<li>Practice your handwriting using the handwriting trainer."
113 "<li>When adding your own character templates make sure they "
114 "are sufficiently different from other characters' templates."
115 "</ul>") );
116
117 addTab( help, tr("Tips") );
118
119 HandwritingTrainer *trainer = new HandwritingTrainer( p, this );
120 addTab( trainer, tr("Trainer") );
121}
122
123void HandwritingHelp::showEvent( QShowEvent * )
124{
125 Global::hideInputMethod();
126}
127
128void HandwritingHelp::hideEvent( QHideEvent * )
129{
130 Global::showInputMethod();
131}
132
133//---------------------------------------------------------------------------
134
135HandwritingTrainer::HandwritingTrainer( QIMPenProfile *p, QWidget *parent, const char *name )
136 : QWidget( parent, name ), profile(p)
137{
138 QGridLayout *gl = new QGridLayout( this, 5, 2, 0, 4 );
139 gl->setRowStretch( 1, 1 );
140 gl->setRowStretch( 2, 1 );
141 gl->setColStretch( 1, 1 );
142
143 charSetCombo = new QComboBox( this );
144 gl->addMultiCellWidget( charSetCombo, 0, 0, 0, 1 );
145 connect( charSetCombo, SIGNAL(activated(int)), SLOT(selectCharSet(int)));
146 QIMPenCharSetIterator it( profile->charSets() );
147 for ( ; it.current(); ++it ) {
148 charSetCombo->insertItem( it.current()->description() );
149 }
150
151 charList = new QListBox( this );
152 charList->setHScrollBarMode( QListBox::AlwaysOff );
153 charList->setFixedWidth( 80 );
154 connect( charList, SIGNAL(highlighted(int)), this, SLOT(selectChar(int)) );
155 gl->addMultiCellWidget( charList, 1, 2, 0, 0 );
156
157 QLabel *help = new QLabel( this );
158 help->setAlignment( AlignLeft | AlignVCenter | WordBreak );
159 gl->addWidget( help, 1, 1 );
160 help->setText(
161 tr( "Select a character from the list. The writing area on the left "
162 "shows the reference character. Practice writing in the area on "
163 "the right.") );
164
165 result = new QLabel( this );
166 gl->addMultiCellWidget( result, 2, 3, 1, 1 );
167
168 matcher = new QIMPenMatch( this );
169 matcher->setCharSet( currentSet );
170 connect( matcher, SIGNAL(noMatch()), this, SLOT(noMatch()) );
171 connect( matcher, SIGNAL(matchedCharacters(const QIMPenCharMatchList &)),
172 this, SLOT(matched(const QIMPenCharMatchList &)) );
173
174 QHBoxLayout *hb = new QHBoxLayout();
175 gl->addLayout( hb, 3, 0 );
176 prevBtn = new QPushButton( this );
177 prevBtn->setPixmap( QPixmap( (const char **)left_xpm ) );
178 connect( prevBtn, SIGNAL(clicked()), SLOT(prevChar()));
179 hb->addWidget( prevBtn );
180
181 nextBtn = new QPushButton( this );
182 nextBtn->setPixmap( QPixmap( (const char **)right_xpm ) );
183 connect( nextBtn, SIGNAL(clicked()), SLOT(nextChar()));
184 hb->addWidget( nextBtn );
185
186 refPw = new QIMPenWidget( this );
187 refPw->setReadOnly( TRUE );
188 gl->addWidget( refPw, 4, 0 );
189
190 pracPw = new QIMPenWidget( this );
191 connect( matcher, SIGNAL(removeStroke()), pracPw, SLOT(removeStroke()) );
192 connect( pracPw, SIGNAL(beginStroke()),
193 this, SLOT(beginStroke()) );
194 connect( pracPw, SIGNAL(stroke( QIMPenStroke * )),
195 this, SLOT(strokeEntered( QIMPenStroke * )) );
196 connect( pracPw, SIGNAL(beginStroke()),
197 matcher, SLOT(beginStroke()) );
198 connect( pracPw, SIGNAL(stroke( QIMPenStroke * )),
199 matcher, SLOT(strokeEntered( QIMPenStroke * )) );
200 gl->addWidget( pracPw, 4, 1 );
201
202 redrawTimer = new QTimer( this );
203 connect( redrawTimer, SIGNAL(timeout()), this, SLOT(redrawChar()) );
204 redrawTimer->start( 5000 );
205
206 currentSet = 0;
207 charSetCombo->setCurrentItem( 1 );
208 selectCharSet( 1 );
209}
210
211HandwritingTrainer::~HandwritingTrainer()
212{
213}
214
215void HandwritingTrainer::showEvent( QShowEvent * )
216{
217 redrawChar();
218 redrawTimer->start( 5000 );
219}
220
221void HandwritingTrainer::setCurrentChar( QIMPenChar *c )
222{
223 currentChar = c;
224 refPw->showCharacter( currentChar );
225 pracPw->clear();
226 if ( currentChar ) {
227 prevBtn->setEnabled( findPrev() != 0 );
228 nextBtn->setEnabled( findNext() != 0 );
229 }
230 result->setText( "" );
231 redrawTimer->start( 5000 );
232}
233
234void HandwritingTrainer::selectChar( int i )
235{
236 currentChar = 0;
237 currentCode = ((CharListItem *)charList->item(i))->code();
238 QIMPenCharIterator it(currentSet->characters() );
239 for ( ; it.current(); ++it ) {
240 if ( it.current()->character() == currentCode &&
241 !it.current()->testFlag( QIMPenChar::Deleted ) ) {
242 setCurrentChar( it.current() );
243 break;
244 }
245 }
246 if ( !it.current() )
247 setCurrentChar( 0 );
248}
249
250void HandwritingTrainer::selectCharSet( int i )
251{
252 if ( currentSet ) {
253 refPw->removeCharSet( 0 );
254 pracPw->removeCharSet( 0 );
255 }
256 currentSet = profile->charSets().at( i );
257 fillCharList();
258 refPw->insertCharSet( currentSet );
259 pracPw->insertCharSet( currentSet );
260 matcher->setCharSet( currentSet );
261 if ( charList->count() ) {
262 charList->setSelected( 0, TRUE );
263 selectChar(0);
264 }
265}
266
267void HandwritingTrainer::noMatch()
268{
269 result->setText( "No match" );
270}
271
272void HandwritingTrainer::matched( const QIMPenCharMatchList &ml )
273{
274 int maxErr = 20000 + (*ml.begin()).penChar->strokeLength(0) * 1000;
275 int baseErr = (*ml.begin()).penChar->strokeLength(0) * 250;
276 unsigned int numStrokes = (*ml.begin()).penChar->strokeCount();
277 QIMPenCharMatchList::ConstIterator it;
278 /*
279 for ( it = ml.begin(); it != ml.end(); ++it ) {
280 if ( (*it).penChar->strokeCount() == numStrokes ) {
281 if ( (*it).error > maxErr )
282 maxErr = (*it).error;
283 }
284 }
285 */
286 int i;
287 QString res;
288 QTextStream ts(&res, IO_WriteOnly);
289 ts << "<qt>" << tr("Matched: ");
290 for ( i = 0, it = ml.begin(); it != ml.end() && i < 4; ++it, i++ ) {
291 if ( (*it).penChar->strokeCount() == numStrokes ) {
292 int rate = 100 - ( ((*it).error - baseErr) * 100 ) / maxErr;
293 if ( it != ml.begin() ) {
294 if ( rate < -10 )
295 continue;
296 ts << "<br>";
297 ts << tr("Similar to: ");
298 }
299 ts << "<big>";
300 if ( (*it).penChar->character() == currentChar->character() )
301 ts << "<b>";
302 ts << Qtopia::escapeString((*it).penChar->name());
303 ts << " (" << rateString(rate) << ")";
304 if ( (*it).penChar->character() == currentChar->character() )
305 ts << "</b>";
306 ts << "</big>";
307 }
308 }
309 ts << "</qt>";
310 result->setText( res );
311}
312
313QString HandwritingTrainer::rateString( int rate ) const
314{
315 if ( rate < 1 )
316 rate = 1;
317 if ( rate > 100 )
318 rate = 100;
319 return tr("%1%").arg(rate);
320}
321
322void HandwritingTrainer::prevChar()
323{
324 QIMPenChar *pc = findPrev();
325 if ( pc )
326 setCurrentChar( pc );
327}
328
329void HandwritingTrainer::nextChar()
330{
331 QIMPenChar *pc = findNext();
332 if ( pc )
333 setCurrentChar( pc );
334}
335
336void HandwritingTrainer::redrawChar()
337{
338 if ( currentChar )
339 refPw->showCharacter( currentChar );
340}
341
342void HandwritingTrainer::beginStroke()
343{
344 redrawTimer->start( 5000 );
345}
346
347void HandwritingTrainer::strokeEntered( QIMPenStroke * )
348{
349 pracPw->greyStroke();
350}
351
352QIMPenChar *HandwritingTrainer::findPrev()
353{
354 if ( !currentChar )
355 return 0;
356 QIMPenCharIterator it( currentSet->characters() );
357 bool found = FALSE;
358 for ( it.toLast(); it.current(); --it ) {
359 if ( !found && it.current() == currentChar )
360 found = TRUE;
361 else if ( found && it.current()->character() == currentCode &&
362 !it.current()->testFlag( QIMPenChar::Deleted ) ) {
363 return it.current();
364 }
365 }
366
367 return 0;
368}
369
370QIMPenChar *HandwritingTrainer::findNext()
371{
372 if ( !currentChar )
373 return 0;
374 QIMPenCharIterator it( currentSet->characters() );
375 bool found = FALSE;
376 for ( ; it.current(); ++it ) {
377 if ( !found && it.current() == currentChar )
378 found = TRUE;
379 else if ( found && it.current()->character() == currentCode &&
380 !it.current()->testFlag( QIMPenChar::Deleted ) ) {
381 return it.current();
382 }
383 }
384
385 return 0;
386}
387
388void HandwritingTrainer::fillCharList()
389{
390 charList->clear();
391 QIMPenCharIterator it( currentSet->characters() );
392 CharListItem *li = 0;
393 for ( ; it.current(); ++it ) {
394 uint ch = it.current()->character();
395 QString n = it.current()->name();
396 if ( !n.isEmpty() )
397 li = new CharListItem( n, ch );
398 if ( li ) {
399 CharListItem *i = (CharListItem *)charList->findItem( li->text() );
400 if ( !i || i->code() != ch ) {
401 charList->insertItem( li );
402 } else {
403 delete li;
404 li = 0;
405 }
406 }
407 }
408 currentChar = 0;
409}
410