kcharselect.cpp
00001 /* This file is part of the KDE libraries 00002 00003 Copyright (C) 1999 Reginald Stadlbauer <reggie@kde.org> 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License as published by the Free Software Foundation; either 00008 version 2 of the License, or (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 You should have received a copy of the GNU Library General Public License 00016 along with this library; see the file COPYING.LIB. If not, write to 00017 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00018 Boston, MA 02110-1301, USA. 00019 */ 00020 00021 #include "kcharselect.h" 00022 #include "kcharselect.moc" 00023 00024 #include <tqbrush.h> 00025 #include <tqcolor.h> 00026 #include <tqevent.h> 00027 #include <tqfont.h> 00028 #include <tqfontdatabase.h> 00029 #include <tqhbox.h> 00030 #include <tqkeycode.h> 00031 #include <tqlabel.h> 00032 #include <tqpainter.h> 00033 #include <tqpen.h> 00034 #include <tqregexp.h> 00035 #include <tqstyle.h> 00036 #include <tqtooltip.h> 00037 #include <tqvalidator.h> 00038 00039 #include <tdeapplication.h> 00040 #include <kdebug.h> 00041 #include <kdialog.h> 00042 #include <klineedit.h> 00043 #include <tdelocale.h> 00044 00045 class KCharSelect::KCharSelectPrivate 00046 { 00047 public: 00048 TQLineEdit *unicodeLine; 00049 }; 00050 00051 TQFontDatabase * KCharSelect::fontDataBase = 0; 00052 00053 void KCharSelect::cleanupFontDatabase() 00054 { 00055 delete fontDataBase; 00056 fontDataBase = 0; 00057 } 00058 00059 /******************************************************************/ 00060 /* Class: KCharSelectTable */ 00061 /******************************************************************/ 00062 00063 //================================================================== 00064 KCharSelectTable::KCharSelectTable( TQWidget *parent, const char *name, const TQString &_font, 00065 const TQChar &_chr, int _tableNum ) 00066 : TQGridView( parent, name ), vFont( _font ), vChr( _chr ), 00067 vTableNum( _tableNum ), vPos( 0, 0 ), focusItem( _chr ), focusPos( 0, 0 ), d(0) 00068 { 00069 setBackgroundColor( colorGroup().base() ); 00070 00071 setCellWidth( 20 ); 00072 setCellHeight( 25 ); 00073 00074 setNumCols( 32 ); 00075 setNumRows( 8 ); 00076 00077 repaintContents( false ); 00078 00079 setToolTips(); 00080 00081 setFocusPolicy( TQ_StrongFocus ); 00082 setBackgroundMode( TQWidget::NoBackground ); 00083 } 00084 00085 //================================================================== 00086 void KCharSelectTable::setFont( const TQString &_font ) 00087 { 00088 vFont = _font; 00089 repaintContents( false ); 00090 00091 setToolTips(); 00092 } 00093 00094 //================================================================== 00095 void KCharSelectTable::setChar( const TQChar &_chr ) 00096 { 00097 vChr = _chr; 00098 repaintContents( false ); 00099 } 00100 00101 //================================================================== 00102 void KCharSelectTable::setTableNum( int _tableNum ) 00103 { 00104 focusItem = TQChar( _tableNum * 256 ); 00105 00106 vTableNum = _tableNum; 00107 repaintContents( false ); 00108 00109 setToolTips(); 00110 } 00111 00112 //================================================================== 00113 TQSize KCharSelectTable::sizeHint() const 00114 { 00115 int w = cellWidth(); 00116 int h = cellHeight(); 00117 00118 w *= numCols(); 00119 h *= numRows(); 00120 00121 return TQSize( w, h ); 00122 } 00123 00124 //================================================================== 00125 void KCharSelectTable::resizeEvent( TQResizeEvent * e ) 00126 { 00127 const int new_w = (e->size().width() - 2*(margin()+frameWidth())) / numCols(); 00128 const int new_h = (e->size().height() - 2*(margin()+frameWidth())) / numRows(); 00129 00130 if( new_w != cellWidth()) 00131 setCellWidth( new_w ); 00132 if( new_h != cellHeight()) 00133 setCellHeight( new_h ); 00134 00135 setToolTips(); 00136 } 00137 00138 //================================================================== 00139 void KCharSelectTable::paintCell( class TQPainter* p, int row, int col ) 00140 { 00141 const int w = cellWidth(); 00142 const int h = cellHeight(); 00143 const int x2 = w - 1; 00144 const int y2 = h - 1; 00145 00146 //if( row == 0 && col == 0 ) { 00147 // printf("Repaint %d\n", temp++); 00148 // fflush( stdout ); 00149 // } 00150 00151 TQFont font = TQFont( vFont ); 00152 font.setPixelSize( int(.7 * h) ); 00153 00154 unsigned short c = vTableNum * 256; 00155 c += row * numCols(); 00156 c += col; 00157 00158 if ( c == vChr.unicode() ) { 00159 p->setBrush( TQBrush( colorGroup().highlight() ) ); 00160 p->setPen( NoPen ); 00161 p->drawRect( 0, 0, w, h ); 00162 p->setPen( colorGroup().highlightedText() ); 00163 vPos = TQPoint( col, row ); 00164 } else { 00165 TQFontMetrics fm = TQFontMetrics( font ); 00166 if( fm.inFont( c ) ) 00167 p->setBrush( TQBrush( colorGroup().base() ) ); 00168 else 00169 p->setBrush( TQBrush( colorGroup().button() ) ); 00170 p->setPen( NoPen ); 00171 p->drawRect( 0, 0, w, h ); 00172 p->setPen( colorGroup().text() ); 00173 } 00174 00175 if ( c == focusItem.unicode() && hasFocus() ) { 00176 style().tqdrawPrimitive( TQStyle::PE_FocusRect, p, TQRect( 2, 2, w - 4, h - 4 ), 00177 colorGroup() ); 00178 focusPos = TQPoint( col, row ); 00179 } 00180 00181 p->setFont( font ); 00182 00183 p->drawText( 0, 0, x2, y2, AlignHCenter | AlignVCenter, TQString( TQChar( c ) ) ); 00184 00185 p->setPen( colorGroup().text() ); 00186 p->drawLine( x2, 0, x2, y2 ); 00187 p->drawLine( 0, y2, x2, y2 ); 00188 00189 if ( row == 0 ) 00190 p->drawLine( 0, 0, x2, 0 ); 00191 if ( col == 0 ) 00192 p->drawLine( 0, 0, 0, y2 ); 00193 } 00194 00195 //================================================================== 00196 void KCharSelectTable::mouseMoveEvent( TQMouseEvent *e ) 00197 { 00198 const int row = rowAt( e->y() ); 00199 const int col = columnAt( e->x() ); 00200 if ( row >= 0 && row < numRows() && col >= 0 && col < numCols() ) { 00201 const TQPoint oldPos = vPos; 00202 00203 vPos.setX( col ); 00204 vPos.setY( row ); 00205 00206 vChr = TQChar( vTableNum * 256 + numCols() * vPos.y() + vPos.x() ); 00207 00208 const TQPoint oldFocus = focusPos; 00209 00210 focusPos = vPos; 00211 focusItem = vChr; 00212 00213 repaintCell( oldFocus.y(), oldFocus.x(), true ); 00214 repaintCell( oldPos.y(), oldPos.x(), true ); 00215 repaintCell( vPos.y(), vPos.x(), true ); 00216 00217 emit highlighted( vChr ); 00218 emit highlighted(); 00219 00220 emit focusItemChanged( focusItem ); 00221 emit focusItemChanged(); 00222 } 00223 } 00224 00225 //================================================================== 00226 void KCharSelectTable::keyPressEvent( TQKeyEvent *e ) 00227 { 00228 switch ( e->key() ) { 00229 case Key_Left: 00230 gotoLeft(); 00231 break; 00232 case Key_Right: 00233 gotoRight(); 00234 break; 00235 case Key_Up: 00236 gotoUp(); 00237 break; 00238 case Key_Down: 00239 gotoDown(); 00240 break; 00241 case Key_Next: 00242 emit tableDown(); 00243 break; 00244 case Key_Prior: 00245 emit tableUp(); 00246 break; 00247 case Key_Space: 00248 emit activated( ' ' ); 00249 emit activated(); 00250 emit highlighted( ' ' ); 00251 emit highlighted(); 00252 break; 00253 case Key_Enter: case Key_Return: { 00254 const TQPoint oldPos = vPos; 00255 00256 vPos = focusPos; 00257 vChr = focusItem; 00258 00259 repaintCell( oldPos.y(), oldPos.x(), true ); 00260 repaintCell( vPos.y(), vPos.x(), true ); 00261 00262 emit activated( vChr ); 00263 emit activated(); 00264 emit highlighted( vChr ); 00265 emit highlighted(); 00266 } break; 00267 } 00268 } 00269 00270 //================================================================== 00271 void KCharSelectTable::gotoLeft() 00272 { 00273 if ( focusPos.x() > 0 ) { 00274 const TQPoint oldPos = focusPos; 00275 00276 focusPos.setX( focusPos.x() - 1 ); 00277 00278 focusItem = TQChar( vTableNum * 256 + numCols() * focusPos.y() + focusPos.x() ); 00279 00280 repaintCell( oldPos.y(), oldPos.x(), true ); 00281 repaintCell( focusPos.y(), focusPos.x(), true ); 00282 00283 emit focusItemChanged( vChr ); 00284 emit focusItemChanged(); 00285 } 00286 } 00287 00288 //================================================================== 00289 void KCharSelectTable::gotoRight() 00290 { 00291 if ( focusPos.x() < numCols()-1 ) { 00292 const TQPoint oldPos = focusPos; 00293 00294 focusPos.setX( focusPos.x() + 1 ); 00295 00296 focusItem = TQChar( vTableNum * 256 + numCols() * focusPos.y() + focusPos.x() ); 00297 00298 repaintCell( oldPos.y(), oldPos.x(), true ); 00299 repaintCell( focusPos.y(), focusPos.x(), true ); 00300 00301 emit focusItemChanged( vChr ); 00302 emit focusItemChanged(); 00303 } 00304 } 00305 00306 //================================================================== 00307 void KCharSelectTable::gotoUp() 00308 { 00309 if ( focusPos.y() > 0 ) { 00310 const TQPoint oldPos = focusPos; 00311 00312 focusPos.setY( focusPos.y() - 1 ); 00313 00314 focusItem = TQChar( vTableNum * 256 + numCols() * focusPos.y() + focusPos.x() ); 00315 00316 repaintCell( oldPos.y(), oldPos.x(), true ); 00317 repaintCell( focusPos.y(), focusPos.x(), true ); 00318 00319 emit focusItemChanged( vChr ); 00320 emit focusItemChanged(); 00321 } 00322 } 00323 00324 //================================================================== 00325 void KCharSelectTable::gotoDown() 00326 { 00327 if ( focusPos.y() < numRows()-1 ) { 00328 const TQPoint oldPos = focusPos; 00329 00330 focusPos.setY( focusPos.y() + 1 ); 00331 00332 focusItem = TQChar( vTableNum * 256 + numCols() * focusPos.y() + focusPos.x() ); 00333 00334 repaintCell( oldPos.y(), oldPos.x(), true ); 00335 repaintCell( focusPos.y(), focusPos.x(), true ); 00336 00337 emit focusItemChanged( vChr ); 00338 emit focusItemChanged(); 00339 } 00340 } 00341 00342 //================================================================== 00343 void KCharSelectTable::setToolTips() 00344 { 00345 const int rowCount = numRows(); 00346 const int colCount = numCols(); 00347 for( int i=0 ; i< rowCount; ++i ) 00348 { 00349 for( int j=0; j< colCount; ++j ) 00350 { 00351 const TQRect r( cellWidth()*j, cellHeight()*i, cellWidth(), cellHeight() ); 00352 TQToolTip::remove(this,r); 00353 const ushort uni = vTableNum * 256 + numCols()*i + j; 00354 TQString s; 00355 s.sprintf( "%04X", uint( uni ) ); 00356 TQString character; // Character (which sometimes need to be escaped) 00357 switch ( uni ) 00358 { 00359 case 0x3c: character = "<"; break; 00360 case 0x3e: character = ">"; break; 00361 case 0x26: character = "&"; break; 00362 case 0x27: character = "'"; break; 00363 case 0x22: character = """; break; 00364 default: character = TQChar( uni ); break; 00365 } 00366 TQToolTip::add(this, r, i18n( "Character","<qt><font size=\"+4\" face=\"%1\">%2</font><br>Unicode code point: U+%3<br>(In decimal: %4)<br>(Character: %5)</qt>" ).arg( vFont ).arg( character ).arg( s ).arg( uni ).arg( character ) ); 00367 } 00368 } 00369 } 00370 00371 /******************************************************************/ 00372 /* Class: KCharSelect */ 00373 /******************************************************************/ 00374 00375 //================================================================== 00376 KCharSelect::KCharSelect( TQWidget *parent, const char *name, const TQString &_font, const TQChar &_chr, int _tableNum ) 00377 : TQVBox( parent, name ), d(new KCharSelectPrivate) 00378 { 00379 setSpacing( KDialog::spacingHint() ); 00380 TQHBox* const bar = new TQHBox( this ); 00381 bar->setSpacing( KDialog::spacingHint() ); 00382 00383 TQLabel* const lFont = new TQLabel( i18n( "Font:" ), bar ); 00384 lFont->resize( lFont->sizeHint() ); 00385 lFont->setAlignment( Qt::AlignRight | Qt::AlignVCenter ); 00386 lFont->setMaximumWidth( lFont->sizeHint().width() ); 00387 00388 fontCombo = new TQComboBox( true, bar ); 00389 fillFontCombo(); 00390 fontCombo->resize( fontCombo->sizeHint() ); 00391 00392 connect( fontCombo, TQT_SIGNAL( activated( const TQString & ) ), this, TQT_SLOT( fontSelected( const TQString & ) ) ); 00393 00394 TQLabel* const lTable = new TQLabel( i18n( "Table:" ), bar ); 00395 lTable->resize( lTable->sizeHint() ); 00396 lTable->setAlignment( Qt::AlignRight | Qt::AlignVCenter ); 00397 lTable->setMaximumWidth( lTable->sizeHint().width() ); 00398 00399 tableSpinBox = new TQSpinBox( 0, 255, 1, bar ); 00400 tableSpinBox->resize( tableSpinBox->sizeHint() ); 00401 00402 connect( tableSpinBox, TQT_SIGNAL( valueChanged( int ) ), this, TQT_SLOT( tableChanged( int ) ) ); 00403 00404 TQLabel* const lUnicode = new TQLabel( i18n( "&Unicode code point:" ), bar ); 00405 lUnicode->resize( lUnicode->sizeHint() ); 00406 lUnicode->setAlignment( Qt::AlignRight | Qt::AlignVCenter ); 00407 lUnicode->setMaximumWidth( lUnicode->sizeHint().width() ); 00408 00409 const TQRegExp rx( "[a-fA-F0-9]{1,4}" ); 00410 TQValidator* const validator = new TQRegExpValidator( rx, TQT_TQOBJECT(this) ); 00411 00412 d->unicodeLine = new KLineEdit( bar ); 00413 d->unicodeLine->setValidator(validator); 00414 lUnicode->setBuddy(d->unicodeLine); 00415 d->unicodeLine->resize( d->unicodeLine->sizeHint() ); 00416 slotUpdateUnicode(_chr); 00417 00418 connect( d->unicodeLine, TQT_SIGNAL( returnPressed() ), this, TQT_SLOT( slotUnicodeEntered() ) ); 00419 00420 charTable = new KCharSelectTable( this, name, _font.isEmpty() ? TQString(TQVBox::font().family()) : _font, _chr, _tableNum ); 00421 const TQSize sz( charTable->contentsWidth() + 4 , 00422 charTable->contentsHeight() + 4 ); 00423 charTable->resize( sz ); 00424 //charTable->setMaximumSize( sz ); 00425 charTable->setMinimumSize( sz ); 00426 charTable->setHScrollBarMode( TQScrollView::AlwaysOff ); 00427 charTable->setVScrollBarMode( TQScrollView::AlwaysOff ); 00428 00429 setFont( _font.isEmpty() ? TQString(TQVBox::font().family()) : _font ); 00430 setTableNum( _tableNum ); 00431 00432 connect( charTable, TQT_SIGNAL( highlighted( const TQChar & ) ), this, TQT_SLOT( slotUpdateUnicode( const TQChar & ) ) ); 00433 connect( charTable, TQT_SIGNAL( highlighted( const TQChar & ) ), this, TQT_SLOT( charHighlighted( const TQChar & ) ) ); 00434 connect( charTable, TQT_SIGNAL( highlighted() ), this, TQT_SLOT( charHighlighted() ) ); 00435 connect( charTable, TQT_SIGNAL( activated( const TQChar & ) ), this, TQT_SLOT( charActivated( const TQChar & ) ) ); 00436 connect( charTable, TQT_SIGNAL( activated() ), this, TQT_SLOT( charActivated() ) ); 00437 connect( charTable, TQT_SIGNAL( focusItemChanged( const TQChar & ) ), 00438 this, TQT_SLOT( charFocusItemChanged( const TQChar & ) ) ); 00439 connect( charTable, TQT_SIGNAL( focusItemChanged() ), this, TQT_SLOT( charFocusItemChanged() ) ); 00440 connect( charTable, TQT_SIGNAL( tableUp() ), this, TQT_SLOT( charTableUp() ) ); 00441 connect( charTable, TQT_SIGNAL( tableDown() ), this, TQT_SLOT( charTableDown() ) ); 00442 00443 connect( charTable, TQT_SIGNAL(doubleClicked()),this,TQT_SLOT(slotDoubleClicked())); 00444 00445 setFocusPolicy( TQ_StrongFocus ); 00446 setFocusProxy( charTable ); 00447 } 00448 00449 KCharSelect::~KCharSelect() 00450 { 00451 delete d; 00452 } 00453 00454 //================================================================== 00455 TQSize KCharSelect::sizeHint() const 00456 { 00457 return TQVBox::sizeHint(); 00458 } 00459 00460 //================================================================== 00461 void KCharSelect::setFont( const TQString &_font ) 00462 { 00463 const TQValueList<TQString>::Iterator it = fontList.find( _font ); 00464 if ( it != fontList.end() ) { 00465 TQValueList<TQString>::Iterator it2 = fontList.begin(); 00466 int pos = 0; 00467 for ( ; it != it2; ++it2, ++pos); 00468 fontCombo->setCurrentItem( pos ); 00469 charTable->setFont( _font ); 00470 } 00471 else 00472 kdWarning() << "Can't find Font: " << _font << endl; 00473 } 00474 00475 //================================================================== 00476 void KCharSelect::setChar( const TQChar &_chr ) 00477 { 00478 charTable->setChar( _chr ); 00479 slotUpdateUnicode( _chr ); 00480 } 00481 00482 //================================================================== 00483 void KCharSelect::setTableNum( int _tableNum ) 00484 { 00485 tableSpinBox->setValue( _tableNum ); 00486 charTable->setTableNum( _tableNum ); 00487 } 00488 00489 //================================================================== 00490 void KCharSelect::fillFontCombo() 00491 { 00492 if ( !fontDataBase ) { 00493 fontDataBase = new TQFontDatabase(); 00494 tqAddPostRoutine( cleanupFontDatabase ); 00495 } 00496 fontList=fontDataBase->families(); 00497 fontCombo->insertStringList( fontList ); 00498 } 00499 00500 //================================================================== 00501 void KCharSelect::fontSelected( const TQString &_font ) 00502 { 00503 charTable->setFont( _font ); 00504 emit fontChanged( _font ); 00505 } 00506 00507 //================================================================== 00508 void KCharSelect::tableChanged( int _value ) 00509 { 00510 charTable->setTableNum( _value ); 00511 } 00512 00513 //================================================================== 00514 void KCharSelect::slotUnicodeEntered( ) 00515 { 00516 const TQString s = d->unicodeLine->text(); 00517 if (s.isEmpty()) 00518 return; 00519 00520 bool ok; 00521 const int uc = s.toInt(&ok, 16); 00522 if (!ok) 00523 return; 00524 00525 const int table = uc / 256; 00526 charTable->setTableNum( table ); 00527 tableSpinBox->setValue(table); 00528 const TQChar ch(uc); 00529 charTable->setChar( ch ); 00530 charActivated( ch ); 00531 } 00532 00533 void KCharSelect::slotUpdateUnicode( const TQChar &c ) 00534 { 00535 const int uc = c.unicode(); 00536 TQString s; 00537 s.sprintf("%04X", uc); 00538 d->unicodeLine->setText(s); 00539 } 00540 00541 void KCharSelectTable::virtual_hook( int, void*) 00542 { /*BASE::virtual_hook( id, data );*/ } 00543 00544 void KCharSelect::virtual_hook( int, void* ) 00545 { /*BASE::virtual_hook( id, data );*/ } 00546