00001
00002
00003
00004
00005
00006 #include <config.h>
00007
00008 #include "kmedit.h"
00009 #include "kmlineeditspell.h"
00010
00011 #define REALLY_WANT_KMCOMPOSEWIN_H
00012 #include "kmcomposewin.h"
00013 #undef REALLY_WANT_KMCOMPOSEWIN_H
00014 #include "kmmsgdict.h"
00015 #include "kmfolder.h"
00016 #include "kmcommands.h"
00017
00018 #include <maillistdrag.h>
00019 using KPIM::MailListDrag;
00020
00021 #include <libkdepim/kfileio.h>
00022 #include <libemailfunctions/email.h>
00023
00024 #include <kcursor.h>
00025 #include <kprocess.h>
00026
00027 #include <kpopupmenu.h>
00028 #include <kdebug.h>
00029 #include <kmessagebox.h>
00030 #include <kurldrag.h>
00031
00032 #include <ktempfile.h>
00033 #include <klocale.h>
00034 #include <kapplication.h>
00035 #include <kdirwatch.h>
00036 #include <kiconloader.h>
00037
00038 #include "globalsettings.h"
00039 #include "replyphrases.h"
00040
00041 #include <kspell.h>
00042 #include <kspelldlg.h>
00043 #include <spellingfilter.h>
00044 #include <ksyntaxhighlighter.h>
00045
00046 #include <qregexp.h>
00047 #include <qbuffer.h>
00048 #include <qevent.h>
00049
00050 #include <sys/stat.h>
00051 #include <sys/types.h>
00052 #include <stdlib.h>
00053 #include <unistd.h>
00054 #include <errno.h>
00055 #include <fcntl.h>
00056 #include <assert.h>
00057
00058
00059 void KMEdit::contentsDragEnterEvent(QDragEnterEvent *e)
00060 {
00061 if (e->provides(MailListDrag::format()))
00062 e->accept(true);
00063 else if (e->provides("image/png"))
00064 e->accept();
00065 else
00066 return KEdit::contentsDragEnterEvent(e);
00067 }
00068
00069 void KMEdit::contentsDragMoveEvent(QDragMoveEvent *e)
00070 {
00071 if (e->provides(MailListDrag::format()))
00072 e->accept();
00073 else if (e->provides("image/png"))
00074 e->accept();
00075 else
00076 return KEdit::contentsDragMoveEvent(e);
00077 }
00078
00079 void KMEdit::keyPressEvent( QKeyEvent* e )
00080 {
00081 if( e->key() == Key_Return ) {
00082 int line, col;
00083 getCursorPosition( &line, &col );
00084 QString lineText = text( line );
00085
00086 lineText.truncate( lineText.length() - 1 );
00087
00088
00089 if( ( col > 0 ) && ( col < int( lineText.length() ) ) ) {
00090 bool isQuotedLine = false;
00091 uint bot = 0;
00092 while( bot < lineText.length() ) {
00093 if( ( lineText[bot] == '>' ) || ( lineText[bot] == '|' ) ) {
00094 isQuotedLine = true;
00095 ++bot;
00096 }
00097 else if( lineText[bot].isSpace() ) {
00098 ++bot;
00099 }
00100 else {
00101 break;
00102 }
00103 }
00104
00105 KEdit::keyPressEvent( e );
00106
00107
00108
00109
00110 if( isQuotedLine
00111 && ( bot != lineText.length() )
00112 && ( col >= int( bot ) ) ) {
00113
00114
00115
00116 getCursorPosition( &line, &col );
00117 QString newLine = text( line );
00118
00119
00120 unsigned int leadingWhiteSpaceCount = 0;
00121 while( ( leadingWhiteSpaceCount < newLine.length() )
00122 && newLine[leadingWhiteSpaceCount].isSpace() ) {
00123 ++leadingWhiteSpaceCount;
00124 }
00125 newLine = newLine.replace( 0, leadingWhiteSpaceCount,
00126 lineText.left( bot ) );
00127 removeParagraph( line );
00128 insertParagraph( newLine, line );
00129
00130
00131
00132 setCursorPosition( line, 0 );
00133 }
00134 }
00135 else
00136 KEdit::keyPressEvent( e );
00137 }
00138 else
00139 KEdit::keyPressEvent( e );
00140 }
00141
00142 void KMEdit::contentsDropEvent(QDropEvent *e)
00143 {
00144 if (e->provides(MailListDrag::format())) {
00145
00146 QByteArray serNums;
00147 MailListDrag::decode( e, serNums );
00148 QBuffer serNumBuffer(serNums);
00149 serNumBuffer.open(IO_ReadOnly);
00150 QDataStream serNumStream(&serNumBuffer);
00151 Q_UINT32 serNum;
00152 KMFolder *folder = 0;
00153 int idx;
00154 QPtrList<KMMsgBase> messageList;
00155 while (!serNumStream.atEnd()) {
00156 KMMsgBase *msgBase = 0;
00157 serNumStream >> serNum;
00158 KMMsgDict::instance()->getLocation(serNum, &folder, &idx);
00159 if (folder)
00160 msgBase = folder->getMsgBase(idx);
00161 if (msgBase)
00162 messageList.append( msgBase );
00163 }
00164 serNumBuffer.close();
00165 uint identity = folder ? folder->identity() : 0;
00166 KMCommand *command =
00167 new KMForwardAttachedCommand(mComposer, messageList,
00168 identity, mComposer);
00169 command->start();
00170 }
00171 else if( e->provides("image/png") ) {
00172 emit attachPNGImageData(e->encodedData("image/png"));
00173 }
00174 else if( KURLDrag::canDecode( e ) ) {
00175 KURL::List urlList;
00176 if( KURLDrag::decode( e, urlList ) ) {
00177 KPopupMenu p;
00178 p.insertItem( i18n("Add as Text"), 0 );
00179 p.insertItem( i18n("Add as Attachment"), 1 );
00180 int id = p.exec( mapToGlobal( e->pos() ) );
00181 switch ( id) {
00182 case 0:
00183 for ( KURL::List::Iterator it = urlList.begin();
00184 it != urlList.end(); ++it ) {
00185 insert( (*it).url() );
00186 }
00187 break;
00188 case 1:
00189 for ( KURL::List::Iterator it = urlList.begin();
00190 it != urlList.end(); ++it ) {
00191 mComposer->addAttach( *it );
00192 }
00193 break;
00194 }
00195 }
00196 else if ( QTextDrag::canDecode( e ) ) {
00197 QString s;
00198 if ( QTextDrag::decode( e, s ) )
00199 insert( s );
00200 }
00201 else
00202 kdDebug(5006) << "KMEdit::contentsDropEvent, unable to add dropped object" << endl;
00203 }
00204 else if( e->provides("text/x-textsnippet") ) {
00205 emit insertSnippet();
00206 }
00207 else {
00208 KEdit::contentsDropEvent(e);
00209 }
00210 }
00211
00212 KMEdit::KMEdit(QWidget *parent, KMComposeWin* composer,
00213 KSpellConfig* autoSpellConfig,
00214 const char *name)
00215 : KEdit( parent, name ),
00216 mComposer( composer ),
00217 mKSpell( 0 ),
00218 mSpellConfig( autoSpellConfig ),
00219 mSpellingFilter( 0 ),
00220 mExtEditorTempFile( 0 ),
00221 mExtEditorTempFileWatcher( 0 ),
00222 mExtEditorProcess( 0 ),
00223 mUseExtEditor( false ),
00224 mWasModifiedBeforeSpellCheck( false ),
00225 mSpellChecker( 0 ),
00226 mSpellLineEdit( false ),
00227 mPasteMode( QClipboard::Clipboard )
00228 {
00229 connect( this, SIGNAL(selectionChanged()), this, SLOT(slotSelectionChanged()) );
00230 installEventFilter(this);
00231 KCursor::setAutoHideCursor( this, true, true );
00232 setOverwriteEnabled( true );
00233 }
00234
00235
00236 void KMEdit::initializeAutoSpellChecking()
00237 {
00238 if ( mSpellChecker )
00239 return;
00240 QColor defaultColor1( 0x00, 0x80, 0x00 );
00241 QColor defaultColor2( 0x00, 0x70, 0x00 );
00242 QColor defaultColor3( 0x00, 0x60, 0x00 );
00243 QColor defaultForeground( kapp->palette().active().text() );
00244
00245 QColor c = Qt::red;
00246 KConfigGroup readerConfig( KMKernel::config(), "Reader" );
00247 QColor col1;
00248 if ( !readerConfig.readBoolEntry( "defaultColors", true ) )
00249 col1 = readerConfig.readColorEntry( "ForegroundColor", &defaultForeground );
00250 else
00251 col1 = defaultForeground;
00252 QColor col2 = readerConfig.readColorEntry( "QuotedText3", &defaultColor3 );
00253 QColor col3 = readerConfig.readColorEntry( "QuotedText2", &defaultColor2 );
00254 QColor col4 = readerConfig.readColorEntry( "QuotedText1", &defaultColor1 );
00255 QColor misspelled = readerConfig.readColorEntry( "MisspelledColor", &c );
00256 mSpellChecker = new KDictSpellingHighlighter( this, true,
00257 false,
00258 misspelled,
00259 true,
00260 col1, col2, col3, col4,
00261 mSpellConfig );
00262
00263 connect( mSpellChecker, SIGNAL(newSuggestions(const QString&, const QStringList&, unsigned int)),
00264 this, SLOT(addSuggestion(const QString&, const QStringList&, unsigned int)) );
00265 }
00266
00267
00268 QPopupMenu *KMEdit::createPopupMenu( const QPoint& pos )
00269 {
00270 enum { IdUndo, IdRedo, IdSep1, IdCut, IdCopy, IdPaste, IdClear, IdSep2, IdSelectAll };
00271
00272 QPopupMenu *menu = KEdit::createPopupMenu( pos );
00273 if ( !QApplication::clipboard()->image().isNull() ) {
00274 int id = menu->idAt(0);
00275 menu->setItemEnabled( id - IdPaste, true);
00276 }
00277
00278 return menu;
00279 }
00280
00281 void KMEdit::deleteAutoSpellChecking()
00282 {
00283 delete mSpellChecker;
00284 mSpellChecker =0;
00285 }
00286
00287 void KMEdit::addSuggestion(const QString& text, const QStringList& lst, unsigned int )
00288 {
00289 mReplacements[text] = lst;
00290 }
00291
00292 void KMEdit::setSpellCheckingActive(bool spellCheckingActive)
00293 {
00294 if ( mSpellChecker ) {
00295 mSpellChecker->setActive(spellCheckingActive);
00296 }
00297 }
00298
00299
00300 KMEdit::~KMEdit()
00301 {
00302 removeEventFilter(this);
00303
00304 delete mKSpell;
00305 delete mSpellChecker;
00306 mSpellChecker = 0;
00307
00308 }
00309
00310
00311
00312 QString KMEdit::brokenText()
00313 {
00314 QString temp, line;
00315
00316 int num_lines = numLines();
00317 for (int i = 0; i < num_lines; ++i)
00318 {
00319 int lastLine = 0;
00320 line = textLine(i);
00321 for (int j = 0; j < (int)line.length(); ++j)
00322 {
00323 if (lineOfChar(i, j) > lastLine)
00324 {
00325 lastLine = lineOfChar(i, j);
00326 temp += '\n';
00327 }
00328 temp += line[j];
00329 }
00330 if (i + 1 < num_lines) temp += '\n';
00331 }
00332
00333 return temp;
00334 }
00335
00336
00337 unsigned int KMEdit::lineBreakColumn() const
00338 {
00339 unsigned int lineBreakColumn = 0;
00340 unsigned int numlines = numLines();
00341 while ( numlines-- ) {
00342 lineBreakColumn = QMAX( lineBreakColumn, textLine( numlines ).length() );
00343 }
00344 return lineBreakColumn;
00345 }
00346
00347
00348 bool KMEdit::eventFilter(QObject*o, QEvent* e)
00349 {
00350 if (o == this)
00351 KCursor::autoHideEventFilter(o, e);
00352
00353 if (e->type() == QEvent::KeyPress)
00354 {
00355 QKeyEvent *k = (QKeyEvent*)e;
00356
00357 if (mUseExtEditor) {
00358 if (k->key() == Key_Up)
00359 {
00360 emit focusUp();
00361 return true;
00362 }
00363
00364
00365 if ( (k->key() == Key_Shift) || (k->key() == Key_Control) ||
00366 (k->key() == Key_Meta) || (k->key() == Key_Alt) )
00367 return true;
00368 if (mExtEditorTempFile) return true;
00369 QString sysLine = mExtEditor;
00370 mExtEditorTempFile = new KTempFile();
00371
00372 mExtEditorTempFile->setAutoDelete(true);
00373
00374 (*mExtEditorTempFile->textStream()) << text();
00375
00376 mExtEditorTempFile->close();
00377
00378 sysLine.replace( "%f", mExtEditorTempFile->name() );
00379 mExtEditorProcess = new KProcess();
00380 mExtEditorProcess->setUseShell( true );
00381 sysLine += " ";
00382 while (!sysLine.isEmpty())
00383 {
00384 *mExtEditorProcess << sysLine.left(sysLine.find(" ")).local8Bit();
00385 sysLine.remove(0, sysLine.find(" ") + 1);
00386 }
00387 connect(mExtEditorProcess, SIGNAL(processExited(KProcess*)),
00388 SLOT(slotExternalEditorDone(KProcess*)));
00389 if (!mExtEditorProcess->start())
00390 {
00391 KMessageBox::error( topLevelWidget(),
00392 i18n("Unable to start external editor.") );
00393 killExternalEditor();
00394 } else {
00395 mExtEditorTempFileWatcher = new KDirWatch( this, "mExtEditorTempFileWatcher" );
00396 connect( mExtEditorTempFileWatcher, SIGNAL(dirty(const QString&)),
00397 SLOT(slotExternalEditorTempFileChanged(const QString&)) );
00398 mExtEditorTempFileWatcher->addFile( mExtEditorTempFile->name() );
00399 }
00400 return true;
00401 } else {
00402
00403
00404 if (k->key() == Key_Up && k->state() != ShiftButton && currentLine() == 0
00405 && lineOfChar(0, currentColumn()) == 0)
00406 {
00407 deselect();
00408 emit focusUp();
00409 return true;
00410 }
00411
00412
00413 if (k->key() == Key_Backtab && k->state() == ShiftButton)
00414 {
00415 deselect();
00416 emit focusUp();
00417 return true;
00418 }
00419
00420 }
00421 } else if ( e->type() == QEvent::ContextMenu ) {
00422 QContextMenuEvent *event = (QContextMenuEvent*) e;
00423
00424 int para = 1, charPos, firstSpace, lastSpace;
00425
00426
00427 charPos = charAt( viewportToContents(event->pos()), ¶ );
00428 QString paraText = text( para );
00429
00430 if( !paraText.at(charPos).isSpace() )
00431 {
00432
00433 const QRegExp wordBoundary( "[\\s\\W]" );
00434 firstSpace = paraText.findRev( wordBoundary, charPos ) + 1;
00435 lastSpace = paraText.find( wordBoundary, charPos );
00436 if( lastSpace == -1 )
00437 lastSpace = paraText.length();
00438 QString word = paraText.mid( firstSpace, lastSpace - firstSpace );
00439
00440 if( !word.isEmpty() && mReplacements.contains( word ) )
00441 {
00442 KPopupMenu p;
00443 p.insertTitle( i18n("Suggestions") );
00444
00445
00446 QStringList reps = mReplacements[word];
00447 if( reps.count() > 0 )
00448 {
00449 int listPos = 0;
00450 for ( QStringList::Iterator it = reps.begin(); it != reps.end(); ++it ) {
00451 p.insertItem( *it, listPos );
00452 listPos++;
00453 }
00454 }
00455 else
00456 {
00457 p.insertItem( QString::fromLatin1("No Suggestions"), -2 );
00458 }
00459
00460
00461 int id = p.exec( mapToGlobal( event->pos() ) );
00462
00463 if( id > -1 )
00464 {
00465
00466 int parIdx = 1, txtIdx = 1;
00467 getCursorPosition(&parIdx, &txtIdx);
00468 setSelection(para, firstSpace, para, lastSpace);
00469 insert(mReplacements[word][id]);
00470
00471
00472 if ( para == parIdx && txtIdx >= lastSpace )
00473 txtIdx += mReplacements[word][id].length() - word.length();
00474 setCursorPosition(parIdx, txtIdx);
00475 }
00476
00477 return true;
00478 }
00479 }
00480 } else if ( e->type() == QEvent::FocusIn || e->type() == QEvent::FocusOut ) {
00481 QFocusEvent *fe = static_cast<QFocusEvent*>(e);
00482 if(! (fe->reason() == QFocusEvent::ActiveWindow || fe->reason() == QFocusEvent::Popup) )
00483 emit focusChanged( fe->gotFocus() );
00484 }
00485
00486 return KEdit::eventFilter(o, e);
00487 }
00488
00489
00490 int KMEdit::autoSpellChecking( bool on )
00491 {
00492 if ( textFormat() == Qt::RichText ) {
00493
00494 if ( on )
00495 KMessageBox::sorry(this, i18n("Automatic spellchecking is not possible on text with markup."));
00496 return -1;
00497 }
00498 if ( mSpellChecker ) {
00499
00500 mSpellChecker->setAutomatic( on );
00501 mSpellChecker->setActive( on );
00502 }
00503 return 1;
00504 }
00505
00506
00507 void KMEdit::slotExternalEditorTempFileChanged( const QString & fileName ) {
00508 if ( !mExtEditorTempFile )
00509 return;
00510 if ( fileName != mExtEditorTempFile->name() )
00511 return;
00512
00513 setAutoUpdate(false);
00514 clear();
00515
00516 insertLine(QString::fromLocal8Bit(KPIM::kFileToString( fileName, true, false )), -1);
00517 setAutoUpdate(true);
00518 repaint();
00519 }
00520
00521 void KMEdit::slotExternalEditorDone( KProcess * proc ) {
00522 assert(proc == mExtEditorProcess);
00523
00524 slotExternalEditorTempFileChanged( mExtEditorTempFile->name() );
00525 killExternalEditor();
00526 }
00527
00528 void KMEdit::killExternalEditor() {
00529 delete mExtEditorTempFileWatcher; mExtEditorTempFileWatcher = 0;
00530 delete mExtEditorTempFile; mExtEditorTempFile = 0;
00531 delete mExtEditorProcess; mExtEditorProcess = 0;
00532 }
00533
00534
00535 bool KMEdit::checkExternalEditorFinished() {
00536 if ( !mExtEditorProcess )
00537 return true;
00538 switch ( KMessageBox::warningYesNoCancel( topLevelWidget(),
00539 i18n("The external editor is still running.\n"
00540 "Abort the external editor or leave it open?"),
00541 i18n("External Editor"),
00542 i18n("Abort Editor"), i18n("Leave Editor Open") ) ) {
00543 case KMessageBox::Yes:
00544 killExternalEditor();
00545 return true;
00546 case KMessageBox::No:
00547 return true;
00548 default:
00549 return false;
00550 }
00551 }
00552
00553 void KMEdit::spellcheck()
00554 {
00555 if ( mKSpell )
00556 return;
00557 mWasModifiedBeforeSpellCheck = isModified();
00558 mSpellLineEdit = !mSpellLineEdit;
00559
00560
00561
00562
00563
00564
00565
00566 mKSpell = new KSpell(this, i18n("Spellcheck - KMail"), this,
00567 SLOT(slotSpellcheck2(KSpell*)));
00568
00569
00570 QStringList l = KSpellingHighlighter::personalWords();
00571 for ( QStringList::Iterator it = l.begin(); it != l.end(); ++it ) {
00572 mKSpell->addPersonal( *it );
00573 }
00574 connect (mKSpell, SIGNAL( death()),
00575 this, SLOT (slotSpellDone()));
00576 connect (mKSpell, SIGNAL (misspelling (const QString &, const QStringList &, unsigned int)),
00577 this, SLOT (slotMisspelling (const QString &, const QStringList &, unsigned int)));
00578 connect (mKSpell, SIGNAL (corrected (const QString &, const QString &, unsigned int)),
00579 this, SLOT (slotCorrected (const QString &, const QString &, unsigned int)));
00580 connect (mKSpell, SIGNAL (done(const QString &)),
00581 this, SLOT (slotSpellResult (const QString&)));
00582 }
00583
00584 void KMEdit::cut()
00585 {
00586 KEdit::cut();
00587 if ( textFormat() != Qt::RichText && mSpellChecker )
00588 mSpellChecker->restartBackgroundSpellCheck();
00589 }
00590
00591 void KMEdit::clear()
00592 {
00593 KEdit::clear();
00594 if ( textFormat() != Qt::RichText && mSpellChecker )
00595 mSpellChecker->restartBackgroundSpellCheck();
00596 }
00597
00598 void KMEdit::del()
00599 {
00600 KEdit::del();
00601 if ( textFormat() != Qt::RichText && mSpellChecker )
00602 mSpellChecker->restartBackgroundSpellCheck();
00603 }
00604
00605 void KMEdit::paste()
00606 {
00607 mComposer->paste( mPasteMode );
00608 }
00609
00610
00611
00612
00613
00614
00615 void KMEdit::contentsMouseReleaseEvent( QMouseEvent * e )
00616 {
00617 if( e->button() != Qt::MidButton )
00618 return KEdit::contentsMouseReleaseEvent( e );
00619 mPasteMode = QClipboard::Selection;
00620 KEdit::contentsMouseReleaseEvent( e );
00621 mPasteMode = QClipboard::Clipboard;
00622 }
00623
00624 void KMEdit::slotMisspelling(const QString &text, const QStringList &lst, unsigned int pos)
00625 {
00626 kdDebug(5006)<<"void KMEdit::slotMisspelling(const QString &text, const QStringList &lst, unsigned int pos) : "<<text <<endl;
00627 if( mSpellLineEdit )
00628 mComposer->sujectLineWidget()->spellCheckerMisspelling( text, lst, pos);
00629 else
00630 misspelling(text, lst, pos);
00631 }
00632
00633 void KMEdit::slotCorrected (const QString &oldWord, const QString &newWord, unsigned int pos)
00634 {
00635 kdDebug(5006)<<"slotCorrected (const QString &oldWord, const QString &newWord, unsigned int pos) : "<<oldWord<<endl;
00636 if( mSpellLineEdit )
00637 mComposer->sujectLineWidget()->spellCheckerCorrected( oldWord, newWord, pos);
00638 else {
00639 unsigned int l = 0;
00640 unsigned int cnt = 0;
00641 bool _bold,_underline,_italic;
00642 QColor _color;
00643 QFont _font;
00644 posToRowCol (pos, l, cnt);
00645 setCursorPosition(l, cnt+1);
00646 _bold = bold();
00647 _underline = underline();
00648 _italic = italic();
00649 _color = color();
00650 _font = currentFont();
00651 corrected(oldWord, newWord, pos);
00652 setSelection (l, cnt, l, cnt+newWord.length());
00653 setBold(_bold);
00654 setItalic(_italic);
00655 setUnderline(_underline);
00656 setColor(_color);
00657 setCurrentFont(_font);
00658 }
00659
00660 }
00661
00662 void KMEdit::slotSpellcheck2(KSpell*)
00663 {
00664 if( !mSpellLineEdit)
00665 {
00666 spellcheck_start();
00667
00668 QString quotePrefix;
00669 if(mComposer && mComposer->msg())
00670 {
00671 int languageNr = GlobalSettings::self()->replyCurrentLanguage();
00672 ReplyPhrases replyPhrases( QString::number(languageNr) );
00673 replyPhrases.readConfig();
00674
00675 quotePrefix = mComposer->msg()->formatString(
00676 replyPhrases.indentPrefix() );
00677 }
00678
00679 kdDebug(5006) << "spelling: new SpellingFilter with prefix=\"" << quotePrefix << "\"" << endl;
00680 QTextEdit plaintext;
00681 plaintext.setText(text());
00682 plaintext.setTextFormat(Qt::PlainText);
00683 mSpellingFilter = new SpellingFilter(plaintext.text(), quotePrefix, SpellingFilter::FilterUrls,
00684 SpellingFilter::FilterEmailAddresses);
00685
00686 mKSpell->check(mSpellingFilter->filteredText());
00687 }
00688 else if( mComposer )
00689 mKSpell->check( mComposer->sujectLineWidget()->text());
00690 }
00691
00692 void KMEdit::slotSpellResult(const QString &s)
00693 {
00694 if( !mSpellLineEdit)
00695 spellcheck_stop();
00696
00697 int dlgResult = mKSpell->dlgResult();
00698 if ( dlgResult == KS_CANCEL )
00699 {
00700 if( mSpellLineEdit)
00701 {
00702
00703 mSpellLineEdit = false;
00704 QString tmpText( s );
00705 tmpText = tmpText.remove('\n');
00706
00707 if( tmpText != mComposer->sujectLineWidget()->text() )
00708 mComposer->sujectLineWidget()->setText( tmpText );
00709 }
00710 else
00711 {
00712 setModified(true);
00713 }
00714 }
00715 mKSpell->cleanUp();
00716 KDictSpellingHighlighter::dictionaryChanged();
00717
00718 emit spellcheck_done( dlgResult );
00719 }
00720
00721 void KMEdit::slotSpellDone()
00722 {
00723 kdDebug(5006)<<" void KMEdit::slotSpellDone()\n";
00724 KSpell::spellStatus status = mKSpell->status();
00725 delete mKSpell;
00726 mKSpell = 0;
00727
00728 kdDebug(5006) << "spelling: delete SpellingFilter" << endl;
00729 delete mSpellingFilter;
00730 mSpellingFilter = 0;
00731 mComposer->sujectLineWidget()->deselect();
00732 if (status == KSpell::Error)
00733 {
00734 KMessageBox::sorry( topLevelWidget(),
00735 i18n("ISpell/Aspell could not be started. Please "
00736 "make sure you have ISpell or Aspell properly "
00737 "configured and in your PATH.") );
00738 emit spellcheck_done( KS_CANCEL );
00739 }
00740 else if (status == KSpell::Crashed)
00741 {
00742 spellcheck_stop();
00743 KMessageBox::sorry( topLevelWidget(),
00744 i18n("ISpell/Aspell seems to have crashed.") );
00745 emit spellcheck_done( KS_CANCEL );
00746 }
00747 else
00748 {
00749 if( mSpellLineEdit )
00750 spellcheck();
00751 else if( !mComposer->subjectTextWasSpellChecked() && status == KSpell::FinishedNoMisspellingsEncountered )
00752 KMessageBox::information( topLevelWidget(),
00753 i18n("No misspellings encountered.") );
00754 }
00755 }
00756
00757 void KMEdit::setCursorPositionFromStart( unsigned int pos ) {
00758 unsigned int l = 0;
00759 unsigned int c = 0;
00760 posToRowCol( pos, l, c );
00761
00762
00763 setCursorPosition( l, c );
00764 ensureCursorVisible();
00765 }
00766
00767 #include "kmedit.moc"