00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "ktextedit.h"
00021
00022 #include <qapplication.h>
00023 #include <qclipboard.h>
00024 #include <qpopupmenu.h>
00025
00026 #include <ksyntaxhighlighter.h>
00027 #include <kspell.h>
00028 #include <kcursor.h>
00029 #include <kglobalsettings.h>
00030 #include <kstdaccel.h>
00031 #include <kiconloader.h>
00032 #include <klocale.h>
00033
00034 class KTextEdit::KTextEditPrivate
00035 {
00036 public:
00037 KTextEditPrivate()
00038 : customPalette( false ),
00039 checkSpellingEnabled( false ),
00040 highlighter( 0 ),
00041 spell( 0 )
00042 {}
00043 ~KTextEditPrivate() {
00044 delete highlighter;
00045 delete spell;
00046 }
00047
00048 bool customPalette;
00049 bool checkSpellingEnabled;
00050 KDictSpellingHighlighter *highlighter;
00051 KSpell *spell;
00052 };
00053
00054 KTextEdit::KTextEdit( const QString& text, const QString& context,
00055 QWidget *parent, const char *name )
00056 : QTextEdit ( text, context, parent, name )
00057 {
00058 d = new KTextEditPrivate();
00059 KCursor::setAutoHideCursor( this, true, false );
00060 }
00061
00062 KTextEdit::KTextEdit( QWidget *parent, const char *name )
00063 : QTextEdit ( parent, name )
00064 {
00065 d = new KTextEditPrivate();
00066 KCursor::setAutoHideCursor( this, true, false );
00067 }
00068
00069 KTextEdit::~KTextEdit()
00070 {
00071 delete d;
00072 }
00073
00074 void KTextEdit::keyPressEvent( QKeyEvent *e )
00075 {
00076 KKey key( e );
00077
00078 if ( KStdAccel::copy().contains( key ) ) {
00079 copy();
00080 e->accept();
00081 return;
00082 }
00083 else if ( KStdAccel::paste().contains( key ) ) {
00084 paste();
00085 e->accept();
00086 return;
00087 }
00088 else if ( KStdAccel::cut().contains( key ) ) {
00089 cut();
00090 e->accept();
00091 return;
00092 }
00093 else if ( KStdAccel::undo().contains( key ) ) {
00094 undo();
00095 e->accept();
00096 return;
00097 }
00098 else if ( KStdAccel::redo().contains( key ) ) {
00099 redo();
00100 e->accept();
00101 return;
00102 }
00103 else if ( KStdAccel::deleteWordBack().contains( key ) )
00104 {
00105 deleteWordBack();
00106 e->accept();
00107 return;
00108 }
00109 else if ( KStdAccel::deleteWordForward().contains( key ) )
00110 {
00111 deleteWordForward();
00112 e->accept();
00113 return;
00114 }
00115 else if ( KStdAccel::backwardWord().contains( key ) )
00116 {
00117 CursorAction action = MoveWordBackward;
00118 int para, index;
00119 getCursorPosition( ¶, & index );
00120 if (text(para).isRightToLeft())
00121 action = MoveWordForward;
00122 moveCursor(action, false );
00123 e->accept();
00124 return;
00125 }
00126 else if ( KStdAccel::forwardWord().contains( key ) )
00127 {
00128 CursorAction action = MoveWordForward;
00129 int para, index;
00130 getCursorPosition( ¶, & index );
00131 if (text(para).isRightToLeft())
00132 action = MoveWordBackward;
00133 moveCursor( action, false );
00134 e->accept();
00135 return;
00136 }
00137 else if ( KStdAccel::next().contains( key ) )
00138 {
00139 moveCursor( MovePgDown, false );
00140 e->accept();
00141 return;
00142 }
00143 else if ( KStdAccel::prior().contains( key ) )
00144 {
00145 moveCursor( MovePgUp, false );
00146 e->accept();
00147 return;
00148 }
00149 else if ( KStdAccel::home().contains( key ) )
00150 {
00151 moveCursor( MoveHome, false );
00152 e->accept();
00153 return;
00154 }
00155 else if ( KStdAccel::end().contains( key ) )
00156 {
00157 moveCursor( MoveEnd, false );
00158 e->accept();
00159 return;
00160 }
00161 else if ( KStdAccel::beginningOfLine().contains( key ) )
00162 {
00163 moveCursor( MoveLineStart, false );
00164 e->accept();
00165 return;
00166 }
00167 else if ( KStdAccel::endOfLine().contains( key ) )
00168 {
00169 moveCursor(MoveLineEnd, false);
00170 e->accept();
00171 return;
00172 }
00173 else if ( KStdAccel::pasteSelection().contains( key ) )
00174 {
00175 QString text = QApplication::clipboard()->text( QClipboard::Selection);
00176 if ( !text.isEmpty() )
00177 insert( text );
00178 e->accept();
00179 return;
00180 }
00181
00182
00183 else if ( e->state() == ControlButton &&
00184 (e->key() == Key_Return || e->key() == Key_Enter) &&
00185 topLevelWidget()->inherits( "KDialog" ) )
00186 {
00187 e->ignore();
00188 return;
00189 }
00190
00191 QTextEdit::keyPressEvent( e );
00192 }
00193
00194 void KTextEdit::deleteWordBack()
00195 {
00196 removeSelection();
00197 moveCursor( MoveWordBackward, true );
00198 removeSelectedText();
00199 }
00200
00201 void KTextEdit::deleteWordForward()
00202 {
00203 removeSelection();
00204 moveCursor( MoveWordForward, true );
00205 removeSelectedText();
00206 }
00207
00208 void KTextEdit::slotAllowTab()
00209 {
00210 setTabChangesFocus(!tabChangesFocus());
00211 }
00212
00213 QPopupMenu *KTextEdit::createPopupMenu( const QPoint &pos )
00214 {
00215 enum { IdUndo, IdRedo, IdSep1, IdCut, IdCopy, IdPaste, IdClear, IdSep2, IdSelectAll };
00216
00217 QPopupMenu *menu = QTextEdit::createPopupMenu( pos );
00218
00219 if ( isReadOnly() )
00220 menu->changeItem( menu->idAt(0), SmallIconSet("editcopy"), menu->text( menu->idAt(0) ) );
00221 else {
00222 int id = menu->idAt(0);
00223 menu->changeItem( id - IdUndo, SmallIconSet("undo"), menu->text( id - IdUndo) );
00224 menu->changeItem( id - IdRedo, SmallIconSet("redo"), menu->text( id - IdRedo) );
00225 menu->changeItem( id - IdCut, SmallIconSet("editcut"), menu->text( id - IdCut) );
00226 menu->changeItem( id - IdCopy, SmallIconSet("editcopy"), menu->text( id - IdCopy) );
00227 menu->changeItem( id - IdPaste, SmallIconSet("editpaste"), menu->text( id - IdPaste) );
00228 menu->changeItem( id - IdClear, SmallIconSet("editclear"), menu->text( id - IdClear) );
00229
00230 menu->insertSeparator();
00231 id = menu->insertItem( SmallIconSet( "spellcheck" ), i18n( "Check Spelling..." ),
00232 this, SLOT( checkSpelling() ) );
00233
00234 if( text().isEmpty() )
00235 menu->setItemEnabled( id, false );
00236
00237 id = menu->insertItem( i18n( "Auto Spell Check" ),
00238 this, SLOT( toggleAutoSpellCheck() ) );
00239 menu->setItemChecked(id, d->checkSpellingEnabled);
00240 menu->insertSeparator();
00241 id=menu->insertItem(i18n("Allow Tabulations"),this,SLOT(slotAllowTab()));
00242 menu->setItemChecked(id, !tabChangesFocus());
00243 }
00244
00245 return menu;
00246 }
00247
00248 QPopupMenu *KTextEdit::createPopupMenu()
00249 {
00250 return QTextEdit::createPopupMenu();
00251 }
00252
00253 void KTextEdit::contentsWheelEvent( QWheelEvent *e )
00254 {
00255 if ( KGlobalSettings::wheelMouseZooms() )
00256 QTextEdit::contentsWheelEvent( e );
00257 else
00258 QScrollView::contentsWheelEvent( e );
00259 }
00260
00261 void KTextEdit::setPalette( const QPalette& palette )
00262 {
00263 QTextEdit::setPalette( palette );
00264
00265
00266 d->customPalette = ownPalette();
00267 }
00268
00269 void KTextEdit::toggleAutoSpellCheck()
00270 {
00271 setCheckSpellingEnabled( !d->checkSpellingEnabled );
00272 }
00273
00274 void KTextEdit::setCheckSpellingEnabled( bool check )
00275 {
00276 if ( check == d->checkSpellingEnabled )
00277 return;
00278
00279
00280
00281
00282
00283 d->checkSpellingEnabled = check;
00284 if ( check )
00285 {
00286 if (hasFocus())
00287 d->highlighter = new KDictSpellingHighlighter( this );
00288 }
00289 else
00290 {
00291 delete d->highlighter;
00292 d->highlighter = 0;
00293 }
00294 }
00295
00296 void KTextEdit::focusInEvent( QFocusEvent *e )
00297 {
00298 if ( d->checkSpellingEnabled && !isReadOnly() && !d->highlighter )
00299 d->highlighter = new KDictSpellingHighlighter( this );
00300
00301 QTextEdit::focusInEvent( e );
00302 }
00303
00304 bool KTextEdit::checkSpellingEnabled() const
00305 {
00306 return d->checkSpellingEnabled;
00307 }
00308
00309 void KTextEdit::setReadOnly(bool readOnly)
00310 {
00311 if ( !readOnly && hasFocus() && d->checkSpellingEnabled && !d->highlighter )
00312 d->highlighter = new KDictSpellingHighlighter( this );
00313
00314 if ( readOnly == isReadOnly() )
00315 return;
00316
00317 if (readOnly)
00318 {
00319 delete d->highlighter;
00320 d->highlighter = 0;
00321
00322 bool custom = ownPalette();
00323 QPalette p = palette();
00324 QColor color = p.color(QPalette::Disabled, QColorGroup::Background);
00325 p.setColor(QColorGroup::Base, color);
00326 p.setColor(QColorGroup::Background, color);
00327 setPalette(p);
00328 d->customPalette = custom;
00329 }
00330 else
00331 {
00332 if ( d->customPalette )
00333 {
00334 QPalette p = palette();
00335 QColor color = p.color(QPalette::Normal, QColorGroup::Base);
00336 p.setColor(QColorGroup::Base, color);
00337 p.setColor(QColorGroup::Background, color);
00338 setPalette( p );
00339 }
00340 else
00341 unsetPalette();
00342 }
00343
00344 QTextEdit::setReadOnly (readOnly);
00345 }
00346
00347 void KTextEdit::virtual_hook( int, void* )
00348 { }
00349
00350 void KTextEdit::checkSpelling()
00351 {
00352 delete d->spell;
00353 d->spell = new KSpell( this, i18n( "Spell Checking" ),
00354 this, SLOT( slotSpellCheckReady( KSpell *) ), 0, true, true);
00355
00356 connect( d->spell, SIGNAL( death() ),
00357 this, SLOT( spellCheckerFinished() ) );
00358
00359 connect( d->spell, SIGNAL( misspelling( const QString &, const QStringList &, unsigned int ) ),
00360 this, SLOT( spellCheckerMisspelling( const QString &, const QStringList &, unsigned int ) ) );
00361
00362 connect( d->spell, SIGNAL( corrected( const QString &, const QString &, unsigned int ) ),
00363 this, SLOT( spellCheckerCorrected( const QString &, const QString &, unsigned int ) ) );
00364 }
00365
00366 void KTextEdit::spellCheckerMisspelling( const QString &text, const QStringList &, unsigned int pos )
00367 {
00368 highLightWord( text.length(), pos );
00369 }
00370
00371 void KTextEdit::spellCheckerCorrected( const QString &oldWord, const QString &newWord, unsigned int pos )
00372 {
00373 unsigned int l = 0;
00374 unsigned int cnt = 0;
00375 if ( oldWord != newWord ) {
00376 posToRowCol( pos, l, cnt );
00377 setSelection( l, cnt, l, cnt + oldWord.length() );
00378 removeSelectedText();
00379 insert( newWord );
00380 }
00381 }
00382
00383 void KTextEdit::posToRowCol(unsigned int pos, unsigned int &line, unsigned int &col)
00384 {
00385 for ( line = 0; line < static_cast<uint>( lines() ) && col <= pos; line++ )
00386 col += paragraphLength( line ) + 1;
00387
00388 line--;
00389 col = pos - col + paragraphLength( line ) + 1;
00390 }
00391
00392 void KTextEdit::spellCheckerFinished()
00393 {
00394 delete d->spell;
00395 d->spell = 0L;
00396 }
00397
00398 void KTextEdit::slotSpellCheckReady( KSpell *s )
00399 {
00400 s->check( text() );
00401 connect( s, SIGNAL( done( const QString & ) ), this, SLOT( slotSpellCheckDone( const QString & ) ) );
00402 }
00403
00404 void KTextEdit::slotSpellCheckDone( const QString &s )
00405 {
00406 if ( s != text() )
00407 setText( s );
00408 }
00409
00410
00411 void KTextEdit::highLightWord( unsigned int length, unsigned int pos )
00412 {
00413 unsigned int l = 0;
00414 unsigned int cnt = 0;
00415 posToRowCol( pos, l, cnt );
00416 setSelection( l, cnt, l, cnt + length );
00417 }
00418
00419 #include "ktextedit.moc"