• Skip to content
  • Skip to link menu
KDE 4.1 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KDEUI

ktextedit.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE libraries
00002    Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org>
00003                  2005 Michael Brade <brade@kde.org>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018    Boston, MA 02110-1301, USA.
00019 */
00020 
00021 #include "ktextedit.h"
00022 
00023 #include <QApplication>
00024 #include <QClipboard>
00025 #include <QKeyEvent>
00026 #include <QScrollBar>
00027 #include <QTextCursor>
00028 #include <dialog.h>
00029 #include "backgroundchecker.h"
00030 #include <kaction.h>
00031 #include <kcursor.h>
00032 #include <kglobalsettings.h>
00033 #include <kstandardaction.h>
00034 #include <kstandardshortcut.h>
00035 #include <kicon.h>
00036 #include <kiconloader.h>
00037 #include <klocale.h>
00038 #include <kdialog.h>
00039 #include <kreplacedialog.h>
00040 #include <kfinddialog.h>
00041 #include <kfind.h>
00042 #include <kreplace.h>
00043 #include <QMenu>
00044 #include <kmessagebox.h>
00045 #include <kwindowsystem.h>
00046 
00047 class KTextEdit::Private
00048 {
00049   public:
00050     Private( KTextEdit *_parent )
00051       : parent( _parent ),
00052         customPalette( false ),
00053         checkSpellingEnabled( false ),
00054         findReplaceEnabled(true),
00055         highlighter( 0 ), findDlg(0),find(0),repDlg(0),replace(0), findIndex(0), repIndex(0)
00056     {
00057     }
00058 
00059     ~Private()
00060     {
00061       delete highlighter;
00062       delete findDlg;
00063       delete find;
00064       delete replace;
00065       delete repDlg;
00066     }
00067 
00073     bool overrideShortcut(const QKeyEvent* e);
00077     bool handleShortcut(const QKeyEvent* e);
00078 
00079     void slotSpellCheckDone( const QString &s );
00080 
00081     void spellCheckerMisspelling( const QString &text, int pos );
00082     void spellCheckerCorrected( const QString &, int,const QString &);
00083     void spellCheckerAutoCorrect(const QString&,const QString&);
00084     void spellCheckerCanceled();
00085 
00086     void slotFindHighlight(const QString& text, int matchingIndex, int matchingLength);
00087     void slotReplaceText(const QString &text, int replacementIndex, int /*replacedLength*/, int matchedLength);
00088 
00089     void spellCheckerFinished();
00090     void toggleAutoSpellCheck();
00091     void slotAllowTab();
00092     void menuActivated( QAction* action );
00093 
00094     KTextEdit *parent;
00095     QAction *autoSpellCheckAction;
00096     QAction *allowTab;
00097     QAction *spellCheckAction;
00098     bool customPalette : 1;
00099 
00100     bool checkSpellingEnabled : 1;
00101     bool findReplaceEnabled: 1;
00102     QString originalBuffer;
00103     QString spellChechingConfigFileName;
00104     QString spellCheckingLanguage;
00105     Sonnet::Highlighter *highlighter;
00106     KFindDialog *findDlg;
00107     KFind *find;
00108     KReplaceDialog *repDlg;
00109     KReplace *replace;
00110     int findIndex, repIndex;
00111 };
00112 
00113 void KTextEdit::Private::spellCheckerCanceled()
00114 {
00115     parent->selectAll();
00116     parent->setPlainText(originalBuffer);
00117     spellCheckerFinished();
00118 }
00119 
00120 void KTextEdit::Private::spellCheckerAutoCorrect(const QString&,const QString&)
00121 {
00122     //TODO
00123 }
00124 
00125 void KTextEdit::Private::slotSpellCheckDone( const QString &s )
00126 {
00127 //Necessary ?
00128 //    if ( s != text() ) // TODO: toPlainText()?? (MiB)
00129 //        setText( s ); // setPlainText() ?! we'd loose rich text info
00130 }
00131 
00132 void KTextEdit::Private::spellCheckerMisspelling( const QString &text, int pos )
00133 {
00134     //kDebug()<<"TextEdit::Private::spellCheckerMisspelling :"<<text<<" pos :"<<pos;
00135     parent->highlightWord( text.length(), pos );
00136 }
00137 
00138 void KTextEdit::Private::spellCheckerCorrected( const QString& oldWord, int pos,const QString& newWord)
00139 {
00140   //kDebug()<<" oldWord :"<<oldWord<<" newWord :"<<newWord<<" pos : "<<pos;
00141   if (oldWord != newWord ) {
00142     QTextCursor cursor(parent->document());
00143     cursor.setPosition(pos);
00144     cursor.setPosition(pos+oldWord.length(),QTextCursor::KeepAnchor);
00145     cursor.insertText(newWord);
00146   }
00147 }
00148 
00149 void KTextEdit::Private::spellCheckerFinished()
00150 {
00151    QTextCursor cursor(parent->document());
00152    cursor.clearSelection();
00153    parent->setTextCursor(cursor);
00154    if (parent->highlighter())
00155        parent->highlighter()->rehighlight();
00156 }
00157 
00158 void KTextEdit::Private::toggleAutoSpellCheck()
00159 {
00160   parent->setCheckSpellingEnabled( !checkSpellingEnabled );
00161 }
00162 
00163 void KTextEdit::Private::slotAllowTab()
00164 {
00165   parent->setTabChangesFocus( !parent->tabChangesFocus() );
00166 }
00167 
00168 void KTextEdit::Private::menuActivated( QAction* action )
00169 {
00170   if ( action == spellCheckAction )
00171     parent->checkSpelling();
00172   else if ( action == autoSpellCheckAction )
00173     toggleAutoSpellCheck();
00174   else if ( action == allowTab )
00175     slotAllowTab();
00176 }
00177 
00178 
00179 void KTextEdit::Private::slotFindHighlight(const QString& text, int matchingIndex, int matchingLength)
00180 {
00181     Q_UNUSED(text)
00182     //kDebug() << "Highlight: [" << text << "] mi:" << matchingIndex << " ml:" << matchingLength;
00183     QTextCursor tc = parent->textCursor();
00184     tc.setPosition(matchingIndex);
00185     tc.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, matchingLength);
00186     parent->setTextCursor(tc);
00187     parent->ensureCursorVisible();
00188 }
00189 
00190 
00191 void KTextEdit::Private::slotReplaceText(const QString &text, int replacementIndex, int /*replacedLength*/, int matchedLength) {
00192     Q_UNUSED(text)
00193     //kDebug() << "Replace: [" << text << "] ri:" << replacementIndex << " rl:" << replacedLength << " ml:" << matchedLength;
00194     QTextCursor tc = parent->textCursor();
00195     tc.setPosition(replacementIndex);
00196     tc.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, matchedLength);
00197     tc.removeSelectedText();
00198     tc.insertText(repDlg->replacement());
00199     parent->setTextCursor(tc);
00200     if (replace->options() & KReplaceDialog::PromptOnReplace) {
00201         parent->ensureCursorVisible();
00202     }
00203 }
00204 
00205 KTextEdit::KTextEdit( const QString& text, QWidget *parent )
00206   : QTextEdit( text, parent ), d( new Private( this ) )
00207 {
00208   KCursor::setAutoHideCursor( this, true, false );
00209 }
00210 
00211 KTextEdit::KTextEdit( QWidget *parent )
00212   : QTextEdit( parent ), d( new Private( this ) )
00213 {
00214   KCursor::setAutoHideCursor( this, true, false );
00215 }
00216 
00217 KTextEdit::~KTextEdit()
00218 {
00219   delete d;
00220 }
00221 
00222 void KTextEdit::setSpellCheckingConfigFileName(const QString &_fileName)
00223 {
00224     d->spellChechingConfigFileName = _fileName;
00225 }
00226 
00227 void KTextEdit::setSpellCheckingLanguage(const QString &_language)
00228 {
00229     d->spellCheckingLanguage = _language;
00230 }
00231 
00232 bool KTextEdit::event(QEvent* ev)
00233 {
00234     if (ev->type() == QEvent::ShortcutOverride) {
00235         QKeyEvent *e = static_cast<QKeyEvent *>( ev );
00236         if (d->overrideShortcut(e)) {
00237             e->accept();
00238             return true;
00239         }
00240     }
00241     return QTextEdit::event(ev);
00242 }
00243 
00244 bool KTextEdit::Private::handleShortcut(const QKeyEvent* event)
00245 {
00246   const int key = event->key() | event->modifiers();
00247 
00248   if ( KStandardShortcut::copy().contains( key ) ) {
00249     parent->copy();
00250     return true;
00251   } else if ( KStandardShortcut::paste().contains( key ) ) {
00252     parent->paste();
00253     return true;
00254   } else if ( KStandardShortcut::cut().contains( key ) ) {
00255     parent->cut();
00256     return true;
00257   } else if ( KStandardShortcut::undo().contains( key ) ) {
00258     parent->document()->undo();
00259     return true;
00260   } else if ( KStandardShortcut::redo().contains( key ) ) {
00261     parent->document()->redo();
00262     return true;
00263   } else if ( KStandardShortcut::deleteWordBack().contains( key ) ) {
00264     parent->deleteWordBack();
00265     return true;
00266   } else if ( KStandardShortcut::deleteWordForward().contains( key ) ) {
00267     parent->deleteWordForward();
00268     return true;
00269   } else if ( KStandardShortcut::backwardWord().contains( key ) ) {
00270     QTextCursor cursor = parent->textCursor();
00271     cursor.movePosition( QTextCursor::PreviousWord );
00272     parent->setTextCursor( cursor );
00273     return true;
00274   } else if ( KStandardShortcut::forwardWord().contains( key ) ) {
00275     QTextCursor cursor = parent->textCursor();
00276     cursor.movePosition( QTextCursor::NextWord );
00277     parent->setTextCursor( cursor );
00278     return true;
00279   } else if ( KStandardShortcut::next().contains( key ) ) {
00280     QTextCursor cursor = parent->textCursor();
00281     int targetY = parent->verticalScrollBar()->value() + parent->viewport()->height();
00282     bool moved = false;
00283     do {
00284       moved = cursor.movePosition( QTextCursor::Down );
00285       parent->setTextCursor( cursor );
00286     } while ( moved && parent->verticalScrollBar()->value() < targetY );
00287     return true;
00288   } else if ( KStandardShortcut::prior().contains( key ) ) {
00289     QTextCursor cursor = parent->textCursor();
00290     int targetY = parent->verticalScrollBar()->value() - parent->viewport()->height();
00291     bool moved = false;
00292     do {
00293       moved = cursor.movePosition( QTextCursor::Up );
00294       parent->setTextCursor( cursor );
00295     } while ( moved && parent->verticalScrollBar()->value() > targetY );
00296     return true;
00297   } else if ( KStandardShortcut::begin().contains( key ) ) {
00298     QTextCursor cursor = parent->textCursor();
00299     cursor.movePosition( QTextCursor::Start );
00300     parent->setTextCursor( cursor );
00301     return true;
00302   } else if ( KStandardShortcut::end().contains( key ) ) {
00303     QTextCursor cursor = parent->textCursor();
00304     cursor.movePosition( QTextCursor::End );
00305     parent->setTextCursor( cursor );
00306     return true;
00307   } else if ( KStandardShortcut::beginningOfLine().contains( key ) ) {
00308     QTextCursor cursor = parent->textCursor();
00309     cursor.movePosition( QTextCursor::StartOfLine );
00310     parent->setTextCursor( cursor );
00311     return true;
00312   } else if ( KStandardShortcut::endOfLine().contains( key ) ) {
00313     QTextCursor cursor = parent->textCursor();
00314     cursor.movePosition( QTextCursor::EndOfLine );
00315     parent->setTextCursor( cursor );
00316     return true;
00317   } else if ( KStandardShortcut::pasteSelection().contains( key ) ) {
00318     QString text = QApplication::clipboard()->text( QClipboard::Selection );
00319     if ( !text.isEmpty() )
00320       parent->insertPlainText( text );  // TODO: check if this is html? (MiB)
00321     return true;
00322   }
00323   return false;
00324 }
00325 
00326 void KTextEdit::deleteWordBack()
00327 {
00328   QTextCursor cursor = textCursor();
00329   cursor.clearSelection();
00330   cursor.movePosition( QTextCursor::PreviousWord, QTextCursor::KeepAnchor );
00331   cursor.removeSelectedText();
00332 }
00333 
00334 void KTextEdit::deleteWordForward()
00335 {
00336   QTextCursor cursor = textCursor();
00337   cursor.clearSelection();
00338   cursor.movePosition( QTextCursor::EndOfWord, QTextCursor::KeepAnchor );
00339   cursor.removeSelectedText();
00340 }
00341 
00342 QMenu *KTextEdit::mousePopupMenu()
00343 {
00344   QMenu *popup = createStandardContextMenu();
00345   connect( popup, SIGNAL( triggered ( QAction* ) ),
00346              this, SLOT( menuActivated( QAction* ) ) );
00347 
00348   bool emptyDocument = document()->isEmpty();
00349   if( !isReadOnly() )
00350   {
00351       QList<QAction *> actionList = popup->actions();
00352       enum { UndoAct, RedoAct, CutAct, CopyAct, PasteAct, ClearAct, SelectAllAct, NCountActs };
00353       QAction *separatorAction = 0L;
00354       int idx = actionList.indexOf( actionList[SelectAllAct] ) + 1;
00355       if ( idx < actionList.count() )
00356           separatorAction = actionList.at( idx );
00357       if ( separatorAction )
00358       {
00359           KAction *clearAllAction = KStandardAction::clear( this, SLOT( clear() ), this) ;
00360           if ( emptyDocument )
00361               clearAllAction->setEnabled( false );
00362           popup->insertAction( separatorAction, clearAllAction );
00363       }
00364   }
00365   KIconTheme::assignIconsToContextMenu( isReadOnly() ? KIconTheme::ReadOnlyText
00366                                           : KIconTheme::TextEditor,
00367                                           popup->actions() );
00368 
00369   if( !isReadOnly() )
00370   {
00371       popup->addSeparator();
00372       d->spellCheckAction = popup->addAction( KIcon( "tools-check-spelling" ),
00373                                               i18n( "Check Spelling..." ) );
00374       if ( emptyDocument )
00375         d->spellCheckAction->setEnabled( false );
00376       d->autoSpellCheckAction = popup->addAction( i18n( "Auto Spell Check" ) );
00377       d->autoSpellCheckAction->setCheckable( true );
00378       d->autoSpellCheckAction->setChecked( d->checkSpellingEnabled );
00379       popup->addSeparator();
00380       d->allowTab = popup->addAction( i18n("Allow Tabulations") );
00381       d->allowTab->setCheckable( true );
00382       d->allowTab->setChecked( !tabChangesFocus() );
00383 
00384       if (d->findReplaceEnabled)
00385       {
00386           KAction *findAction = KStandardAction::find( this, SLOT( slotFind() ), this );
00387           KAction *findNextAction = KStandardAction::findNext( this, SLOT( slotFindNext() ), this );
00388           KAction *replaceAction = KStandardAction::replace( this, SLOT( slotReplace() ), this );
00389           if (emptyDocument)
00390           {
00391               findAction->setEnabled(false);
00392               findNextAction->setEnabled(d->find != 0 );
00393               replaceAction->setEnabled(false);
00394           }
00395           popup->addSeparator();
00396           popup->addAction(findAction);
00397           popup->addAction(findNextAction);
00398           popup->addAction(replaceAction);
00399       }
00400   }
00401   return popup;
00402 }
00403 
00404 void KTextEdit::contextMenuEvent( QContextMenuEvent *event )
00405 {
00406   QMenu *popup = mousePopupMenu();
00407   popup->exec( event->globalPos() );
00408 
00409   delete popup;
00410 }
00411 
00412 void KTextEdit::wheelEvent( QWheelEvent *event )
00413 {
00414   if ( KGlobalSettings::wheelMouseZooms() )
00415     QTextEdit::wheelEvent( event );
00416   else // thanks, we don't want to zoom, so skip QTextEdit's impl.
00417     QAbstractScrollArea::wheelEvent( event );
00418 }
00419 
00420 void KTextEdit::createHighlighter()
00421 {
00422     setHighlighter(new Sonnet::Highlighter(this, d->spellChechingConfigFileName));
00423 }
00424 
00425 Sonnet::Highlighter* KTextEdit::highlighter() const
00426 {
00427     return d->highlighter;
00428 }
00429 
00430 void KTextEdit::setHighlighter(Sonnet::Highlighter *_highLighter)
00431 {
00432     delete d->highlighter;
00433     d->highlighter = _highLighter;
00434 }
00435 
00436 void KTextEdit::setCheckSpellingEnabled( bool check )
00437 {
00438   emit checkSpellingChanged( check );
00439   if ( check == d->checkSpellingEnabled )
00440     return;
00441 
00442   // From the above statment we know know that if we're turning checking
00443   // on that we need to create a new highlighter and if we're turning it
00444   // off we should remove the old one.
00445 
00446   d->checkSpellingEnabled = check;
00447     if ( check )
00448     {
00449         if ( hasFocus() ) {
00450             createHighlighter();
00451         }
00452     }
00453     else
00454     {
00455         delete d->highlighter;
00456         d->highlighter = 0;
00457     }
00458 }
00459 
00460 void KTextEdit::focusInEvent( QFocusEvent *event )
00461 {
00462   if ( d->checkSpellingEnabled && !isReadOnly() && !d->highlighter )
00463     createHighlighter();
00464 
00465   QTextEdit::focusInEvent( event );
00466 }
00467 
00468 bool KTextEdit::checkSpellingEnabled() const
00469 {
00470   return d->checkSpellingEnabled;
00471 }
00472 
00473 void KTextEdit::setReadOnly( bool readOnly )
00474 {
00475   if ( !readOnly && hasFocus() && d->checkSpellingEnabled && !d->highlighter )
00476     createHighlighter();
00477 
00478   if ( readOnly == isReadOnly() )
00479     return;
00480 
00481   if ( readOnly ) {
00482     delete d->highlighter;
00483     d->highlighter = 0;
00484 
00485     d->customPalette = testAttribute( Qt::WA_SetPalette );
00486     QPalette p = palette();
00487     QColor color = p.color( QPalette::Disabled, QPalette::Background );
00488     p.setColor( QPalette::Base, color );
00489     p.setColor( QPalette::Background, color );
00490     setPalette( p );
00491   } else {
00492     if ( d->customPalette && testAttribute( Qt::WA_SetPalette ) ) {
00493         QPalette p = palette();
00494         QColor color = p.color( QPalette::Normal, QPalette::Base );
00495         p.setColor( QPalette::Base, color );
00496         p.setColor( QPalette::Background, color );
00497         setPalette( p );
00498     } else
00499         setPalette( QPalette() );
00500   }
00501 
00502   QTextEdit::setReadOnly( readOnly );
00503 }
00504 
00505 void KTextEdit::checkSpelling()
00506 {
00507   if(document()->isEmpty())
00508   {
00509       KMessageBox::information(this, i18n("Nothing to spell check."));
00510       return;
00511   }
00512   Sonnet::BackgroundChecker *backgroundSpellCheck = new Sonnet::BackgroundChecker(this);
00513   if(!d->spellCheckingLanguage.isEmpty())
00514      backgroundSpellCheck->changeLanguage(d->spellCheckingLanguage);
00515   Sonnet::Dialog *spellDialog = new Sonnet::Dialog(
00516       backgroundSpellCheck, 0);
00517   connect(spellDialog, SIGNAL(replace( const QString&, int,const QString&)),
00518           this, SLOT(spellCheckerCorrected( const QString&, int,const QString&)));
00519   connect(spellDialog, SIGNAL(misspelling( const QString&, int)),
00520           this, SLOT(spellCheckerMisspelling(const QString &,int)));
00521   connect(spellDialog, SIGNAL(autoCorrect(const QString&, const QString&)),
00522           this, SLOT(spellCheckerAutoCorrect(const QString&, const QString&)));
00523   connect(spellDialog, SIGNAL(done(const QString&)),
00524           this, SLOT(spellCheckerFinished()));
00525   connect(spellDialog, SIGNAL(cancel()),
00526           this, SLOT(spellCheckerCanceled()));
00527   connect(spellDialog, SIGNAL(stop()),
00528           this, SLOT(spellCheckerFinished()));
00529   connect(spellDialog, SIGNAL(spellCheckStatus(const QString &)),
00530           this,SIGNAL(spellCheckStatus(const QString &)));
00531   connect(spellDialog, SIGNAL(languageChanged(const QString &)),
00532           this, SIGNAL(languageChanged(const QString &)));
00533   d->originalBuffer = toPlainText();
00534   spellDialog->setBuffer(d->originalBuffer);
00535   spellDialog->show();
00536 }
00537 
00538 void KTextEdit::highlightWord( int length, int pos )
00539 {
00540   QTextCursor cursor(document());
00541   cursor.setPosition(pos);
00542   cursor.setPosition(pos+length,QTextCursor::KeepAnchor);
00543   setTextCursor (cursor);
00544   ensureCursorVisible();
00545 }
00546 
00547 void KTextEdit::replace()
00548 {
00549      if( document()->isEmpty() )  // saves having to track the text changes
00550         return;
00551 
00552     if ( d->repDlg ) {
00553       KWindowSystem::activateWindow( d->repDlg->winId() );
00554     } else {
00555       d->repDlg = new KReplaceDialog(this, 0,
00556                                     QStringList(), QStringList(), false);
00557       connect( d->repDlg, SIGNAL(okClicked()), this, SLOT(slotDoReplace()) );
00558     }
00559     d->repDlg->show();
00560 }
00561 
00562 void KTextEdit::slotDoReplace()
00563 {
00564     if (!d->repDlg) {
00565         // Should really assert()
00566         return;
00567     }
00568 
00569     delete d->replace;
00570     d->replace = new KReplace(d->repDlg->pattern(), d->repDlg->replacement(), d->repDlg->options(), this);
00571     d->repIndex = 0;
00572     if (d->replace->options() & KFind::FromCursor || d->replace->options() & KFind::FindBackwards) {
00573         d->repIndex = textCursor().anchor();
00574     }
00575 
00576     // Connect highlight signal to code which handles highlighting
00577     // of found text.
00578     connect(d->replace, SIGNAL(highlight(const QString &, int, int)),
00579             this, SLOT(slotFindHighlight(const QString &, int, int)));
00580     connect(d->replace, SIGNAL(findNext()), this, SLOT(slotReplaceNext()));
00581     connect(d->replace, SIGNAL(replace(const QString &, int, int, int)),
00582             this, SLOT(slotReplaceText(const QString &, int, int, int)));
00583 
00584     d->repDlg->close();
00585     slotReplaceNext();
00586 }
00587 
00588 
00589 void KTextEdit::slotReplaceNext()
00590 {
00591     if (!d->replace)
00592         return;
00593 
00594     if (!(d->replace->options() & KReplaceDialog::PromptOnReplace))
00595         viewport()->setUpdatesEnabled(false);
00596 
00597     KFind::Result res = KFind::NoMatch;
00598 
00599     if (d->replace->needData())
00600         d->replace->setData(toPlainText(), d->repIndex);
00601     res = d->replace->replace();
00602     if (!(d->replace->options() & KReplaceDialog::PromptOnReplace)) {
00603         viewport()->setUpdatesEnabled(true);
00604         viewport()->update();
00605     }
00606 
00607     if (res == KFind::NoMatch) {
00608         d->replace->displayFinalDialog();
00609         d->replace->disconnect(this);
00610         d->replace->deleteLater(); // we are in a slot connected to m_replace, don't delete it right away
00611         d->replace = 0;
00612         ensureCursorVisible();
00613         //or           if ( m_replace->shouldRestart() ) { reinit (w/o FromCursor) and call slotReplaceNext(); }
00614     } else {
00615         //m_replace->closeReplaceNextDialog();
00616     }
00617 }
00618 
00619 
00620 void KTextEdit::slotDoFind()
00621 {
00622     if (!d->findDlg) {
00623         // Should really assert()
00624         return;
00625     }
00626 
00627     delete d->find;
00628     d->find = new KFind(d->findDlg->pattern(), d->findDlg->options(), this);
00629     d->findIndex = 0;
00630     if (d->find->options() & KFind::FromCursor || d->find->options() & KFind::FindBackwards) {
00631         d->findIndex = textCursor().anchor();
00632     }
00633 
00634     // Connect highlight signal to code which handles highlighting
00635     // of found text.
00636     connect(d->find, SIGNAL(highlight(const QString &, int, int)),
00637             this, SLOT(slotFindHighlight(const QString &, int, int)));
00638     connect(d->find, SIGNAL(findNext()), this, SLOT(slotFindNext()));
00639 
00640     d->findDlg->close();
00641     d->find->closeFindNextDialog();
00642     slotFindNext();
00643 }
00644 
00645 
00646 void KTextEdit::slotFindNext()
00647 {
00648     if (!d->find)
00649         return;
00650 
00651     KFind::Result res = KFind::NoMatch;
00652     if (d->find->needData())
00653         d->find->setData(toPlainText(), d->findIndex);
00654     res = d->find->find();
00655 
00656     if (res == KFind::NoMatch) {
00657         d->find->displayFinalDialog();
00658         d->find->disconnect(this);
00659         d->find->deleteLater(); // we are in a slot connected to m_find, don't delete right away
00660         d->find = 0;
00661         //or           if ( m_find->shouldRestart() ) { reinit (w/o FromCursor) and call slotFindNext(); }
00662     } else {
00663         //m_find->closeFindNextDialog();
00664     }
00665 }
00666 
00667 
00668 void KTextEdit::slotFind()
00669 {
00670     if( document()->isEmpty() )  // saves having to track the text changes
00671         return;
00672 
00673     if ( d->findDlg ) {
00674       KWindowSystem::activateWindow( d->findDlg->winId() );
00675     } else {
00676       d->findDlg = new KFindDialog(this);
00677       connect( d->findDlg, SIGNAL(okClicked()), this, SLOT(slotDoFind()) );
00678     }
00679     d->findDlg->show();
00680 }
00681 
00682 
00683 void KTextEdit::slotReplace()
00684 {
00685     if( document()->isEmpty() )  // saves having to track the text changes
00686         return;
00687 
00688     if ( d->repDlg ) {
00689       KWindowSystem::activateWindow( d->repDlg->winId() );
00690     } else {
00691       d->repDlg = new KReplaceDialog(this, 0,
00692                                     QStringList(), QStringList(), false);
00693       connect( d->repDlg, SIGNAL(okClicked()), this, SLOT(slotDoReplace()) );
00694     }
00695     d->repDlg->show();
00696 }
00697 
00698 void KTextEdit::enableFindReplace( bool enabled )
00699 {
00700     d->findReplaceEnabled = enabled;
00701 }
00702 
00703 bool KTextEdit::Private::overrideShortcut(const QKeyEvent* event)
00704 {
00705   const int key = event->key() | event->modifiers();
00706 
00707   if ( KStandardShortcut::copy().contains( key ) ) {
00708     return true;
00709   } else if ( KStandardShortcut::paste().contains( key ) ) {
00710     return true;
00711   } else if ( KStandardShortcut::cut().contains( key ) ) {
00712     return true;
00713   } else if ( KStandardShortcut::undo().contains( key ) ) {
00714     return true;
00715   } else if ( KStandardShortcut::redo().contains( key ) ) {
00716     return true;
00717   } else if ( KStandardShortcut::deleteWordBack().contains( key ) ) {
00718     return true;
00719   } else if ( KStandardShortcut::deleteWordForward().contains( key ) ) {
00720     return true;
00721   } else if ( KStandardShortcut::backwardWord().contains( key ) ) {
00722     return true;
00723   } else if ( KStandardShortcut::forwardWord().contains( key ) ) {
00724     return true;
00725   } else if ( KStandardShortcut::next().contains( key ) ) {
00726     return true;
00727   } else if ( KStandardShortcut::prior().contains( key ) ) {
00728     return true;
00729   } else if ( KStandardShortcut::begin().contains( key ) ) {
00730     return true;
00731   } else if ( KStandardShortcut::end().contains( key ) ) {
00732     return true;
00733   } else if ( KStandardShortcut::beginningOfLine().contains( key ) ) {
00734     return true;
00735   } else if ( KStandardShortcut::endOfLine().contains( key ) ) {
00736     return true;
00737   } else if ( KStandardShortcut::pasteSelection().contains( key ) ) {
00738     return true;
00739   } else if (event->modifiers() == Qt::ControlModifier &&
00740             (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) &&
00741               qobject_cast<KDialog*>(parent->window()) ) {
00742     // ignore Ctrl-Return so that KDialogs can close the dialog
00743     return true;
00744   }
00745   return false;
00746 }
00747 
00748 void KTextEdit::keyPressEvent( QKeyEvent *event )
00749 {
00750     if (d->handleShortcut(event)) {
00751         event->accept();
00752     }else if (event->modifiers() == Qt::ControlModifier &&
00753             (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) &&
00754               qobject_cast<KDialog*>(window()) ) {
00755         event->ignore();
00756     } else {
00757         QTextEdit::keyPressEvent(event);
00758     }
00759 }
00760 
00761 #include "ktextedit.moc"

KDEUI

Skip menu "KDEUI"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • KIO
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal