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 moveCursor(MoveWordBackward, false );
00118 e->accept();
00119 return;
00120 }
00121 else if ( KStdAccel::forwardWord().contains( key ) )
00122 {
00123 moveCursor( MoveWordForward, false );
00124 e->accept();
00125 return;
00126 }
00127 else if ( KStdAccel::next().contains( key ) )
00128 {
00129 moveCursor( MovePgDown, false );
00130 e->accept();
00131 return;
00132 }
00133 else if ( KStdAccel::prior().contains( key ) )
00134 {
00135 moveCursor( MovePgUp, false );
00136 e->accept();
00137 return;
00138 }
00139 else if ( KStdAccel::home().contains( key ) )
00140 {
00141 moveCursor( MoveHome, false );
00142 e->accept();
00143 return;
00144 }
00145 else if ( KStdAccel::end().contains( key ) )
00146 {
00147 moveCursor( MoveEnd, false );
00148 e->accept();
00149 return;
00150 }
00151 else if ( KStdAccel::beginningOfLine().contains( key ) )
00152 {
00153 moveCursor( MoveLineStart, false );
00154 e->accept();
00155 return;
00156 }
00157 else if ( KStdAccel::endOfLine().contains( key ) )
00158 {
00159 moveCursor(MoveLineEnd, false);
00160 e->accept();
00161 return;
00162 }
00163
00164 else if ( e->key() == Key_Insert &&
00165 (e->state() == (ShiftButton | ControlButton)) )
00166 {
00167 QString text = QApplication::clipboard()->text( QClipboard::Selection);
00168 if ( !text.isEmpty() )
00169 insert( text );
00170 e->accept();
00171 return;
00172 }
00173
00174
00175 else if ( e->state() == ControlButton &&
00176 (e->key() == Key_Return || e->key() == Key_Enter) &&
00177 topLevelWidget()->inherits( "KDialog" ) )
00178 {
00179 e->ignore();
00180 return;
00181 }
00182
00183 QTextEdit::keyPressEvent( e );
00184 }
00185
00186 void KTextEdit::deleteWordBack()
00187 {
00188 removeSelection();
00189 moveCursor( MoveWordBackward, true );
00190 removeSelectedText();
00191 }
00192
00193 void KTextEdit::deleteWordForward()
00194 {
00195 removeSelection();
00196 moveCursor( MoveWordForward, true );
00197 removeSelectedText();
00198 }
00199
00200 void KTextEdit::slotAllowTab()
00201 {
00202 setTabChangesFocus(!tabChangesFocus());
00203 }
00204
00205 QPopupMenu *KTextEdit::createPopupMenu( const QPoint &pos )
00206 {
00207 enum { IdUndo, IdRedo, IdSep1, IdCut, IdCopy, IdPaste, IdClear, IdSep2, IdSelectAll };
00208
00209 QPopupMenu *menu = QTextEdit::createPopupMenu( pos );
00210
00211 if ( isReadOnly() )
00212 menu->changeItem( menu->idAt(0), SmallIconSet("editcopy"), menu->text( menu->idAt(0) ) );
00213 else {
00214 int id = menu->idAt(0);
00215 menu->changeItem( id - IdUndo, SmallIconSet("undo"), menu->text( id - IdUndo) );
00216 menu->changeItem( id - IdRedo, SmallIconSet("redo"), menu->text( id - IdRedo) );
00217 menu->changeItem( id - IdCut, SmallIconSet("editcut"), menu->text( id - IdCut) );
00218 menu->changeItem( id - IdCopy, SmallIconSet("editcopy"), menu->text( id - IdCopy) );
00219 menu->changeItem( id - IdPaste, SmallIconSet("editpaste"), menu->text( id - IdPaste) );
00220 menu->changeItem( id - IdClear, SmallIconSet("editclear"), menu->text( id - IdClear) );
00221
00222 menu->insertSeparator();
00223 id = menu->insertItem( SmallIconSet( "spellcheck" ), i18n( "Check Spelling..." ),
00224 this, SLOT( checkSpelling() ) );
00225
00226 if( text().isEmpty() )
00227 menu->setItemEnabled( id, false );
00228
00229 id = menu->insertItem( i18n( "Auto Spell Check" ),
00230 this, SLOT( toggleAutoSpellCheck() ) );
00231 menu->setItemChecked(id, d->checkSpellingEnabled);
00232 menu->insertSeparator();
00233 id=menu->insertItem(i18n("Allow Tabulations"),this,SLOT(slotAllowTab()));
00234 menu->setItemChecked(id, !tabChangesFocus());
00235 }
00236
00237 return menu;
00238 }
00239
00240 QPopupMenu *KTextEdit::createPopupMenu()
00241 {
00242 return QTextEdit::createPopupMenu();
00243 }
00244
00245 void KTextEdit::contentsWheelEvent( QWheelEvent *e )
00246 {
00247 if ( KGlobalSettings::wheelMouseZooms() )
00248 QTextEdit::contentsWheelEvent( e );
00249 else
00250 QScrollView::contentsWheelEvent( e );
00251 }
00252
00253 void KTextEdit::setPalette( const QPalette& palette )
00254 {
00255 QTextEdit::setPalette( palette );
00256
00257
00258 d->customPalette = ownPalette();
00259 }
00260
00261 void KTextEdit::toggleAutoSpellCheck()
00262 {
00263 setCheckSpellingEnabled( !d->checkSpellingEnabled );
00264 }
00265
00266 void KTextEdit::setCheckSpellingEnabled( bool check )
00267 {
00268 if ( check == d->checkSpellingEnabled )
00269 return;
00270
00271
00272
00273
00274
00275 d->checkSpellingEnabled = check;
00276 if ( check )
00277 {
00278 if (hasFocus())
00279 d->highlighter = new KDictSpellingHighlighter( this );
00280 }
00281 else
00282 {
00283 delete d->highlighter;
00284 d->highlighter = 0;
00285 }
00286 }
00287
00288 void KTextEdit::focusInEvent( QFocusEvent *e )
00289 {
00290 if ( d->checkSpellingEnabled && !d->highlighter )
00291 d->highlighter = new KDictSpellingHighlighter( this );
00292
00293 QTextEdit::focusInEvent( e );
00294 }
00295
00296 bool KTextEdit::checkSpellingEnabled() const
00297 {
00298 return d->checkSpellingEnabled;
00299 }
00300
00301 void KTextEdit::setReadOnly(bool readOnly)
00302 {
00303 if ( readOnly == isReadOnly() )
00304 return;
00305
00306 if (readOnly)
00307 {
00308 bool custom = ownPalette();
00309 QPalette p = palette();
00310 QColor color = p.color(QPalette::Disabled, QColorGroup::Background);
00311 p.setColor(QColorGroup::Base, color);
00312 p.setColor(QColorGroup::Background, color);
00313 setPalette(p);
00314 d->customPalette = custom;
00315 }
00316 else
00317 {
00318 if ( d->customPalette )
00319 {
00320 QPalette p = palette();
00321 QColor color = p.color(QPalette::Normal, QColorGroup::Base);
00322 p.setColor(QColorGroup::Base, color);
00323 p.setColor(QColorGroup::Background, color);
00324 setPalette( p );
00325 }
00326 else
00327 unsetPalette();
00328 }
00329
00330 QTextEdit::setReadOnly (readOnly);
00331 }
00332
00333 void KTextEdit::virtual_hook( int, void* )
00334 { }
00335
00336 void KTextEdit::checkSpelling()
00337 {
00338 delete d->spell;
00339 d->spell = new KSpell( this, i18n( "Spell Checking" ),
00340 this, SLOT( slotSpellCheckReady( KSpell *) ), 0, true, true);
00341
00342 connect( d->spell, SIGNAL( death() ),
00343 this, SLOT( spellCheckerFinished() ) );
00344
00345 connect( d->spell, SIGNAL( misspelling( const QString &, const QStringList &, unsigned int ) ),
00346 this, SLOT( spellCheckerMisspelling( const QString &, const QStringList &, unsigned int ) ) );
00347
00348 connect( d->spell, SIGNAL( corrected( const QString &, const QString &, unsigned int ) ),
00349 this, SLOT( spellCheckerCorrected( const QString &, const QString &, unsigned int ) ) );
00350 }
00351
00352 void KTextEdit::spellCheckerMisspelling( const QString &text, const QStringList &, unsigned int pos )
00353 {
00354 highLightWord( text.length(), pos );
00355 }
00356
00357 void KTextEdit::spellCheckerCorrected( const QString &oldWord, const QString &newWord, unsigned int pos )
00358 {
00359 unsigned int l = 0;
00360 unsigned int cnt = 0;
00361 if ( oldWord != newWord ) {
00362 posToRowCol( pos, l, cnt );
00363 setSelection( l, cnt, l, cnt + oldWord.length() );
00364 removeSelectedText();
00365 insert( newWord );
00366 }
00367 }
00368
00369 void KTextEdit::posToRowCol(unsigned int pos, unsigned int &line, unsigned int &col)
00370 {
00371 for ( line = 0; line < static_cast<uint>( lines() ) && col <= pos; line++ )
00372 col += paragraphLength( line ) + 1;
00373
00374 line--;
00375 col = pos - col + paragraphLength( line ) + 1;
00376 }
00377
00378 void KTextEdit::spellCheckerFinished()
00379 {
00380 delete d->spell;
00381 d->spell = 0L;
00382 }
00383
00384 void KTextEdit::slotSpellCheckReady( KSpell *s )
00385 {
00386 s->check( text() );
00387 connect( s, SIGNAL( done( const QString & ) ), this, SLOT( slotSpellCheckDone( const QString & ) ) );
00388 }
00389
00390 void KTextEdit::slotSpellCheckDone( const QString &s )
00391 {
00392 if ( s != text() )
00393 setText( s );
00394 }
00395
00396
00397 void KTextEdit::highLightWord( unsigned int length, unsigned int pos )
00398 {
00399 unsigned int l = 0;
00400 unsigned int cnt = 0;
00401 posToRowCol( pos, l, cnt );
00402 setSelection( l, cnt, l, cnt + length );
00403 }
00404
00405 #include "ktextedit.moc"