00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "kcharselect.h"
00022 #include "kcharselect.moc"
00023
00024 #include <qbrush.h>
00025 #include <qcolor.h>
00026 #include <qevent.h>
00027 #include <qfont.h>
00028 #include <qfontdatabase.h>
00029 #include <qhbox.h>
00030 #include <qkeycode.h>
00031 #include <qlabel.h>
00032 #include <qpainter.h>
00033 #include <qpen.h>
00034 #include <qregexp.h>
00035 #include <qstyle.h>
00036 #include <qtooltip.h>
00037 #include <qvalidator.h>
00038
00039 #include <kapplication.h>
00040 #include <kdebug.h>
00041 #include <kdialog.h>
00042 #include <klineedit.h>
00043 #include <klocale.h>
00044
00045 class KCharSelect::KCharSelectPrivate
00046 {
00047 public:
00048 QLineEdit *unicodeLine;
00049 };
00050
00051 QFontDatabase * KCharSelect::fontDataBase = 0;
00052
00053 void KCharSelect::cleanupFontDatabase()
00054 {
00055 delete fontDataBase;
00056 fontDataBase = 0;
00057 }
00058
00059
00060
00061
00062
00063
00064 KCharSelectTable::KCharSelectTable( QWidget *parent, const char *name, const QString &_font,
00065 const QChar &_chr, int _tableNum )
00066 : QGridView( 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( QWidget::StrongFocus );
00082 setBackgroundMode( QWidget::NoBackground );
00083 }
00084
00085
00086 void KCharSelectTable::setFont( const QString &_font )
00087 {
00088 vFont = _font;
00089 repaintContents( false );
00090
00091 setToolTips();
00092 }
00093
00094
00095 void KCharSelectTable::setChar( const QChar &_chr )
00096 {
00097 vChr = _chr;
00098 repaintContents( false );
00099 }
00100
00101
00102 void KCharSelectTable::setTableNum( int _tableNum )
00103 {
00104 focusItem = QChar( _tableNum * 256 );
00105
00106 vTableNum = _tableNum;
00107 repaintContents( false );
00108
00109 setToolTips();
00110 }
00111
00112
00113 QSize KCharSelectTable::sizeHint() const
00114 {
00115 int w = cellWidth();
00116 int h = cellHeight();
00117
00118 w *= numCols();
00119 h *= numRows();
00120
00121 return QSize( w, h );
00122 }
00123
00124
00125 void KCharSelectTable::resizeEvent( QResizeEvent * 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 QPainter* 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
00147
00148
00149
00150
00151 QFont font = QFont( 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( QBrush( colorGroup().highlight() ) );
00160 p->setPen( NoPen );
00161 p->drawRect( 0, 0, w, h );
00162 p->setPen( colorGroup().highlightedText() );
00163 vPos = QPoint( col, row );
00164 } else {
00165 QFontMetrics fm = QFontMetrics( font );
00166 if( fm.inFont( c ) )
00167 p->setBrush( QBrush( colorGroup().base() ) );
00168 else
00169 p->setBrush( QBrush( 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().drawPrimitive( QStyle::PE_FocusRect, p, QRect( 2, 2, w - 4, h - 4 ),
00177 colorGroup() );
00178 focusPos = QPoint( col, row );
00179 }
00180
00181 p->setFont( font );
00182
00183 p->drawText( 0, 0, x2, y2, AlignHCenter | AlignVCenter, QString( QChar( 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( QMouseEvent *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 QPoint oldPos = vPos;
00202
00203 vPos.setX( col );
00204 vPos.setY( row );
00205
00206 vChr = QChar( vTableNum * 256 + numCols() * vPos.y() + vPos.x() );
00207
00208 const QPoint 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( QKeyEvent *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 QPoint 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 QPoint oldPos = focusPos;
00275
00276 focusPos.setX( focusPos.x() - 1 );
00277
00278 focusItem = QChar( 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 QPoint oldPos = focusPos;
00293
00294 focusPos.setX( focusPos.x() + 1 );
00295
00296 focusItem = QChar( 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 QPoint oldPos = focusPos;
00311
00312 focusPos.setY( focusPos.y() - 1 );
00313
00314 focusItem = QChar( 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 QPoint oldPos = focusPos;
00329
00330 focusPos.setY( focusPos.y() + 1 );
00331
00332 focusItem = QChar( 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 QRect r( cellWidth()*j, cellHeight()*i, cellWidth(), cellHeight() );
00352 QToolTip::remove(this,r);
00353 const ushort uni = vTableNum * 256 + numCols()*i + j;
00354 QString s;
00355 s.sprintf( "%04X", uint( uni ) );
00356 QString character;
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 = QChar( uni ); break;
00365 }
00366 QToolTip::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
00373
00374
00375
00376 KCharSelect::KCharSelect( QWidget *parent, const char *name, const QString &_font, const QChar &_chr, int _tableNum )
00377 : QVBox( parent, name ), d(new KCharSelectPrivate)
00378 {
00379 setSpacing( KDialog::spacingHint() );
00380 QHBox* const bar = new QHBox( this );
00381 bar->setSpacing( KDialog::spacingHint() );
00382
00383 QLabel* const lFont = new QLabel( 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 QComboBox( true, bar );
00389 fillFontCombo();
00390 fontCombo->resize( fontCombo->sizeHint() );
00391
00392 connect( fontCombo, SIGNAL( activated( const QString & ) ), this, SLOT( fontSelected( const QString & ) ) );
00393
00394 QLabel* const lTable = new QLabel( 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 QSpinBox( 0, 255, 1, bar );
00400 tableSpinBox->resize( tableSpinBox->sizeHint() );
00401
00402 connect( tableSpinBox, SIGNAL( valueChanged( int ) ), this, SLOT( tableChanged( int ) ) );
00403
00404 QLabel* const lUnicode = new QLabel( 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 QRegExp rx( "[a-fA-F0-9]{1,4}" );
00410 QValidator* const validator = new QRegExpValidator( rx, 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, SIGNAL( returnPressed() ), this, SLOT( slotUnicodeEntered() ) );
00419
00420 charTable = new KCharSelectTable( this, name, _font.isEmpty() ? QVBox::font().family() : _font, _chr, _tableNum );
00421 const QSize sz( charTable->contentsWidth() + 4 ,
00422 charTable->contentsHeight() + 4 );
00423 charTable->resize( sz );
00424
00425 charTable->setMinimumSize( sz );
00426 charTable->setHScrollBarMode( QScrollView::AlwaysOff );
00427 charTable->setVScrollBarMode( QScrollView::AlwaysOff );
00428
00429 setFont( _font.isEmpty() ? QVBox::font().family() : _font );
00430 setTableNum( _tableNum );
00431
00432 connect( charTable, SIGNAL( highlighted( const QChar & ) ), this, SLOT( slotUpdateUnicode( const QChar & ) ) );
00433 connect( charTable, SIGNAL( highlighted( const QChar & ) ), this, SLOT( charHighlighted( const QChar & ) ) );
00434 connect( charTable, SIGNAL( highlighted() ), this, SLOT( charHighlighted() ) );
00435 connect( charTable, SIGNAL( activated( const QChar & ) ), this, SLOT( charActivated( const QChar & ) ) );
00436 connect( charTable, SIGNAL( activated() ), this, SLOT( charActivated() ) );
00437 connect( charTable, SIGNAL( focusItemChanged( const QChar & ) ),
00438 this, SLOT( charFocusItemChanged( const QChar & ) ) );
00439 connect( charTable, SIGNAL( focusItemChanged() ), this, SLOT( charFocusItemChanged() ) );
00440 connect( charTable, SIGNAL( tableUp() ), this, SLOT( charTableUp() ) );
00441 connect( charTable, SIGNAL( tableDown() ), this, SLOT( charTableDown() ) );
00442
00443 connect( charTable, SIGNAL(doubleClicked()),this,SLOT(slotDoubleClicked()));
00444
00445 setFocusPolicy( QWidget::StrongFocus );
00446 setFocusProxy( charTable );
00447 }
00448
00449 KCharSelect::~KCharSelect()
00450 {
00451 delete d;
00452 }
00453
00454
00455 QSize KCharSelect::sizeHint() const
00456 {
00457 return QVBox::sizeHint();
00458 }
00459
00460
00461 void KCharSelect::setFont( const QString &_font )
00462 {
00463 const QValueList<QString>::Iterator it = fontList.find( _font );
00464 if ( it != fontList.end() ) {
00465 QValueList<QString>::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 QChar &_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 QFontDatabase();
00494 qAddPostRoutine( cleanupFontDatabase );
00495 }
00496 fontList=fontDataBase->families();
00497 fontCombo->insertStringList( fontList );
00498 }
00499
00500
00501 void KCharSelect::fontSelected( const QString &_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 QString 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 QChar ch(uc);
00529 charTable->setChar( ch );
00530 charActivated( ch );
00531 }
00532
00533 void KCharSelect::slotUpdateUnicode( const QChar &c )
00534 {
00535 const int uc = c.unicode();
00536 QString s;
00537 s.sprintf("%04X", uc);
00538 d->unicodeLine->setText(s);
00539 }
00540
00541 void KCharSelectTable::virtual_hook( int, void*)
00542 { }
00543
00544 void KCharSelect::virtual_hook( int, void* )
00545 { }
00546