summaryrefslogtreecommitdiff
path: root/inputmethods/handwriting/qimpensetup.cpp
Unidiff
Diffstat (limited to 'inputmethods/handwriting/qimpensetup.cpp') (more/less context) (show whitespace changes)
-rw-r--r--inputmethods/handwriting/qimpensetup.cpp656
1 files changed, 656 insertions, 0 deletions
diff --git a/inputmethods/handwriting/qimpensetup.cpp b/inputmethods/handwriting/qimpensetup.cpp
new file mode 100644
index 0000000..a6ae3a8
--- a/dev/null
+++ b/inputmethods/handwriting/qimpensetup.cpp
@@ -0,0 +1,656 @@
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 "qimpenprefbase.h"
23#include "qimpensetup.h"
24
25#include <qpe/qpeapplication.h>
26#include <qpe/config.h>
27
28#include <qcombobox.h>
29#include <qlistbox.h>
30#include <qlabel.h>
31#include <qpushbutton.h>
32#include <qlayout.h>
33#include <qpixmap.h>
34#include <qbuttongroup.h>
35#include <qslider.h>
36#include <qtabwidget.h>
37#include <qdir.h>
38#include <qmessagebox.h>
39
40
41/* XPM */
42static const char * const left_xpm[] = {
43"16 16 2 1",
44 " c None",
45 ".c #000000",
46" ",
47" ",
48" ",
49" . ",
50" .. ",
51" ... ",
52" .... ",
53" ..... ",
54" ...... ",
55" ..... ",
56" .... ",
57" ... ",
58" .. ",
59" . ",
60" ",
61" "};
62
63
64/* XPM */
65static const char * const right_xpm[] = {
66"16 16 2 1",
67 " c None",
68 ".c #000000",
69" ",
70" ",
71" ",
72" . ",
73" .. ",
74" ... ",
75" .... ",
76" ..... ",
77" ...... ",
78" ..... ",
79" .... ",
80" ... ",
81" .. ",
82" . ",
83" ",
84" "};
85
86
87
88QIMPenSetup::QIMPenSetup( QIMPenProfile *p, QWidget *parent,
89 const char *name, bool modal, int WFlags )
90 : QDialog( parent, name, modal, WFlags ), profileCombo(0), profile(p)
91{
92 setCaption( tr("Setup Handwriting Input") );
93
94 QVBoxLayout *vb = new QVBoxLayout( this );
95
96#if 0
97 profileList.setAutoDelete( true );
98 QHBoxLayout *hb = new QHBoxLayout( vb );
99 hb->setMargin( 6 );
100 QLabel *l = new QLabel( tr("Character Profile:"), this );
101 hb->addWidget( l );
102 profileCombo = new QComboBox( this );
103 connect( profileCombo, SIGNAL(activated(const QString &)),
104 this, SLOT(selectProfile(const QString &)) );
105 hb->addWidget( profileCombo );
106 loadProfiles();
107#else
108 profileList.append( profile );
109#endif
110
111 QTabWidget *tw = new QTabWidget( this );
112 vb->addWidget( tw );
113
114 pref = new QIMPenPrefBase( this );
115 tw->addTab( pref, tr("Preferences") );
116
117 pref->inputStyle->setExclusive( TRUE );
118
119 style = profile->style() == QIMPenProfile::ToggleCases ? 1 : 0;
120 pref->inputStyle->setButton( style );
121 connect( pref->inputStyle, SIGNAL(clicked(int)),
122 this, SLOT(styleClicked(int)) );
123 pref->inputStyle->setEnabled( profile->canSelectStyle() );
124
125 multiTimeout = profile->multiStrokeTimeout();
126 pref->multiStrokeSlider->setValue( multiTimeout );
127 multiTimeoutChanged( multiTimeout );
128 connect( pref->multiStrokeSlider, SIGNAL(valueChanged(int)),
129 this, SLOT(multiTimeoutChanged(int)) );
130
131 edit = new QIMPenEdit( p, tw );
132 tw->addTab( edit, tr("Customize") );
133}
134
135void QIMPenSetup::loadProfiles()
136{
137 QString path = QPEApplication::qpeDir() + "etc/qimpen";
138 QDir dir( path, "*.conf" );
139 QStringList list = dir.entryList();
140 QStringList::Iterator it;
141 for ( it = list.begin(); it != list.end(); ++it ) {
142 QIMPenProfile *p = new QIMPenProfile( path + "/" + *it );
143 profileList.append( p );
144 profileCombo->insertItem( p->name() );
145 if ( p->name() == profile->name() ) {
146 profileCombo->setCurrentItem( profileCombo->count()-1 );
147 profile = p;
148 }
149 }
150}
151
152void QIMPenSetup::styleClicked( int id )
153{
154 style = id;
155}
156
157void QIMPenSetup::multiTimeoutChanged( int v )
158{
159 multiTimeout = v;
160 pref->multiStrokeLabel->setText( tr("%1 ms").arg(v) );
161}
162
163void QIMPenSetup::selectProfile( const QString &p )
164{
165 if ( p == profile->name() )
166 return;
167
168 profile->setStyle( style ? QIMPenProfile::ToggleCases : QIMPenProfile::BothCases );
169 profile->setMultiStrokeTimeout( multiTimeout );
170
171 for ( int i = 0; i < (int)profileList.count(); i++ ) {
172 if ( profileList.at(i)->name() == p ) {
173 profile = profileList.at(i);
174 style = profile->style() == QIMPenProfile::ToggleCases ? 1 : 0;
175 pref->inputStyle->setButton( style );
176 pref->inputStyle->setEnabled( profile->canSelectStyle() );
177 multiTimeout = profile->multiStrokeTimeout();
178 pref->multiStrokeSlider->setValue( multiTimeout );
179 multiTimeoutChanged( multiTimeout );
180 edit->setProfile( profile );
181 break;
182 }
183 }
184}
185
186void QIMPenSetup::accept()
187{
188 profile->setStyle( style ? QIMPenProfile::ToggleCases : QIMPenProfile::BothCases );
189 profile->setMultiStrokeTimeout( multiTimeout );
190 // Save current profile
191 if ( profileCombo ) {
192 Config config( "handwriting" );
193 config.setGroup( "Settings" );
194 config.writeEntry( "Profile", profileCombo->currentText() );
195 }
196 // Save charsets
197 bool ok = TRUE;
198 for ( int i = 0; i < (int)profileList.count(); i++ ) {
199 QIMPenProfile *prof = profileList.at(i);
200 QIMPenCharSetIterator it(prof->charSets());
201 for ( ; it.current(); ++it ) {
202 if ( !(it.current()->save( QIMPenCharSet::User )) ) {
203 ok = FALSE;
204 break;
205 }
206 }
207 }
208 if ( !ok ) {
209 if ( QMessageBox::critical( 0, tr( "Out of space" ),
210 tr("Unable to save information.\n"
211 "Free up some space\n"
212 "and try again.\n"
213 "\nQuit anyway?"),
214 QMessageBox::Yes|QMessageBox::Escape,
215 QMessageBox::No|QMessageBox::Default )
216 != QMessageBox::No ) {
217 QDialog::accept();
218 }
219 } else {
220 QDialog::accept();
221 }
222}
223
224//---------------------------------------------------------------------------
225
226QIMPenInputCharDlg::QIMPenInputCharDlg( QWidget *parent, const char *name,
227 bool modal, int WFlags)
228 : QDialog( parent, name, modal, WFlags )
229{
230 setCaption( tr("Enter new character") );
231 uni = 0;
232
233 QVBoxLayout *vb = new QVBoxLayout( this, 10 );
234
235 QHBoxLayout *hb = new QHBoxLayout();
236 vb->addLayout( hb );
237
238 QLabel *label = new QLabel( "Character:", this );
239 hb->addWidget( label );
240
241 QComboBox *cb = new QComboBox( TRUE, this );
242 connect( cb, SIGNAL(activated(int)), SLOT(setSpecial(int)) );
243 connect( cb, SIGNAL(textChanged(const QString &)),
244 SLOT(setCharacter(const QString &)) );
245 addSpecial( cb );
246 cb->setEditText( "" );
247 hb->addWidget( cb );
248
249 hb = new QHBoxLayout();
250 vb->addLayout( hb );
251
252 QPushButton *pb = new QPushButton( "OK", this );
253 connect( pb, SIGNAL(clicked()), SLOT(accept()));
254 hb->addWidget( pb );
255 pb = new QPushButton( "Cancel", this );
256 connect( pb, SIGNAL(clicked()), SLOT(reject()));
257 hb->addWidget( pb );
258
259 cb->setFocus();
260}
261
262void QIMPenInputCharDlg::addSpecial( QComboBox *cb )
263{
264 int i = 0;
265 while ( qimpen_specialKeys[i].code != Key_unknown ) {
266 cb->insertItem( qimpen_specialKeys[i].name );
267 i++;
268 }
269}
270
271void QIMPenInputCharDlg::setSpecial( int sp )
272{
273 uni = qimpen_specialKeys[sp].code << 16;
274}
275
276void QIMPenInputCharDlg::setCharacter( const QString &string )
277{
278 uni = string[0].unicode();
279}
280
281//---------------------------------------------------------------------------
282
283class CharListItem : public QListBoxText
284{
285public:
286 CharListItem( const QString &text, uint c )
287 : QListBoxText( text )
288 {
289 _code = c;
290 }
291
292 uint code() const { return _code; }
293
294protected:
295 uint _code;
296};
297
298/*!
299 \class QIMPenEdit qimpensetup.h
300
301 Class to allow users to input totally useless character definitions
302 which could match any number of the default set.
303*/
304
305QIMPenEdit::QIMPenEdit( QIMPenProfile *p, QWidget *parent,
306 const char *name )
307 : QWidget( parent, name ), profile(p)
308{
309 currentChar = 0;
310 currentCode = 0;
311 inputChar = new QIMPenChar();
312
313 QVBoxLayout *tvb = new QVBoxLayout( this, 5 );
314
315 QGridLayout *gl = new QGridLayout( tvb, 4, 2 );
316 gl->setRowStretch( 1, 1 );
317 gl->addRowSpacing( 2, 35 );
318 gl->addRowSpacing( 3, 35 );
319
320 charSetCombo = new QComboBox( this );
321 gl->addMultiCellWidget( charSetCombo, 0, 0, 0, 1 );
322 connect( charSetCombo, SIGNAL(activated(int)), SLOT(selectCharSet(int)));
323 QIMPenCharSetIterator it( profile->charSets() );
324 for ( ; it.current(); ++it ) {
325 charSetCombo->insertItem( it.current()->description() );
326 }
327
328 charList = new QListBox( this );
329 charList->setMinimumHeight( charList->sizeHint().height() );
330 connect( charList, SIGNAL(highlighted(int)), SLOT(selectChar(int)) );
331 gl->addWidget( charList, 1, 0 );
332
333 pw = new QIMPenWidget( this );
334 pw->setFixedHeight( 75 );
335 gl->addMultiCellWidget( pw, 2, 3, 0, 0 );
336 connect( pw, SIGNAL(stroke(QIMPenStroke *)),
337 SLOT(newStroke(QIMPenStroke *)) );
338
339 QVBoxLayout *vb = new QVBoxLayout();
340 gl->addLayout( vb, 1, 1 );
341 newBtn = new QPushButton( tr("New..."), this );
342 connect( newBtn, SIGNAL(clicked()), SLOT(addNewChar()) );
343 vb->addWidget( newBtn );
344
345 addBtn = new QPushButton( tr("Add"), this );
346 connect( addBtn, SIGNAL(clicked()), SLOT(addChar()) );
347 vb->addWidget( addBtn );
348
349 removeBtn = new QPushButton( tr("Remove"), this );
350 connect( removeBtn, SIGNAL(clicked()), SLOT(removeChar()) );
351 vb->addWidget( removeBtn );
352
353 QPushButton *pb = new QPushButton( tr("Default"), this );
354 connect( pb, SIGNAL(clicked()), SLOT(defaultChars()) );
355 vb->addWidget( pb );
356
357 QHBoxLayout *hb = new QHBoxLayout();
358 gl->addLayout( hb, 2, 1 );
359 prevBtn = new QPushButton( this );
360 prevBtn->setPixmap( QPixmap( (const char **)left_xpm ) );
361 connect( prevBtn, SIGNAL(clicked()), SLOT(prevChar()));
362 hb->addWidget( prevBtn );
363
364 nextBtn = new QPushButton( this );
365 nextBtn->setPixmap( QPixmap( (const char **)right_xpm ) );
366 connect( nextBtn, SIGNAL(clicked()), SLOT(nextChar()));
367 hb->addWidget( nextBtn );
368
369 pb = new QPushButton( tr("Clear"), this );
370 connect( pb, SIGNAL(clicked()), SLOT(clearChar()) );
371 gl->addWidget( pb, 3, 1 );
372
373 //--
374#if !defined(Q_WS_QWS)
375 hb = new QHBoxLayout( tvb );
376 pb = new QPushButton( "OK", this );
377 connect( pb, SIGNAL(clicked()), SLOT(accept()) );
378 hb->addWidget( pb );
379
380 pb = new QPushButton( "Cancel", this );
381 connect( pb, SIGNAL(clicked()), SLOT(reject()) );
382 hb->addWidget( pb );
383#endif
384 selectCharSet( 0 );
385 charList->setFocus();
386
387 resize( minimumSize() );
388 enableButtons();
389}
390
391void QIMPenEdit::setProfile( QIMPenProfile *p )
392{
393 profile = p;
394 charSetCombo->clear();
395 QIMPenCharSetIterator it( profile->charSets() );
396 for ( ; it.current(); ++it ) {
397 charSetCombo->insertItem( it.current()->description() );
398 }
399 selectCharSet( 0 );
400 charList->setFocus();
401 enableButtons();
402}
403
404void QIMPenEdit::selectCharSet( QIMPenCharSet *c )
405{
406 int i = 0;
407 QIMPenCharSetIterator it( profile->charSets() );
408 for ( ; it.current(); ++it, i++ ) {
409 if ( it.current() == c ) {
410 charSetCombo->setCurrentItem( i );
411 selectCharSet( i );
412 }
413 }
414}
415
416
417/*!
418 Fill the character list box with the characters. Duplicates are not
419 inserted.
420*/
421void QIMPenEdit::fillCharList()
422{
423 charList->clear();
424 QIMPenCharIterator it( currentSet->characters() );
425 CharListItem *li = 0;
426 for ( ; it.current(); ++it ) {
427 uint ch = it.current()->character();
428 QString n = it.current()->name();
429 if ( !n.isEmpty() )
430 li = new CharListItem( n, ch );
431 if ( li ) {
432 CharListItem *i = (CharListItem *)charList->findItem( li->text() );
433 if ( !i || i->code() != ch ) {
434 charList->insertItem( li );
435 } else {
436 delete li;
437 li = 0;
438 }
439 }
440 }
441 currentChar = 0;
442}
443
444void QIMPenEdit::enableButtons()
445{
446 bool add = !inputChar->isEmpty();
447 newBtn->setEnabled( add );
448 addBtn->setEnabled( add );
449 removeBtn->setEnabled( currentChar );
450}
451
452/*!
453 Find the previous character with the same code as the current one.
454 returns 0 if there is no previous character.
455*/
456QIMPenChar *QIMPenEdit::findPrev()
457{
458 if ( !currentChar )
459 return 0;
460 QIMPenCharIterator it( currentSet->characters() );
461 bool found = FALSE;
462 for ( it.toLast(); it.current(); --it ) {
463 if ( !found && it.current() == currentChar )
464 found = TRUE;
465 else if ( found && it.current()->character() == currentCode &&
466 !it.current()->testFlag( QIMPenChar::Deleted ) ) {
467 return it.current();
468 }
469 }
470
471 return 0;
472}
473
474/*!
475 Find the next character with the same code as the current one.
476 returns 0 if there is no next character.
477*/
478QIMPenChar *QIMPenEdit::findNext()
479{
480 if ( !currentChar )
481 return 0;
482 QIMPenCharIterator it( currentSet->characters() );
483 bool found = FALSE;
484 for ( ; it.current(); ++it ) {
485 if ( !found && it.current() == currentChar )
486 found = TRUE;
487 else if ( found && it.current()->character() == currentCode &&
488 !it.current()->testFlag( QIMPenChar::Deleted ) ) {
489 return it.current();
490 }
491 }
492
493 return 0;
494}
495
496void QIMPenEdit::setCurrentChar( QIMPenChar *pc )
497{
498 currentChar = pc;
499 pw->showCharacter( currentChar );
500 if ( currentChar ) {
501 prevBtn->setEnabled( findPrev() != 0 );
502 nextBtn->setEnabled( findNext() != 0 );
503 }
504}
505
506void QIMPenEdit::prevChar()
507{
508 QIMPenChar *pc = findPrev();
509 if ( pc )
510 setCurrentChar( pc );
511}
512
513void QIMPenEdit::nextChar()
514{
515 QIMPenChar *pc = findNext();
516 if ( pc )
517 setCurrentChar( pc );
518}
519
520void QIMPenEdit::clearChar()
521{
522 inputChar->clear();
523 pw->clear();
524 enableButtons();
525}
526
527void QIMPenEdit::selectChar( int i )
528{
529 currentChar = 0;
530 currentCode = ((CharListItem *)charList->item(i))->code();
531 QIMPenCharIterator it(currentSet->characters() );
532 for ( ; it.current(); ++it ) {
533 if ( it.current()->character() == currentCode &&
534 !it.current()->testFlag( QIMPenChar::Deleted ) ) {
535 setCurrentChar( it.current() );
536 break;
537 }
538 }
539 if ( !it.current() )
540 setCurrentChar( 0 );
541 inputChar->clear();
542}
543
544void QIMPenEdit::selectCharSet( int i )
545{
546 if ( currentSet )
547 pw->removeCharSet( 0 );
548 currentSet = profile->charSets().at( i );
549 fillCharList();
550 pw->insertCharSet( currentSet );
551 inputChar->clear();
552 if ( charList->count() ) {
553 charList->setSelected( 0, TRUE );
554 selectChar(0);
555 }
556}
557
558void QIMPenEdit::addChar()
559{
560 if ( !inputChar->isEmpty() ) {
561 QIMPenChar *pc = new QIMPenChar( *inputChar );
562 pc->setCharacter( currentCode );
563
564 // User characters override all matching system characters.
565 // Copy and mark deleted identical system characters.
566 QIMPenCharIterator it(currentSet->characters() );
567 QIMPenChar *sc = 0;
568 while ( (sc = it.current()) != 0 ) {
569 ++it;
570 if ( sc->character() == currentCode &&
571 sc->testFlag( QIMPenChar::System ) &&
572 !sc->testFlag( QIMPenChar::Deleted ) ) {
573 QIMPenChar *cc = new QIMPenChar( *sc );
574 cc->clearFlag( QIMPenChar::System );
575 currentSet->addChar( cc );
576 sc->setFlag( QIMPenChar::Deleted );
577 }
578 }
579
580 currentSet->addChar( pc );
581 setCurrentChar( pc );
582 inputChar->clear();
583 }
584}
585
586void QIMPenEdit::addNewChar()
587{
588 if ( !inputChar->isEmpty() ) {
589 QIMPenInputCharDlg dlg( 0, 0, TRUE );
590 if ( dlg.exec() ) {
591 currentCode = dlg.unicode();
592 addChar();
593 fillCharList();
594 for ( unsigned int i = 0; i < charList->count(); i++ ) {
595 CharListItem *li = (CharListItem *)charList->item(i);
596 if ( li->code() == dlg.unicode() ) {
597 charList->setSelected( i, TRUE );
598 break;
599 }
600 }
601 }
602 }
603}
604
605void QIMPenEdit::removeChar()
606{
607 if ( currentChar ) {
608 QIMPenChar *pc = findPrev();
609 if ( !pc ) pc = findNext();
610 if ( currentChar->testFlag( QIMPenChar::System ) )
611 currentChar->setFlag( QIMPenChar::Deleted );
612 else
613 currentSet->removeChar( currentChar );
614 setCurrentChar( pc );
615 }
616}
617
618void QIMPenEdit::defaultChars()
619{
620 if ( currentCode ) {
621 currentChar = 0;
622 bool haveSystem = FALSE;
623 QIMPenCharIterator it(currentSet->characters() );
624 for ( ; it.current(); ++it ) {
625 if ( it.current()->character() == currentCode &&
626 it.current()->testFlag( QIMPenChar::System ) ) {
627 haveSystem = TRUE;
628 break;
629 }
630 }
631 if ( haveSystem ) {
632 it.toFirst();
633 while ( it.current() ) {
634 QIMPenChar *pc = it.current();
635 ++it;
636 if ( pc->character() == currentCode ) {
637 if ( pc->testFlag( QIMPenChar::System ) ) {
638 pc->clearFlag( QIMPenChar::Deleted );
639 if ( !currentChar )
640 currentChar = pc;
641 } else {
642 currentSet->removeChar( pc );
643 }
644 }
645 }
646 setCurrentChar( currentChar );
647 }
648 }
649}
650
651void QIMPenEdit::newStroke( QIMPenStroke *st )
652{
653 inputChar->addStroke( st );
654 enableButtons();
655}
656