00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "ktextedit.h"
00022
00023 #include <QApplication>
00024 #include <QClipboard>
00025 #include <QKeyEvent>
00026 #include <QMenu>
00027 #include <QScrollBar>
00028 #include <QTextCursor>
00029
00030 #include <configdialog.h>
00031 #include <dialog.h>
00032 #include "backgroundchecker.h"
00033 #include <kaction.h>
00034 #include <kcursor.h>
00035 #include <kglobalsettings.h>
00036 #include <kstandardaction.h>
00037 #include <kstandardshortcut.h>
00038 #include <kicon.h>
00039 #include <kiconloader.h>
00040 #include <klocale.h>
00041 #include <kdialog.h>
00042 #include <kreplacedialog.h>
00043 #include <kfinddialog.h>
00044 #include <kfind.h>
00045 #include <kreplace.h>
00046 #include <kmessagebox.h>
00047 #include <kmenu.h>
00048 #include <kwindowsystem.h>
00049
00050 class KTextEdit::Private
00051 {
00052 public:
00053 Private( KTextEdit *_parent )
00054 : parent( _parent ),
00055 customPalette( false ),
00056 checkSpellingEnabled( false ),
00057 findReplaceEnabled(true),
00058 highlighter( 0 ), findDlg(0),find(0),repDlg(0),replace(0), findIndex(0), repIndex(0)
00059 {
00060 }
00061
00062 ~Private()
00063 {
00064 delete highlighter;
00065 delete findDlg;
00066 delete find;
00067 delete replace;
00068 delete repDlg;
00069 }
00070
00076 bool overrideShortcut(const QKeyEvent* e);
00080 bool handleShortcut(const QKeyEvent* e);
00081
00082 void spellCheckerMisspelling( const QString &text, int pos );
00083 void spellCheckerCorrected( const QString &, int,const QString &);
00084 void spellCheckerAutoCorrect(const QString&,const QString&);
00085 void spellCheckerCanceled();
00086 void spellCheckerFinished();
00087 void toggleAutoSpellCheck();
00088
00089 void slotFindHighlight(const QString& text, int matchingIndex, int matchingLength);
00090 void slotReplaceText(const QString &text, int replacementIndex, int , int matchedLength);
00091
00096 void undoableClear();
00097
00098 void slotAllowTab();
00099 void menuActivated( QAction* action );
00100
00101 void init();
00102
00103 KTextEdit *parent;
00104 KTextEditSpellInterface *spellInterface;
00105 QAction *autoSpellCheckAction;
00106 QAction *allowTab;
00107 QAction *spellCheckAction;
00108 bool customPalette : 1;
00109
00110 bool checkSpellingEnabled : 1;
00111 bool findReplaceEnabled: 1;
00112 QString originalBuffer;
00113 QString spellChechingConfigFileName;
00114 QString spellCheckingLanguage;
00115 Sonnet::Highlighter *highlighter;
00116 KFindDialog *findDlg;
00117 KFind *find;
00118 KReplaceDialog *repDlg;
00119 KReplace *replace;
00120 int findIndex, repIndex;
00121 };
00122
00123 void KTextEdit::Private::spellCheckerCanceled()
00124 {
00125 parent->selectAll();
00126 parent->setPlainText(originalBuffer);
00127 spellCheckerFinished();
00128 }
00129
00130 void KTextEdit::Private::spellCheckerAutoCorrect(const QString&,const QString&)
00131 {
00132
00133 }
00134
00135 void KTextEdit::Private::spellCheckerMisspelling( const QString &text, int pos )
00136 {
00137
00138 parent->highlightWord( text.length(), pos );
00139 }
00140
00141 void KTextEdit::Private::spellCheckerCorrected( const QString& oldWord, int pos,const QString& newWord)
00142 {
00143
00144 if (oldWord != newWord ) {
00145 QTextCursor cursor(parent->document());
00146 cursor.setPosition(pos);
00147 cursor.setPosition(pos+oldWord.length(),QTextCursor::KeepAnchor);
00148 cursor.insertText(newWord);
00149 }
00150 }
00151
00152 void KTextEdit::Private::spellCheckerFinished()
00153 {
00154 QTextCursor cursor(parent->document());
00155 cursor.clearSelection();
00156 parent->setTextCursor(cursor);
00157 if (parent->highlighter())
00158 parent->highlighter()->rehighlight();
00159 }
00160
00161 void KTextEdit::Private::toggleAutoSpellCheck()
00162 {
00163 parent->setCheckSpellingEnabled( !parent->checkSpellingEnabled() );
00164 }
00165
00166 void KTextEdit::Private::undoableClear()
00167 {
00168 QTextCursor cursor = parent->textCursor();
00169 cursor.beginEditBlock();
00170 cursor.movePosition(QTextCursor::Start);
00171 cursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
00172 cursor.removeSelectedText();
00173 cursor.endEditBlock();
00174 }
00175
00176 void KTextEdit::Private::slotAllowTab()
00177 {
00178 parent->setTabChangesFocus( !parent->tabChangesFocus() );
00179 }
00180
00181 void KTextEdit::Private::menuActivated( QAction* action )
00182 {
00183 if ( action == spellCheckAction )
00184 parent->checkSpelling();
00185 else if ( action == autoSpellCheckAction )
00186 toggleAutoSpellCheck();
00187 else if ( action == allowTab )
00188 slotAllowTab();
00189 }
00190
00191
00192 void KTextEdit::Private::slotFindHighlight(const QString& text, int matchingIndex, int matchingLength)
00193 {
00194 Q_UNUSED(text)
00195
00196 QTextCursor tc = parent->textCursor();
00197 tc.setPosition(matchingIndex);
00198 tc.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, matchingLength);
00199 parent->setTextCursor(tc);
00200 parent->ensureCursorVisible();
00201 }
00202
00203
00204 void KTextEdit::Private::slotReplaceText(const QString &text, int replacementIndex, int , int matchedLength) {
00205 Q_UNUSED(text)
00206
00207 QTextCursor tc = parent->textCursor();
00208 tc.setPosition(replacementIndex);
00209 tc.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, matchedLength);
00210 tc.removeSelectedText();
00211 tc.insertText(repDlg->replacement());
00212 parent->setTextCursor(tc);
00213 if (replace->options() & KReplaceDialog::PromptOnReplace) {
00214 parent->ensureCursorVisible();
00215 }
00216 }
00217
00218 void KTextEdit::Private::init()
00219 {
00220 spellInterface = 0;
00221 KCursor::setAutoHideCursor(parent, true, false);
00222 parent->connect(parent, SIGNAL(languageChanged(const QString&)),
00223 parent, SLOT(setSpellCheckingLanguage(const QString&)));
00224 }
00225
00226 KTextEdit::KTextEdit( const QString& text, QWidget *parent )
00227 : QTextEdit( text, parent ), d( new Private( this ) )
00228 {
00229 d->init();
00230 }
00231
00232 KTextEdit::KTextEdit( QWidget *parent )
00233 : QTextEdit( parent ), d( new Private( this ) )
00234 {
00235 d->init();
00236 }
00237
00238 KTextEdit::~KTextEdit()
00239 {
00240 delete d;
00241 }
00242
00243 void KTextEdit::setSpellCheckingConfigFileName(const QString &_fileName)
00244 {
00245 d->spellChechingConfigFileName = _fileName;
00246 }
00247
00248 const QString& KTextEdit::spellCheckingLanguage() const
00249 {
00250 return d->spellCheckingLanguage;
00251 }
00252
00253 void KTextEdit::setSpellCheckingLanguage(const QString &_language)
00254 {
00255 if (highlighter()) {
00256 highlighter()->setCurrentLanguage(_language);
00257 highlighter()->rehighlight();
00258 }
00259
00260 if (_language != d->spellCheckingLanguage) {
00261 d->spellCheckingLanguage = _language;
00262 emit languageChanged(_language);
00263 }
00264 else
00265 d->spellCheckingLanguage = _language;
00266 }
00267
00268 void KTextEdit::showSpellConfigDialog(const QString &configFileName,
00269 const QString &windowIcon)
00270 {
00271 KConfig config(configFileName);
00272 Sonnet::ConfigDialog dialog(&config, this);
00273 if (!d->spellCheckingLanguage.isEmpty())
00274 dialog.setLanguage(d->spellCheckingLanguage);
00275 connect(&dialog, SIGNAL(languageChanged(const QString &)),
00276 this, SLOT(setSpellCheckingLanguage(const QString &)));
00277 if (!windowIcon.isEmpty())
00278 dialog.setWindowIcon(KIcon(windowIcon));
00279 dialog.exec();
00280 }
00281
00282 bool KTextEdit::event(QEvent* ev)
00283 {
00284 if (ev->type() == QEvent::ShortcutOverride) {
00285 QKeyEvent *e = static_cast<QKeyEvent *>( ev );
00286 if (d->overrideShortcut(e)) {
00287 e->accept();
00288 return true;
00289 }
00290 }
00291 return QTextEdit::event(ev);
00292 }
00293
00294 bool KTextEdit::Private::handleShortcut(const QKeyEvent* event)
00295 {
00296 const int key = event->key() | event->modifiers();
00297
00298 if ( KStandardShortcut::copy().contains( key ) ) {
00299 parent->copy();
00300 return true;
00301 } else if ( KStandardShortcut::paste().contains( key ) ) {
00302 parent->paste();
00303 return true;
00304 } else if ( KStandardShortcut::cut().contains( key ) ) {
00305 parent->cut();
00306 return true;
00307 } else if ( KStandardShortcut::undo().contains( key ) ) {
00308 parent->document()->undo();
00309 return true;
00310 } else if ( KStandardShortcut::redo().contains( key ) ) {
00311 parent->document()->redo();
00312 return true;
00313 } else if ( KStandardShortcut::deleteWordBack().contains( key ) ) {
00314 parent->deleteWordBack();
00315 return true;
00316 } else if ( KStandardShortcut::deleteWordForward().contains( key ) ) {
00317 parent->deleteWordForward();
00318 return true;
00319 } else if ( KStandardShortcut::backwardWord().contains( key ) ) {
00320 QTextCursor cursor = parent->textCursor();
00321 cursor.movePosition( QTextCursor::PreviousWord );
00322 parent->setTextCursor( cursor );
00323 return true;
00324 } else if ( KStandardShortcut::forwardWord().contains( key ) ) {
00325 QTextCursor cursor = parent->textCursor();
00326 cursor.movePosition( QTextCursor::NextWord );
00327 parent->setTextCursor( cursor );
00328 return true;
00329 } else if ( KStandardShortcut::next().contains( key ) ) {
00330 QTextCursor cursor = parent->textCursor();
00331 int targetY = parent->verticalScrollBar()->value() + parent->viewport()->height();
00332 bool moved = false;
00333 do {
00334 moved = cursor.movePosition( QTextCursor::Down );
00335 parent->setTextCursor( cursor );
00336 } while ( moved && parent->verticalScrollBar()->value() < targetY );
00337 return true;
00338 } else if ( KStandardShortcut::prior().contains( key ) ) {
00339 QTextCursor cursor = parent->textCursor();
00340 int targetY = parent->verticalScrollBar()->value() - parent->viewport()->height();
00341 bool moved = false;
00342 do {
00343 moved = cursor.movePosition( QTextCursor::Up );
00344 parent->setTextCursor( cursor );
00345 } while ( moved && parent->verticalScrollBar()->value() > targetY );
00346 return true;
00347 } else if ( KStandardShortcut::begin().contains( key ) ) {
00348 QTextCursor cursor = parent->textCursor();
00349 cursor.movePosition( QTextCursor::Start );
00350 parent->setTextCursor( cursor );
00351 return true;
00352 } else if ( KStandardShortcut::end().contains( key ) ) {
00353 QTextCursor cursor = parent->textCursor();
00354 cursor.movePosition( QTextCursor::End );
00355 parent->setTextCursor( cursor );
00356 return true;
00357 } else if ( KStandardShortcut::beginningOfLine().contains( key ) ) {
00358 QTextCursor cursor = parent->textCursor();
00359 cursor.movePosition( QTextCursor::StartOfLine );
00360 parent->setTextCursor( cursor );
00361 return true;
00362 } else if ( KStandardShortcut::endOfLine().contains( key ) ) {
00363 QTextCursor cursor = parent->textCursor();
00364 cursor.movePosition( QTextCursor::EndOfLine );
00365 parent->setTextCursor( cursor );
00366 return true;
00367 } else if ( KStandardShortcut::pasteSelection().contains( key ) ) {
00368 QString text = QApplication::clipboard()->text( QClipboard::Selection );
00369 if ( !text.isEmpty() )
00370 parent->insertPlainText( text );
00371 return true;
00372 }
00373 return false;
00374 }
00375
00376 void KTextEdit::deleteWordBack()
00377 {
00378 QTextCursor cursor = textCursor();
00379 cursor.clearSelection();
00380 cursor.movePosition( QTextCursor::PreviousWord, QTextCursor::KeepAnchor );
00381 cursor.removeSelectedText();
00382 }
00383
00384 void KTextEdit::deleteWordForward()
00385 {
00386 QTextCursor cursor = textCursor();
00387 cursor.clearSelection();
00388 cursor.movePosition( QTextCursor::EndOfWord, QTextCursor::KeepAnchor );
00389 cursor.removeSelectedText();
00390 }
00391
00392 QMenu *KTextEdit::mousePopupMenu()
00393 {
00394 QMenu *popup = createStandardContextMenu();
00395 if (!popup) return 0;
00396 connect( popup, SIGNAL( triggered ( QAction* ) ),
00397 this, SLOT( menuActivated( QAction* ) ) );
00398
00399 const bool emptyDocument = document()->isEmpty();
00400 if( !isReadOnly() )
00401 {
00402 QList<QAction *> actionList = popup->actions();
00403 enum { UndoAct, RedoAct, CutAct, CopyAct, PasteAct, ClearAct, SelectAllAct, NCountActs };
00404 QAction *separatorAction = 0L;
00405 int idx = actionList.indexOf( actionList[SelectAllAct] ) + 1;
00406 if ( idx < actionList.count() )
00407 separatorAction = actionList.at( idx );
00408 if ( separatorAction )
00409 {
00410 KAction *clearAllAction = KStandardAction::clear(this, SLOT(undoableClear()), this);
00411 if ( emptyDocument )
00412 clearAllAction->setEnabled( false );
00413 popup->insertAction( separatorAction, clearAllAction );
00414 }
00415 }
00416 KIconTheme::assignIconsToContextMenu( isReadOnly() ? KIconTheme::ReadOnlyText
00417 : KIconTheme::TextEditor,
00418 popup->actions() );
00419
00420 if( !isReadOnly() )
00421 {
00422 popup->addSeparator();
00423 d->spellCheckAction = popup->addAction( KIcon( "tools-check-spelling" ),
00424 i18n( "Check Spelling..." ) );
00425 if ( emptyDocument )
00426 d->spellCheckAction->setEnabled( false );
00427 d->autoSpellCheckAction = popup->addAction( i18n( "Auto Spell Check" ) );
00428 d->autoSpellCheckAction->setCheckable( true );
00429 d->autoSpellCheckAction->setChecked( checkSpellingEnabled() );
00430 popup->addSeparator();
00431 d->allowTab = popup->addAction( i18n("Allow Tabulations") );
00432 d->allowTab->setCheckable( true );
00433 d->allowTab->setChecked( !tabChangesFocus() );
00434
00435 if (d->findReplaceEnabled)
00436 {
00437 KAction *findAction = KStandardAction::find( this, SLOT( slotFind() ), this );
00438 KAction *findNextAction = KStandardAction::findNext( this, SLOT( slotFindNext() ), this );
00439 KAction *replaceAction = KStandardAction::replace( this, SLOT( slotReplace() ), this );
00440 if (emptyDocument)
00441 {
00442 findAction->setEnabled(false);
00443 findNextAction->setEnabled(d->find != 0 );
00444 replaceAction->setEnabled(false);
00445 }
00446 popup->addSeparator();
00447 popup->addAction(findAction);
00448 popup->addAction(findNextAction);
00449 popup->addAction(replaceAction);
00450 }
00451 }
00452 return popup;
00453 }
00454
00455 void KTextEdit::contextMenuEvent(QContextMenuEvent *event)
00456 {
00457
00458 QTextCursor cursorAtMouse = cursorForPosition(event->pos());
00459 const int mousePos = cursorAtMouse.position();
00460 QTextCursor cursor = textCursor();
00461
00462
00463 const bool selectedWordClicked = cursor.hasSelection() &&
00464 mousePos >= cursor.selectionStart() &&
00465 mousePos <= cursor.selectionEnd();
00466
00467
00468
00469 QTextCursor wordSelectCursor(cursorAtMouse);
00470 wordSelectCursor.clearSelection();
00471 wordSelectCursor.select(QTextCursor::WordUnderCursor);
00472 QString selectedWord = wordSelectCursor.selectedText();
00473
00474
00475 wordSelectCursor.movePosition(QTextCursor::PreviousCharacter,
00476 QTextCursor::MoveAnchor, selectedWord.size());
00477 if (selectedWord.startsWith('\'') || selectedWord.startsWith('\"')) {
00478 selectedWord = selectedWord.right(selectedWord.size() - 1);
00479 wordSelectCursor.movePosition(QTextCursor::NextCharacter, QTextCursor::MoveAnchor);
00480 }
00481 if (selectedWord.endsWith('\'') || selectedWord.endsWith('\"'))
00482 selectedWord.chop(1);
00483 wordSelectCursor.movePosition(QTextCursor::NextCharacter,
00484 QTextCursor::KeepAnchor, selectedWord.size());
00485
00486 const bool wordIsMisspelled = checkSpellingEnabled() &&
00487 !selectedWord.isEmpty() &&
00488 highlighter() &&
00489 highlighter()->isWordMisspelled(selectedWord);
00490
00491
00492
00493
00494
00495 bool inQuote = false;
00496 if (d->spellInterface &&
00497 !d->spellInterface->shouldBlockBeSpellChecked(cursorAtMouse.block().text()))
00498 inQuote = true;
00499 if (!selectedWordClicked) {
00500 if (wordIsMisspelled && !inQuote)
00501 setTextCursor(wordSelectCursor);
00502 else
00503 setTextCursor(cursorAtMouse);
00504 cursor = textCursor();
00505 }
00506
00507
00508
00509 if (!wordIsMisspelled || selectedWordClicked || inQuote) {
00510 QMenu *popup = mousePopupMenu();
00511 if ( popup ) {
00512 popup->exec( event->globalPos() );
00513 delete popup;
00514 }
00515 }
00516 else {
00517 KMenu suggestions;
00518 KMenu menu;
00519
00520
00521 QStringList reps = highlighter()->suggestionsForWord(selectedWord);
00522 if (reps.count() > 0) {
00523 for (QStringList::const_iterator it = reps.constBegin(); it != reps.constEnd(); ++it) {
00524 suggestions.addAction(*it);
00525 }
00526
00527 }
00528 suggestions.setTitle(i18n("Suggestions"));
00529
00530 QAction *ignoreAction = menu.addAction(i18n("Ignore"));
00531 QAction *addToDictAction = menu.addAction(i18n("Add to Dictionary"));
00532 QAction *suggestionsAction = menu.addMenu(&suggestions);
00533 if (reps.count() == 0)
00534 suggestionsAction->setEnabled(false);
00535
00536
00537 const QAction *selectedAction = menu.exec(event->globalPos());
00538
00539 if (selectedAction) {
00540 Q_ASSERT(cursor.selectedText() == selectedWord);
00541
00542 if (selectedAction == ignoreAction) {
00543 highlighter()->ignoreWord(selectedWord);
00544 highlighter()->rehighlight();
00545 }
00546 else if (selectedAction == addToDictAction) {
00547 highlighter()->addWordToDictionary(selectedWord);
00548 highlighter()->rehighlight();
00549 }
00550
00551
00552 else {
00553 const QString replacement = selectedAction->text();
00554 Q_ASSERT(reps.contains(replacement));
00555 cursor.insertText(replacement);
00556 setTextCursor(cursor);
00557 }
00558 }
00559 }
00560 }
00561
00562 void KTextEdit::wheelEvent( QWheelEvent *event )
00563 {
00564 if ( KGlobalSettings::wheelMouseZooms() )
00565 QTextEdit::wheelEvent( event );
00566 else
00567 QAbstractScrollArea::wheelEvent( event );
00568 }
00569
00570 void KTextEdit::createHighlighter()
00571 {
00572 setHighlighter(new Sonnet::Highlighter(this, d->spellChechingConfigFileName));
00573 }
00574
00575 Sonnet::Highlighter* KTextEdit::highlighter() const
00576 {
00577 return d->highlighter;
00578 }
00579
00580 void KTextEdit::setHighlighter(Sonnet::Highlighter *_highLighter)
00581 {
00582 delete d->highlighter;
00583 d->highlighter = _highLighter;
00584 }
00585
00586 void KTextEdit::setCheckSpellingEnabled(bool check)
00587 {
00588 if (d->spellInterface)
00589 d->spellInterface->setSpellCheckingEnabled(check);
00590 else
00591 setCheckSpellingEnabledInternal(check);
00592 }
00593
00594 void KTextEdit::setCheckSpellingEnabledInternal( bool check )
00595 {
00596 emit checkSpellingChanged( check );
00597 if ( check == d->checkSpellingEnabled )
00598 return;
00599
00600
00601
00602
00603
00604 d->checkSpellingEnabled = check;
00605 if ( check )
00606 {
00607 if ( hasFocus() ) {
00608 createHighlighter();
00609 if (!spellCheckingLanguage().isEmpty())
00610 setSpellCheckingLanguage(spellCheckingLanguage());
00611 }
00612 }
00613 else
00614 {
00615 delete d->highlighter;
00616 d->highlighter = 0;
00617 }
00618 }
00619
00620 void KTextEdit::focusInEvent( QFocusEvent *event )
00621 {
00622 if ( d->checkSpellingEnabled && !isReadOnly() && !d->highlighter )
00623 createHighlighter();
00624
00625 QTextEdit::focusInEvent( event );
00626 }
00627
00628 bool KTextEdit::checkSpellingEnabled() const
00629 {
00630 if (d->spellInterface)
00631 return d->spellInterface->isSpellCheckingEnabled();
00632 else
00633 return checkSpellingEnabledInternal();
00634 }
00635
00636 bool KTextEdit::checkSpellingEnabledInternal() const
00637 {
00638 return d->checkSpellingEnabled;
00639 }
00640
00641 void KTextEdit::setReadOnly( bool readOnly )
00642 {
00643 if ( !readOnly && hasFocus() && d->checkSpellingEnabled && !d->highlighter )
00644 createHighlighter();
00645
00646 if ( readOnly == isReadOnly() )
00647 return;
00648
00649 if ( readOnly ) {
00650 delete d->highlighter;
00651 d->highlighter = 0;
00652
00653 d->customPalette = testAttribute( Qt::WA_SetPalette );
00654 QPalette p = palette();
00655 QColor color = p.color( QPalette::Disabled, QPalette::Background );
00656 p.setColor( QPalette::Base, color );
00657 p.setColor( QPalette::Background, color );
00658 setPalette( p );
00659 } else {
00660 if ( d->customPalette && testAttribute( Qt::WA_SetPalette ) ) {
00661 QPalette p = palette();
00662 QColor color = p.color( QPalette::Normal, QPalette::Base );
00663 p.setColor( QPalette::Base, color );
00664 p.setColor( QPalette::Background, color );
00665 setPalette( p );
00666 } else
00667 setPalette( QPalette() );
00668 }
00669
00670 QTextEdit::setReadOnly( readOnly );
00671 }
00672
00673 void KTextEdit::checkSpelling()
00674 {
00675 if(document()->isEmpty())
00676 {
00677 KMessageBox::information(this, i18n("Nothing to spell check."));
00678 return;
00679 }
00680 Sonnet::BackgroundChecker *backgroundSpellCheck = new Sonnet::BackgroundChecker(this);
00681 if(!d->spellCheckingLanguage.isEmpty())
00682 backgroundSpellCheck->changeLanguage(d->spellCheckingLanguage);
00683 Sonnet::Dialog *spellDialog = new Sonnet::Dialog(
00684 backgroundSpellCheck, 0);
00685 connect(spellDialog, SIGNAL(replace( const QString&, int,const QString&)),
00686 this, SLOT(spellCheckerCorrected( const QString&, int,const QString&)));
00687 connect(spellDialog, SIGNAL(misspelling( const QString&, int)),
00688 this, SLOT(spellCheckerMisspelling(const QString &,int)));
00689 connect(spellDialog, SIGNAL(autoCorrect(const QString&, const QString&)),
00690 this, SLOT(spellCheckerAutoCorrect(const QString&, const QString&)));
00691 connect(spellDialog, SIGNAL(done(const QString&)),
00692 this, SLOT(spellCheckerFinished()));
00693 connect(spellDialog, SIGNAL(cancel()),
00694 this, SLOT(spellCheckerCanceled()));
00695 connect(spellDialog, SIGNAL(stop()),
00696 this, SLOT(spellCheckerFinished()));
00697 connect(spellDialog, SIGNAL(spellCheckStatus(const QString &)),
00698 this,SIGNAL(spellCheckStatus(const QString &)));
00699 connect(spellDialog, SIGNAL(languageChanged(const QString &)),
00700 this, SIGNAL(languageChanged(const QString &)));
00701 d->originalBuffer = toPlainText();
00702 spellDialog->setBuffer(d->originalBuffer);
00703 spellDialog->show();
00704 }
00705
00706 void KTextEdit::highlightWord( int length, int pos )
00707 {
00708 QTextCursor cursor(document());
00709 cursor.setPosition(pos);
00710 cursor.setPosition(pos+length,QTextCursor::KeepAnchor);
00711 setTextCursor (cursor);
00712 ensureCursorVisible();
00713 }
00714
00715 void KTextEdit::replace()
00716 {
00717 if( document()->isEmpty() )
00718 return;
00719
00720 if ( d->repDlg ) {
00721 KWindowSystem::activateWindow( d->repDlg->winId() );
00722 } else {
00723 d->repDlg = new KReplaceDialog(this, 0,
00724 QStringList(), QStringList(), false);
00725 connect( d->repDlg, SIGNAL(okClicked()), this, SLOT(slotDoReplace()) );
00726 }
00727 d->repDlg->show();
00728 }
00729
00730 void KTextEdit::slotDoReplace()
00731 {
00732 if (!d->repDlg) {
00733
00734 return;
00735 }
00736
00737 delete d->replace;
00738 d->replace = new KReplace(d->repDlg->pattern(), d->repDlg->replacement(), d->repDlg->options(), this);
00739 d->repIndex = 0;
00740 if (d->replace->options() & KFind::FromCursor || d->replace->options() & KFind::FindBackwards) {
00741 d->repIndex = textCursor().anchor();
00742 }
00743
00744
00745
00746 connect(d->replace, SIGNAL(highlight(const QString &, int, int)),
00747 this, SLOT(slotFindHighlight(const QString &, int, int)));
00748 connect(d->replace, SIGNAL(findNext()), this, SLOT(slotReplaceNext()));
00749 connect(d->replace, SIGNAL(replace(const QString &, int, int, int)),
00750 this, SLOT(slotReplaceText(const QString &, int, int, int)));
00751
00752 d->repDlg->close();
00753 slotReplaceNext();
00754 }
00755
00756
00757 void KTextEdit::slotReplaceNext()
00758 {
00759 if (!d->replace)
00760 return;
00761
00762 if (!(d->replace->options() & KReplaceDialog::PromptOnReplace))
00763 viewport()->setUpdatesEnabled(false);
00764
00765 KFind::Result res = KFind::NoMatch;
00766
00767 if (d->replace->needData())
00768 d->replace->setData(toPlainText(), d->repIndex);
00769 res = d->replace->replace();
00770 if (!(d->replace->options() & KReplaceDialog::PromptOnReplace)) {
00771 viewport()->setUpdatesEnabled(true);
00772 viewport()->update();
00773 }
00774
00775 if (res == KFind::NoMatch) {
00776 d->replace->displayFinalDialog();
00777 d->replace->disconnect(this);
00778 d->replace->deleteLater();
00779 d->replace = 0;
00780 ensureCursorVisible();
00781
00782 } else {
00783
00784 }
00785 }
00786
00787
00788 void KTextEdit::slotDoFind()
00789 {
00790 if (!d->findDlg) {
00791
00792 return;
00793 }
00794
00795 delete d->find;
00796 d->find = new KFind(d->findDlg->pattern(), d->findDlg->options(), this);
00797 d->findIndex = 0;
00798 if (d->find->options() & KFind::FromCursor || d->find->options() & KFind::FindBackwards) {
00799 d->findIndex = textCursor().anchor();
00800 }
00801
00802
00803
00804 connect(d->find, SIGNAL(highlight(const QString &, int, int)),
00805 this, SLOT(slotFindHighlight(const QString &, int, int)));
00806 connect(d->find, SIGNAL(findNext()), this, SLOT(slotFindNext()));
00807
00808 d->findDlg->close();
00809 d->find->closeFindNextDialog();
00810 slotFindNext();
00811 }
00812
00813
00814 void KTextEdit::slotFindNext()
00815 {
00816 if (!d->find)
00817 return;
00818
00819 KFind::Result res = KFind::NoMatch;
00820 if (d->find->needData())
00821 d->find->setData(toPlainText(), d->findIndex);
00822 res = d->find->find();
00823
00824 if (res == KFind::NoMatch) {
00825 d->find->displayFinalDialog();
00826 d->find->disconnect(this);
00827 d->find->deleteLater();
00828 d->find = 0;
00829
00830 } else {
00831
00832 }
00833 }
00834
00835
00836 void KTextEdit::slotFind()
00837 {
00838 if( document()->isEmpty() )
00839 return;
00840
00841 if ( d->findDlg ) {
00842 KWindowSystem::activateWindow( d->findDlg->winId() );
00843 } else {
00844 d->findDlg = new KFindDialog(this);
00845 connect( d->findDlg, SIGNAL(okClicked()), this, SLOT(slotDoFind()) );
00846 }
00847 d->findDlg->show();
00848 }
00849
00850
00851 void KTextEdit::slotReplace()
00852 {
00853 if( document()->isEmpty() )
00854 return;
00855
00856 if ( d->repDlg ) {
00857 KWindowSystem::activateWindow( d->repDlg->winId() );
00858 } else {
00859 d->repDlg = new KReplaceDialog(this, 0,
00860 QStringList(), QStringList(), false);
00861 connect( d->repDlg, SIGNAL(okClicked()), this, SLOT(slotDoReplace()) );
00862 }
00863 d->repDlg->show();
00864 }
00865
00866 void KTextEdit::enableFindReplace( bool enabled )
00867 {
00868 d->findReplaceEnabled = enabled;
00869 }
00870
00871 void KTextEdit::setSpellInterface(KTextEditSpellInterface *spellInterface)
00872 {
00873 d->spellInterface = spellInterface;
00874 }
00875
00876 bool KTextEdit::Private::overrideShortcut(const QKeyEvent* event)
00877 {
00878 const int key = event->key() | event->modifiers();
00879
00880 if ( KStandardShortcut::copy().contains( key ) ) {
00881 return true;
00882 } else if ( KStandardShortcut::paste().contains( key ) ) {
00883 return true;
00884 } else if ( KStandardShortcut::cut().contains( key ) ) {
00885 return true;
00886 } else if ( KStandardShortcut::undo().contains( key ) ) {
00887 return true;
00888 } else if ( KStandardShortcut::redo().contains( key ) ) {
00889 return true;
00890 } else if ( KStandardShortcut::deleteWordBack().contains( key ) ) {
00891 return true;
00892 } else if ( KStandardShortcut::deleteWordForward().contains( key ) ) {
00893 return true;
00894 } else if ( KStandardShortcut::backwardWord().contains( key ) ) {
00895 return true;
00896 } else if ( KStandardShortcut::forwardWord().contains( key ) ) {
00897 return true;
00898 } else if ( KStandardShortcut::next().contains( key ) ) {
00899 return true;
00900 } else if ( KStandardShortcut::prior().contains( key ) ) {
00901 return true;
00902 } else if ( KStandardShortcut::begin().contains( key ) ) {
00903 return true;
00904 } else if ( KStandardShortcut::end().contains( key ) ) {
00905 return true;
00906 } else if ( KStandardShortcut::beginningOfLine().contains( key ) ) {
00907 return true;
00908 } else if ( KStandardShortcut::endOfLine().contains( key ) ) {
00909 return true;
00910 } else if ( KStandardShortcut::pasteSelection().contains( key ) ) {
00911 return true;
00912 } else if (event->modifiers() == Qt::ControlModifier &&
00913 (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) &&
00914 qobject_cast<KDialog*>(parent->window()) ) {
00915
00916 return true;
00917 }
00918 return false;
00919 }
00920
00921 void KTextEdit::keyPressEvent( QKeyEvent *event )
00922 {
00923 if (d->handleShortcut(event)) {
00924 event->accept();
00925 }else if (event->modifiers() == Qt::ControlModifier &&
00926 (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) &&
00927 qobject_cast<KDialog*>(window()) ) {
00928 event->ignore();
00929 } else {
00930 QTextEdit::keyPressEvent(event);
00931 }
00932 }
00933
00934 #include "ktextedit.moc"