Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

qimpensetup.cpp

Go to the documentation of this file.
00001 /**********************************************************************
00002 ** Copyright (C) 2000-2002 Trolltech AS.  All rights reserved.
00003 **
00004 ** This file is part of the Qtopia Environment.
00005 **
00006 ** This file may be distributed and/or modified under the terms of the
00007 ** GNU General Public License version 2 as published by the Free Software
00008 ** Foundation and appearing in the file LICENSE.GPL included in the
00009 ** packaging of this file.
00010 **
00011 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00012 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00013 **
00014 ** See http://www.trolltech.com/gpl/ for GPL licensing information.
00015 **
00016 ** Contact info@trolltech.com if any conditions of this licensing are
00017 ** not clear to you.
00018 **
00019 **********************************************************************/
00020 
00021 #include "qimpenwidget.h"
00022 #include "qimpenprefbase.h"
00023 #include "qimpensetup.h"
00024 
00025 #include <qpe/qpeapplication.h>
00026 #include <qpe/config.h>
00027 
00028 #include <qcombobox.h>
00029 #include <qlistbox.h>
00030 #include <qlabel.h>
00031 #include <qpushbutton.h>
00032 #include <qlayout.h>
00033 #include <qpixmap.h>
00034 #include <qbuttongroup.h>
00035 #include <qslider.h>
00036 #include <qtabwidget.h>
00037 #include <qdir.h>
00038 #include <qmessagebox.h>
00039 #include <opie2/odebug.h>
00040 
00041 
00042 /* XPM */
00043 static const char * const left_xpm[] = {
00044 "16 16 2 1",
00045 "       c None",
00046 ".      c #000000",
00047 "                ",
00048 "                ",
00049 "                ",
00050 "        .       ",
00051 "       ..       ",
00052 "      ...       ",
00053 "     ....       ",
00054 "    .....       ",
00055 "   ......       ",
00056 "    .....       ",
00057 "     ....       ",
00058 "      ...       ",
00059 "       ..       ",
00060 "        .       ",
00061 "                ",
00062 "                "};
00063 
00064 
00065 /* XPM */
00066 static const char * const right_xpm[] = {
00067 "16 16 2 1",
00068 "       c None",
00069 ".      c #000000",
00070 "                ",
00071 "                ",
00072 "                ",
00073 "     .          ",
00074 "     ..         ",
00075 "     ...        ",
00076 "     ....       ",
00077 "     .....      ",
00078 "     ......     ",
00079 "     .....      ",
00080 "     ....       ",
00081 "     ...        ",
00082 "     ..         ",
00083 "     .          ",
00084 "                ",
00085 "                "};
00086 
00087 
00088 
00089 QIMPenSetup::QIMPenSetup( QIMPenProfile *p, QWidget *parent,
00090                 const char *name, bool modal, int WFlags )
00091     : QDialog( parent, name, modal, WFlags ), profileCombo(0), profile(p)
00092 {
00093     setCaption( tr("Setup Handwriting Input") );
00094 
00095     QVBoxLayout *vb = new QVBoxLayout( this );
00096 
00097 #define MULTIPROFILE
00098 #ifdef MULTIPROFILE
00099     profileList.setAutoDelete( true );
00100     QHBoxLayout *hb = new QHBoxLayout( vb );
00101     hb->setMargin( 6 );
00102     QLabel *l = new QLabel( tr("Character Profile:"), this );
00103     hb->addWidget( l );
00104     profileCombo = new QComboBox( this );
00105     connect( profileCombo, SIGNAL(activated(const QString&)),
00106              this, SLOT(selectProfile(const QString&)) );
00107     hb->addWidget( profileCombo );
00108 #else
00109     profileList.append( profile );
00110 #endif
00111 
00112     owarn << "profiles: " << profileList.count() << oendl;
00113     
00114     QTabWidget *tw = new QTabWidget( this );
00115     vb->addWidget( tw );
00116 
00117     pref = new QIMPenPrefBase( this );
00118     tw->addTab( pref, tr("Preferences") );
00119 
00120     pref->inputStyle->setExclusive( TRUE );
00121 
00122     style = profile->style() == QIMPenProfile::ToggleCases ? 1 : 0;
00123     pref->inputStyle->setButton( style );
00124     connect( pref->inputStyle, SIGNAL(clicked(int)),
00125              this, SLOT(styleClicked(int)) );
00126     pref->inputStyle->setEnabled( profile->canSelectStyle() );
00127 
00128     multiTimeout = profile->multiStrokeTimeout();
00129     pref->multiStrokeSlider->setValue( multiTimeout );
00130     multiTimeoutChanged( multiTimeout );
00131     connect( pref->multiStrokeSlider, SIGNAL(valueChanged(int)),
00132              this, SLOT(multiTimeoutChanged(int)) );
00133 
00134     edit = new QIMPenEdit( p, tw );
00135     tw->addTab( edit, tr("Customize") );
00136 #ifdef MULTIPROFILE
00137     loadProfiles();
00138 #endif
00139 
00140 }
00141 
00142 void QIMPenSetup::loadProfiles()
00143 {
00144     QString path = QPEApplication::qpeDir() + "etc/qimpen";
00145     QDir dir( path, "*.conf" );
00146     QStringList list = dir.entryList();
00147     QStringList::Iterator it;
00148     for ( it = list.begin(); it != list.end(); ++it ) {
00149         QIMPenProfile *p = new QIMPenProfile( path + "/" + *it );
00150         profileList.append( p );
00151         profileCombo->insertItem( p->name() );
00152         if ( p->name() == profile->name() ) {
00153             profileCombo->setCurrentItem( profileCombo->count()-1 );
00154             profile = p;
00155             edit->setProfile( profile );
00156         }
00157     }
00158 }
00159 
00160 void QIMPenSetup::styleClicked( int id )
00161 {
00162     style = id;
00163 }
00164 
00165 void QIMPenSetup::multiTimeoutChanged( int v )
00166 {
00167     multiTimeout = v;
00168     pref->multiStrokeLabel->setText( tr("%1 ms").arg(v) );
00169 }
00170 
00171 void QIMPenSetup::selectProfile( const QString &p )
00172 {
00173     if ( p == profile->name() )
00174         return;
00175 
00176     profile->setStyle( style ? QIMPenProfile::ToggleCases : QIMPenProfile::BothCases );
00177     profile->setMultiStrokeTimeout( multiTimeout );
00178 
00179     for ( int i = 0; i < (int)profileList.count(); i++ ) {
00180         if ( profileList.at(i)->name() == p ) {
00181             profile = profileList.at(i);
00182             style = profile->style() == QIMPenProfile::ToggleCases ? 1 : 0;
00183             pref->inputStyle->setButton( style );
00184             pref->inputStyle->setEnabled( profile->canSelectStyle() );
00185             multiTimeout = profile->multiStrokeTimeout();
00186             pref->multiStrokeSlider->setValue( multiTimeout );
00187             multiTimeoutChanged( multiTimeout );
00188             edit->setProfile( profile );
00189             break;
00190         }
00191     }
00192 }
00193 
00194 void QIMPenSetup::accept()
00195 {
00196     profile->setStyle( style ? QIMPenProfile::ToggleCases : QIMPenProfile::BothCases );
00197     profile->setMultiStrokeTimeout( multiTimeout );
00198     // Save current profile
00199     if ( profileCombo ) {
00200         Config config( "handwriting" );
00201         config.setGroup( "Settings" );
00202         config.writeEntry( "Profile", profileCombo->currentText() );
00203     }
00204     // Save charsets
00205     bool ok = TRUE;
00206     for ( int i = 0; i < (int)profileList.count(); i++ ) {
00207         QIMPenProfile *prof = profileList.at(i);
00208         QIMPenCharSetIterator it(prof->charSets());
00209         for ( ; it.current(); ++it ) {
00210             if ( !(it.current()->save( QIMPenCharSet::User )) ) {
00211                 ok = FALSE;
00212                 break;
00213             }
00214         }
00215     }
00216     if ( !ok ) {
00217         if ( QMessageBox::critical( 0, tr( "Out of space" ),
00218                     tr("Unable to save information.\n"
00219                         "Free up some space\n"
00220                         "and try again.\n"
00221                         "\nQuit anyway?"),
00222                     QMessageBox::Yes|QMessageBox::Escape,
00223                     QMessageBox::No|QMessageBox::Default )
00224                 != QMessageBox::No ) {
00225             QDialog::accept();
00226         }
00227     } else {
00228         QDialog::accept();
00229     }
00230 }
00231 
00232 //---------------------------------------------------------------------------
00233 
00234 QIMPenInputCharDlg::QIMPenInputCharDlg( QWidget *parent, const char *name,
00235         bool modal, int WFlags)
00236     : QDialog( parent, name, modal, WFlags )
00237 {
00238     setCaption( tr("Enter new character") );
00239     uni = 0;
00240 
00241     QVBoxLayout *vb = new QVBoxLayout( this, 10 );
00242 
00243     QHBoxLayout *hb = new QHBoxLayout();
00244     vb->addLayout( hb );
00245 
00246     QLabel *label = new QLabel( tr("Character:"), this );
00247     hb->addWidget( label );
00248 
00249     QComboBox *cb = new QComboBox( TRUE, this );
00250     connect( cb, SIGNAL(activated(int)), SLOT(setSpecial(int)) );
00251     connect( cb, SIGNAL(textChanged(const QString&)),
00252             SLOT(setCharacter(const QString&)) );
00253     addSpecial( cb );
00254     cb->setEditText( "" );
00255     hb->addWidget( cb );
00256 
00257     hb = new QHBoxLayout();
00258     vb->addLayout( hb );
00259 
00260     QPushButton *pb = new QPushButton( "OK", this );
00261     connect( pb, SIGNAL(clicked()), SLOT(accept()));
00262     hb->addWidget( pb );
00263     pb = new QPushButton( "Cancel", this );
00264     connect( pb, SIGNAL(clicked()), SLOT(reject()));
00265     hb->addWidget( pb );
00266 
00267     cb->setFocus();
00268 }
00269 
00270 void QIMPenInputCharDlg::addSpecial( QComboBox *cb )
00271 {
00272     int i = 0;
00273     while ( qimpen_specialKeys[i].code != Key_unknown ) {
00274         cb->insertItem( qimpen_specialKeys[i].name );
00275         i++;
00276     }
00277 }
00278 
00279 void QIMPenInputCharDlg::setSpecial( int sp )
00280 {
00281     uni = qimpen_specialKeys[sp].code << 16;
00282 }
00283 
00284 void QIMPenInputCharDlg::setCharacter( const QString &string )
00285 {
00286     uni = string[0].unicode();
00287 }
00288 
00289 //---------------------------------------------------------------------------
00290 
00291 class CharListItem : public QListBoxText
00292 {
00293 public:
00294     CharListItem( const QString &text, uint c )
00295         : QListBoxText( text )
00296     {
00297         _code = c;
00298     }
00299 
00300     uint code() const { return _code; }
00301 
00302 protected:
00303     uint _code;
00304 };
00305 
00313 QIMPenEdit::QIMPenEdit( QIMPenProfile *p, QWidget *parent,
00314                 const char *name )
00315     : QWidget( parent, name ), profile(p)
00316 {
00317     currentChar = 0;
00318     currentCode = 0;
00319     inputChar = new QIMPenChar();
00320 
00321     QVBoxLayout *tvb = new QVBoxLayout( this, 5 );
00322 
00323     QGridLayout *gl = new QGridLayout( tvb, 4, 2 );
00324     gl->setRowStretch( 1, 1 );
00325     gl->addRowSpacing( 2, 35 );
00326     gl->addRowSpacing( 3, 35 );
00327 
00328     charSetCombo = new QComboBox( this );
00329     gl->addMultiCellWidget( charSetCombo, 0, 0, 0, 1 );
00330     connect( charSetCombo, SIGNAL(activated(int)), SLOT(selectCharSetVisible(int)));
00331     QIMPenCharSetIterator it( profile->charSets() );
00332     for ( ; it.current(); ++it ) {
00333         charSetCombo->insertItem( it.current()->description() );
00334     }
00335 
00336     charList = new QListBox( this );
00337     charList->setMinimumHeight( charList->sizeHint().height() );
00338     connect( charList, SIGNAL(highlighted(int)), SLOT(selectChar(int)) );
00339     gl->addWidget( charList, 1, 0 );
00340 
00341     pw = new QIMPenWidget( this );
00342     pw->setFixedHeight( 75 );
00343     gl->addMultiCellWidget( pw, 2, 3, 0, 0 );
00344     connect( pw, SIGNAL(stroke(QIMPenStroke*)),
00345                  SLOT(newStroke(QIMPenStroke*)) );
00346 
00347     QVBoxLayout *vb = new QVBoxLayout();
00348     gl->addLayout( vb, 1, 1 );
00349     newBtn = new QPushButton( tr("New..."), this );
00350     connect( newBtn, SIGNAL(clicked()), SLOT(addNewChar()) );
00351     vb->addWidget( newBtn );
00352 
00353     addBtn = new QPushButton( tr("Add"), this );
00354     connect( addBtn, SIGNAL(clicked()), SLOT(addChar()) );
00355     vb->addWidget( addBtn );
00356 
00357     removeBtn = new QPushButton( tr("Remove"), this );
00358     connect( removeBtn, SIGNAL(clicked()), SLOT(removeChar()) );
00359     vb->addWidget( removeBtn );
00360 
00361     QPushButton *pb = new QPushButton( tr("Default"), this );
00362     connect( pb, SIGNAL(clicked()), SLOT(defaultChars()) );
00363     vb->addWidget( pb );
00364 
00365     QHBoxLayout *hb = new QHBoxLayout();
00366     gl->addLayout( hb, 2, 1 );
00367     prevBtn = new QPushButton( this );
00368     prevBtn->setPixmap( QPixmap( (const char **)left_xpm ) );
00369     connect( prevBtn, SIGNAL(clicked()), SLOT(prevChar()));
00370     hb->addWidget( prevBtn );
00371 
00372     nextBtn = new QPushButton( this );
00373     nextBtn->setPixmap( QPixmap( (const char **)right_xpm ) );
00374     connect( nextBtn, SIGNAL(clicked()), SLOT(nextChar()));
00375     hb->addWidget( nextBtn );
00376 
00377     pb = new QPushButton( tr("Clear"), this );
00378     connect( pb, SIGNAL(clicked()), SLOT(clearChar()) );
00379     gl->addWidget( pb, 3, 1 );
00380 
00381     //--
00382 #if !defined(Q_WS_QWS)
00383     hb = new QHBoxLayout( tvb );
00384     pb = new QPushButton( tr("OK"), this );
00385     connect( pb, SIGNAL(clicked()), SLOT(accept()) );
00386     hb->addWidget( pb );
00387 
00388     pb = new QPushButton( tr("Cancel"), this );
00389     connect( pb, SIGNAL(clicked()), SLOT(reject()) );
00390     hb->addWidget( pb );
00391 #endif
00392     selectCharSetVisible( 0 );
00393     charList->setFocus();
00394 
00395     resize( minimumSize() );
00396     enableButtons();
00397 }
00398 
00399 void QIMPenEdit::setProfile( QIMPenProfile *p )
00400 {
00401     profile = p;
00402     charSetCombo->clear();
00403     QIMPenCharSetIterator it( profile->charSets() );
00404     for ( ; it.current(); ++it ) {
00405         if ( ! it.current()->hidden() )
00406             charSetCombo->insertItem( it.current()->description() );
00407     }
00408     selectCharSetVisible( 0 );
00409     charList->setFocus();
00410     enableButtons();
00411 }
00412 
00413 void QIMPenEdit::selectCharSet( QIMPenCharSet *c )
00414 {
00415     int i = 0;
00416     QIMPenCharSetIterator it( profile->charSets() );
00417     for ( ; it.current(); ++it, i++ ) {
00418         if ( it.current() == c ) {
00419             charSetCombo->setCurrentItem( i );
00420             selectCharSet( i );
00421         }
00422     }
00423 }
00424 
00425 
00430 void QIMPenEdit::fillCharList()
00431 {
00432     charList->clear();
00433     QIMPenCharIterator it( currentSet->characters() );
00434     CharListItem *li = 0;
00435     for ( ; it.current(); ++it ) {
00436         uint ch = it.current()->character();
00437         QString n = it.current()->name();
00438         if ( !n.isEmpty() )
00439             li = new CharListItem( n, ch );
00440         if ( li ) {
00441             CharListItem *i = (CharListItem *)charList->findItem( li->text() );
00442             if ( !i || i->code() != ch ) {
00443                 charList->insertItem( li );
00444             } else {
00445                 delete li;
00446                 li = 0;
00447             }
00448         }
00449     }
00450     currentChar = 0;
00451 }
00452 
00453 void QIMPenEdit::enableButtons()
00454 {
00455     bool add =  !inputChar->isEmpty();
00456     newBtn->setEnabled( add );
00457     addBtn->setEnabled( add );
00458     removeBtn->setEnabled( currentChar );
00459 }
00460 
00465 QIMPenChar *QIMPenEdit::findPrev()
00466 {
00467     if ( !currentChar )
00468         return 0;
00469     QIMPenCharIterator it( currentSet->characters() );
00470     bool found = FALSE;
00471     for ( it.toLast(); it.current(); --it ) {
00472         if ( !found && it.current() == currentChar )
00473             found = TRUE;
00474         else if ( found && it.current()->character() == currentCode &&
00475                 !it.current()->testFlag( QIMPenChar::Deleted ) ) {
00476             return it.current();
00477         }
00478     }
00479 
00480     return 0;
00481 }
00482 
00487 QIMPenChar *QIMPenEdit::findNext()
00488 {
00489     if ( !currentChar )
00490         return 0;
00491     QIMPenCharIterator it( currentSet->characters() );
00492     bool found = FALSE;
00493     for ( ; it.current(); ++it ) {
00494         if ( !found && it.current() == currentChar )
00495             found = TRUE;
00496         else if ( found && it.current()->character() == currentCode &&
00497                     !it.current()->testFlag( QIMPenChar::Deleted ) ) {
00498             return it.current();
00499         }
00500     }
00501 
00502     return 0;
00503 }
00504 
00505 void QIMPenEdit::setCurrentChar( QIMPenChar *pc )
00506 {
00507     currentChar = pc;
00508     pw->showCharacter( currentChar );
00509     if ( currentChar ) {
00510         prevBtn->setEnabled( findPrev() != 0 );
00511         nextBtn->setEnabled( findNext() != 0 );
00512     }
00513 }
00514 
00515 void QIMPenEdit::prevChar()
00516 {
00517     QIMPenChar *pc = findPrev();
00518     if ( pc )
00519         setCurrentChar( pc );
00520 }
00521 
00522 void QIMPenEdit::nextChar()
00523 {
00524     QIMPenChar *pc = findNext();
00525     if ( pc )
00526         setCurrentChar( pc );
00527 }
00528 
00529 void QIMPenEdit::clearChar()
00530 {
00531     inputChar->clear();
00532     pw->clear();
00533     enableButtons();
00534 }
00535 
00536 void QIMPenEdit::selectChar( int i )
00537 {
00538     currentChar = 0;
00539     currentCode = ((CharListItem *)charList->item(i))->code();
00540     QIMPenCharIterator it(currentSet->characters() );
00541     for ( ; it.current(); ++it ) {
00542         if ( it.current()->character() == currentCode &&
00543              !it.current()->testFlag( QIMPenChar::Deleted ) ) {
00544             setCurrentChar( it.current() );
00545             break;
00546         }
00547     }
00548     if ( !it.current() )
00549         setCurrentChar( 0 );
00550     inputChar->clear();
00551 }
00552 
00553 void QIMPenEdit::selectCharSetVisible( int c )
00554 {
00555     int i = 0;
00556     QIMPenCharSetIterator it( profile->charSets() );
00557     for ( ; it.current(); ++it, i++ ) {
00558         if ( charSetCombo->text( c ) == it.current()->description() ) {
00559             selectCharSet( i );
00560         }
00561     }
00562 }
00563 
00564 void QIMPenEdit::selectCharSet( int i )
00565 {
00566     if ( currentSet )
00567         pw->removeCharSet( 0 );
00568     currentSet = profile->charSets().at( i );
00569     fillCharList();
00570     pw->insertCharSet( currentSet );
00571     inputChar->clear();
00572     if ( charList->count() ) {
00573         charList->setSelected( 0, TRUE );
00574         selectChar(0);
00575     }
00576 }
00577 
00578 void QIMPenEdit::addChar()
00579 {
00580     if ( !inputChar->isEmpty() ) {
00581         QIMPenChar *pc = new QIMPenChar( *inputChar );
00582         pc->setCharacter( currentCode );
00583 
00584         // User characters override all matching system characters.
00585         // Copy and mark deleted identical system characters.
00586 
00587         QIMPenCharIterator it(currentSet->characters() );
00588         QIMPenChar *sc = 0;
00589         while ( (sc = it.current()) != 0 ) {
00590             ++it;
00591             if ( sc->character() == currentCode &&
00592                  sc->testFlag( QIMPenChar::System ) &&
00593                  !sc->testFlag( QIMPenChar::Deleted ) ) {
00594                 QIMPenChar *cc = new QIMPenChar( *sc );
00595                 cc->clearFlag( QIMPenChar::System );
00596                 currentSet->addChar( cc );
00597                 sc->setFlag( QIMPenChar::Deleted );
00598             }
00599         }
00600 
00601         currentSet->addChar( pc );
00602         setCurrentChar( pc );
00603         inputChar->clear();
00604     }
00605 }
00606 
00607 void QIMPenEdit::addNewChar()
00608 {
00609     if ( !inputChar->isEmpty() ) {
00610         QIMPenInputCharDlg dlg( 0, 0, TRUE );
00611         if ( dlg.exec() ) {
00612             currentCode = dlg.unicode();
00613             addChar();
00614             fillCharList();
00615             for ( unsigned int i = 0; i < charList->count(); i++ ) {
00616                 CharListItem *li = (CharListItem *)charList->item(i);
00617                 if ( li->code() == dlg.unicode() ) {
00618                     charList->setSelected( i, TRUE );
00619                     break;
00620                 }
00621             }
00622         }
00623     }
00624 }
00625 
00626 void QIMPenEdit::removeChar()
00627 {
00628     if ( currentChar ) {
00629         QIMPenChar *pc = findPrev();
00630         if ( !pc ) pc = findNext();
00631         if ( currentChar->testFlag( QIMPenChar::System ) )
00632             currentChar->setFlag( QIMPenChar::Deleted );
00633         else
00634             currentSet->removeChar( currentChar );
00635         setCurrentChar( pc );
00636     }
00637 }
00638 
00639 void QIMPenEdit::defaultChars()
00640 {
00641     if ( currentCode ) {
00642         currentChar = 0;
00643         bool haveSystem = FALSE;
00644         QIMPenCharIterator it(currentSet->characters() );
00645         for ( ; it.current(); ++it ) {
00646             if ( it.current()->character() == currentCode &&
00647                  it.current()->testFlag( QIMPenChar::System ) ) {
00648                 haveSystem = TRUE;
00649                 break;
00650             }
00651         }
00652         if ( haveSystem ) {
00653             it.toFirst();
00654             while ( it.current() ) {
00655                 QIMPenChar *pc = it.current();
00656                 ++it;
00657                 if ( pc->character() == currentCode ) {
00658                     if ( pc->testFlag( QIMPenChar::System ) ) {
00659                         pc->clearFlag( QIMPenChar::Deleted );
00660                         if ( !currentChar )
00661                             currentChar = pc;
00662                     } else {
00663                         currentSet->removeChar( pc );
00664                     }
00665                 }
00666             }
00667             setCurrentChar( currentChar );
00668         }
00669     }
00670 }
00671 
00672 void QIMPenEdit::newStroke( QIMPenStroke *st )
00673 {
00674     inputChar->addStroke( st );
00675     enableButtons();
00676 }
00677 

Generated on Sat Nov 5 16:16:01 2005 for OPIE by  doxygen 1.4.2