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