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