00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <qtimer.h>
00021 #include <qclipboard.h>
00022 #include "kotextview.h"
00023 #include "koparagcounter.h"
00024 #include "kotextobject.h"
00025 #include <klocale.h>
00026 #include <kstandarddirs.h>
00027 #include <kstdaccel.h>
00028 #include <kdebug.h>
00029 #include <kinstance.h>
00030 #include <kdatatool.h>
00031 #include <krun.h>
00032 #include <kmessagebox.h>
00033 #include <kovariable.h>
00034 #include <kcommand.h>
00035 #include "KoTextViewIface.h"
00036 #include <kostyle.h>
00037 #include <kbookmarkmanager.h>
00038 #include <kbookmark.h>
00039 #include <kurldrag.h>
00040
00041 class KoTextView::KoTextViewPrivate
00042 {
00043 public:
00044 KoTextViewPrivate()
00045 {
00046 m_currentUnicodeNumber = 0;
00047 }
00048
00049 void appendDigit( int digit ) { m_currentUnicodeNumber = 10 * m_currentUnicodeNumber + digit; }
00050 int currentUnicodeNumber() const { return m_currentUnicodeNumber; }
00051 void clearCurrentUnicodeNumber() { m_currentUnicodeNumber = 0; }
00052 private:
00053 int m_currentUnicodeNumber;
00054 };
00055
00056 KoTextView::KoTextView( KoTextObject *textobj )
00057 {
00058 d = new KoTextViewPrivate;
00059 m_bReadWrite = true;
00060 m_textobj = textobj;
00061 dcop=0;
00062 connect( m_textobj, SIGNAL( hideCursor() ), this, SLOT( hideCursor() ) );
00063 connect( m_textobj, SIGNAL( showCursor() ), this, SLOT( showCursor() ) );
00064 connect( m_textobj, SIGNAL( setCursor( KoTextCursor * ) ), this, SLOT( setCursor( KoTextCursor * ) ) );
00065 connect( m_textobj, SIGNAL( updateUI(bool, bool) ), this, SLOT( updateUI(bool, bool) ) );
00066 connect( m_textobj, SIGNAL( showCurrentFormat() ), this, SLOT( showCurrentFormat() ) );
00067 connect( m_textobj, SIGNAL( ensureCursorVisible() ), this, SLOT( ensureCursorVisible() ) );
00068
00069 m_cursor = new KoTextCursor( m_textobj->textDocument() );
00070
00071 m_cursorVisible = false;
00072
00073 showCursor();
00074 blinkTimer = new QTimer( this );
00075 connect( blinkTimer, SIGNAL( timeout() ),
00076 this, SLOT( blinkCursor() ) );
00077 blinkTimer->start( QApplication::cursorFlashTime() / 2 );
00078
00079 dragStartTimer = new QTimer( this );
00080 connect( dragStartTimer, SIGNAL( timeout() ),
00081 this, SLOT( startDrag() ) );
00082
00083 m_textobj->formatMore( 2 );
00084
00085 blinkCursorVisible = FALSE;
00086 inDoubleClick = FALSE;
00087 mightStartDrag = FALSE;
00088 possibleTripleClick = FALSE;
00089 afterTripleClick = FALSE;
00090 m_currentFormat = 0;
00091 variablePosition =-1;
00092
00093 }
00094
00095 KoTextView::~KoTextView()
00096 {
00097 delete m_cursor;
00098 delete d;
00099 delete dcop;
00100 delete blinkTimer;
00101 delete dragStartTimer;
00102 }
00103
00104 KoTextViewIface* KoTextView::dcopObject()
00105 {
00106 if ( !dcop )
00107 dcop = new KoTextViewIface( this );
00108
00109 return dcop;
00110 }
00111
00112 void KoTextView::terminate(bool removeselection)
00113 {
00114 textObject()->clearUndoRedoInfo();
00115 if ( removeselection && textDocument()->removeSelection( KoTextDocument::Standard ) )
00116 textObject()->selectionChangedNotify();
00117 hideCursor();
00118 }
00119
00120 void KoTextView::deleteWordRight()
00121 {
00122 if ( textObject()->hasSelection() ) {
00123 textObject()->removeSelectedText( m_cursor );
00124 return;
00125 }
00126 textDocument()->setSelectionStart( KoTextDocument::Standard, m_cursor );
00127
00128 do {
00129 m_cursor->gotoRight();
00130 } while ( !m_cursor->atParagEnd()
00131 && !m_cursor->parag()->at( m_cursor->index() )->c.isSpace() );
00132 textDocument()->setSelectionEnd( KoTextDocument::Standard, m_cursor );
00133 textObject()->removeSelectedText( m_cursor, KoTextDocument::Standard, i18n("Remove Word") );
00134 }
00135
00136 void KoTextView::deleteWordLeft()
00137 {
00138 if ( textObject()->hasSelection() ) {
00139 textObject()->removeSelectedText( m_cursor );
00140 return;
00141 }
00142 textDocument()->setSelectionStart( KoTextDocument::Standard, m_cursor );
00143
00144 do {
00145 m_cursor->gotoLeft();
00146 } while ( !m_cursor->atParagStart()
00147 && !m_cursor->parag()->at( m_cursor->index()-1 )->c.isSpace() );
00148 textDocument()->setSelectionEnd( KoTextDocument::Standard, m_cursor );
00149 textObject()->removeSelectedText( m_cursor, KoTextDocument::Standard, i18n("Remove Word") );
00150 }
00151
00152
00153 void KoTextView::handleKeyPressEvent( QKeyEvent * e )
00154 {
00155 textObject()->typingStarted();
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166 bool clearUndoRedoInfo = TRUE;
00167
00168 if ( KShortcut( KKey( e ) ) == KStdAccel::deleteWordBack() )
00169 {
00170 if ( m_cursor->parag()->string()->isRightToLeft() )
00171 deleteWordRight();
00172 else
00173 deleteWordLeft();
00174 clearUndoRedoInfo = TRUE;
00175 } else if ( KShortcut( KKey( e ) ) == KStdAccel::deleteWordForward() )
00176 {
00177 if ( m_cursor->parag()->string()->isRightToLeft() )
00178 deleteWordLeft();
00179 else
00180 deleteWordRight();
00181 clearUndoRedoInfo = TRUE;
00182 }
00183 else
00184 switch ( e->key() ) {
00185 case Key_Left:
00186 case Key_Right: {
00187
00188
00189 CursorAction a;
00190 if ( m_cursor->parag()->string()->isRightToLeft() == (e->key() == Key_Right) )
00191 a = e->state() & ControlButton ? MoveWordBackward : MoveBackward;
00192 else
00193 a = e->state() & ControlButton ? MoveWordForward : MoveForward;
00194 moveCursor( a, e->state() & ShiftButton );
00195 break;
00196 }
00197 case Key_Up:
00198 moveCursor( e->state() & ControlButton ? MoveParagUp : MoveUp, e->state() & ShiftButton );
00199 break;
00200 case Key_Down:
00201 moveCursor( e->state() & ControlButton ? MoveParagDown : MoveDown, e->state() & ShiftButton );
00202 break;
00203 case Key_Home:
00204 moveCursor( e->state() & ControlButton ? MoveHome : MoveLineStart, e->state() & ShiftButton );
00205 break;
00206 case Key_End:
00207 moveCursor( e->state() & ControlButton ? MoveEnd : MoveLineEnd, e->state() & ShiftButton );
00208 break;
00209 case Key_Prior:
00210 moveCursor( e->state() & ControlButton ? MovePgUp : MoveViewportUp, e->state() & ShiftButton );
00211 break;
00212 case Key_Next:
00213 moveCursor( e->state() & ControlButton ? MovePgDown : MoveViewportDown, e->state() & ShiftButton );
00214 break;
00215 case Key_Return: case Key_Enter:
00216 if ( (e->state() & (ShiftButton|ControlButton)) == 0 )
00217 {
00218 if ( textObject()->hasSelection() )
00219 textObject()->removeSelectedText( m_cursor );
00220 clearUndoRedoInfo = FALSE;
00221 textObject()->doKeyboardAction( m_cursor, m_currentFormat, KoTextObject::ActionReturn );
00222 Q_ASSERT( m_cursor->parag()->prev() );
00223 if ( m_cursor->parag()->prev() )
00224 doAutoFormat( m_cursor, m_cursor->parag()->prev(),
00225 m_cursor->parag()->prev()->length() - 1, '\n' );
00226 }
00227 break;
00228 case Key_Delete:
00229 if ( textObject()->hasSelection() ) {
00230 textObject()->removeSelectedText( m_cursor );
00231 break;
00232 }
00233
00234 textObject()->doKeyboardAction( m_cursor, m_currentFormat, KoTextObject::ActionDelete );
00235
00236 clearUndoRedoInfo = FALSE;
00237 break;
00238 case Key_Backspace:
00239 if ( textObject()->hasSelection() ) {
00240 textObject()->removeSelectedText( m_cursor );
00241 break;
00242 }
00243 if ( !m_cursor->parag()->prev() &&
00244 m_cursor->atParagStart() )
00245 {
00246 KoTextParag * parag = m_cursor->parag();
00247 if ( parag->counter() && parag->counter()->style() != KoParagCounter::STYLE_NONE)
00248 textObject()->doKeyboardAction( m_cursor, m_currentFormat, KoTextObject::ActionBackspace );
00249 break;
00250 }
00251 textObject()->doKeyboardAction( m_cursor, m_currentFormat, KoTextObject::ActionBackspace );
00252
00253 clearUndoRedoInfo = FALSE;
00254 break;
00255 case Key_F16:
00256 emit copy();
00257 break;
00258 case Key_F18:
00259 emit paste();
00260 break;
00261 case Key_F20:
00262 emit cut();
00263 break;
00264 case Key_Direction_L: {
00265 if ( !m_cursor->parag() || m_cursor->parag()->direction() == QChar::DirL )
00266 return;
00267 KCommand* cmd = textObject()->setParagDirectionCommand( m_cursor, QChar::DirL );
00268 textObject()->emitNewCommand( cmd );
00269 break;
00270 }
00271 case Key_Direction_R: {
00272 if ( !m_cursor->parag() || m_cursor->parag()->direction() == QChar::DirR )
00273 return;
00274 KCommand* cmd = textObject()->setParagDirectionCommand( m_cursor, QChar::DirR );
00275 textObject()->emitNewCommand( cmd );
00276 break;
00277 }
00278 default: {
00279
00280 if ( e->text().length() &&
00281
00282 ( !e->ascii() || e->ascii() >= 32 ) ||
00283 ( e->text() == "\t" && !( e->state() & ControlButton ) ) ) {
00284 clearUndoRedoInfo = FALSE;
00285 if ( e->key() == Key_Tab ) {
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295 }
00296
00297
00298
00299
00300
00301
00302
00303 QString text = e->text();
00304
00305
00306 if ( ( e->state() & AltButton ) && text[0].isDigit() )
00307 {
00308 while ( text[0].isDigit() ) {
00309 d->appendDigit( text[0].digitValue() );
00310 text.remove( 0, 1 );
00311 }
00312 }
00313
00314 if ( !text.isEmpty() )
00315 {
00316
00317 KoTextParag *p = m_cursor->parag();
00318 if ( p && p->string() && p->string()->isRightToLeft() ) {
00319 QChar *c = (QChar *)text.unicode();
00320 int l = text.length();
00321 while( l-- ) {
00322 if ( c->mirrored() )
00323 *c = c->mirroredChar();
00324 c++;
00325 }
00326 }
00327
00328 if( !doIgnoreDoubleSpace( p, m_cursor->index()-1, text[ text.length() - 1 ] ) )
00329 {
00330 insertText( text );
00331
00332 doAutoFormat( m_cursor, m_cursor->parag(), m_cursor->index() - 1, text[ text.length() - 1 ] );
00333 }
00334 }
00335 break;
00336 }
00337
00338
00339
00340 if ( e->state() & ControlButton ) {
00341 switch ( e->key() ) {
00342 case Key_F16:
00343 copy();
00344 break;
00345 case Key_A:
00346 moveCursor( MoveLineStart, e->state() & ShiftButton );
00347 break;
00348 case Key_E:
00349 moveCursor( MoveLineEnd, e->state() & ShiftButton );
00350 break;
00351 case Key_K:
00352 textObject()->doKeyboardAction( m_cursor, m_currentFormat, KoTextObject::ActionKill );
00353 break;
00354 case Key_Insert:
00355 copy();
00356 break;
00357 case Key_Space:
00358 insertNonbreakingSpace();
00359 break;
00360 }
00361 break;
00362 }
00363 }
00364 }
00365
00366 if ( clearUndoRedoInfo ) {
00367 textObject()->clearUndoRedoInfo();
00368 }
00369 textObject()->typingDone();
00370 }
00371
00372 void KoTextView::insertText( const QString &text )
00373 {
00374 textObject()->insert( m_cursor, m_currentFormat, text, false, true, i18n("Insert Text") );
00375 }
00376
00377 void KoTextView::newParagraph()
00378 {
00379 textObject()->insert( m_cursor, m_currentFormat, "\n", true, true, i18n("Insert Text") );
00380 }
00381
00382 void KoTextView::handleKeyReleaseEvent( QKeyEvent * e )
00383 {
00384 if ( e->key() == Key_Alt && d->currentUnicodeNumber() >= 32 )
00385 {
00386 QString text = QChar( d->currentUnicodeNumber() );
00387 d->clearCurrentUnicodeNumber();
00388 insertText( text );
00389 doAutoFormat( m_cursor, m_cursor->parag(),
00390 m_cursor->index() - 1, text[ text.length() - 1 ] );
00391 }
00392 }
00393
00394 void KoTextView::completion()
00395 {
00396 doCompletion(m_cursor, m_cursor->parag(),
00397 m_cursor->index() - 1);
00398 }
00399
00400 void KoTextView::moveCursor( CursorAction action, bool select )
00401 {
00402 hideCursor();
00403 bool cursorMoved = false;
00404 if ( select ) {
00405 if ( !textDocument()->hasSelection( KoTextDocument::Standard ) )
00406 textDocument()->setSelectionStart( KoTextDocument::Standard, m_cursor );
00407 cursorMoved = moveCursor( action );
00408 if ( textDocument()->setSelectionEnd( KoTextDocument::Standard, m_cursor ) ) {
00409 textObject()->selectionChangedNotify();
00410 }
00411 } else {
00412 bool redraw = textDocument()->removeSelection( KoTextDocument::Standard );
00413 cursorMoved = moveCursor( action );
00414 if ( redraw ) {
00415 textObject()->selectionChangedNotify();
00416 }
00417 }
00418
00419 if ( cursorMoved )
00420 {
00421 ensureCursorVisible();
00422
00423 }
00424 showCursor();
00425 }
00426
00427 bool KoTextView::moveCursor( CursorAction action )
00428 {
00429 bool cursorMoved = true;
00430 switch ( action ) {
00431 case MoveBackward:
00432 m_cursor->gotoPreviousLetter();
00433 break;
00434 case MoveWordBackward:
00435 m_cursor->gotoPreviousWord();
00436 break;
00437 case MoveForward:
00438 m_cursor->gotoNextLetter();
00439 break;
00440 case MoveWordForward:
00441 m_cursor->gotoNextWord();
00442 break;
00443 case MoveUp:
00444 m_cursor->gotoUp();
00445 break;
00446 case MoveDown:
00447 m_cursor->gotoDown();
00448 break;
00449 case MoveViewportUp:
00450 cursorMoved = pgUpKeyPressed();
00451 break;
00452 case MoveViewportDown:
00453 cursorMoved = pgDownKeyPressed();
00454 break;
00455 case MovePgUp:
00456 ctrlPgUpKeyPressed();
00457 break;
00458 case MovePgDown:
00459 ctrlPgDownKeyPressed();
00460 break;
00461 case MoveLineStart:
00462 m_cursor->gotoLineStart();
00463 break;
00464 case MoveHome:
00465 m_cursor->gotoHome();
00466 break;
00467 case MoveLineEnd:
00468 m_cursor->gotoLineEnd();
00469 break;
00470 case MoveEnd:
00471 textObject()->ensureFormatted( textDocument()->lastParag() );
00472 m_cursor->gotoEnd();
00473 break;
00474 case MoveParagUp: {
00475 KoTextParag * parag = m_cursor->parag()->prev();
00476 if ( parag )
00477 {
00478 m_cursor->setParag( parag );
00479 m_cursor->setIndex( 0 );
00480 }
00481 } break;
00482 case MoveParagDown: {
00483 KoTextParag * parag = m_cursor->parag()->next();
00484 if ( parag )
00485 {
00486 m_cursor->setParag( parag );
00487 m_cursor->setIndex( 0 );
00488 }
00489 } break;
00490 }
00491
00492 updateUI( true );
00493 return cursorMoved;
00494 }
00495
00496 KoTextCursor KoTextView::selectWordUnderCursor( const KoTextCursor& cursor, int selectionId )
00497 {
00498 KoTextCursor c1 = cursor;
00499 KoTextCursor c2 = cursor;
00500 if ( cursor.index() > 0 && !cursor.parag()->at( cursor.index()-1 )->c.isSpace() )
00501 c1.gotoWordLeft();
00502 if ( !cursor.parag()->at( cursor.index() )->c.isSpace() && !cursor.atParagEnd() )
00503 c2.gotoWordRight();
00504
00505
00506
00507
00508 KoTextString *s = cursor.parag()->string();
00509 bool beginFound = false;
00510 for ( int i = c1.index(); i< c2.index(); i++)
00511 {
00512 const QChar ch = s->at(i).c;
00513
00514
00515 const bool isWordDelimiter = ch.isSpace() || ch == '.' ||
00516 ch == ',' || ch == ':' || ch == ';';
00517
00518 if( !beginFound && !isWordDelimiter )
00519 {
00520 c1.setIndex(i);
00521 beginFound = true;
00522 }
00523 else if ( beginFound && isWordDelimiter )
00524 {
00525 c2.setIndex(i);
00526 break;
00527 }
00528 }
00529
00530 textDocument()->setSelectionStart( selectionId, &c1 );
00531 textDocument()->setSelectionEnd( selectionId, &c2 );
00532 return c2;
00533 }
00534
00535 KoTextCursor KoTextView::selectParagUnderCursor( const KoTextCursor& cursor, int selectionId, bool copyAndNotify )
00536 {
00537 KoTextCursor c1 = cursor;
00538 KoTextCursor c2 = cursor;
00539 c1.setIndex(0);
00540 c2.setIndex(c1.parag()->string()->length() - 1);
00541 textDocument()->setSelectionStart( selectionId, &c1 );
00542 textDocument()->setSelectionEnd( selectionId, &c2 );
00543 if ( copyAndNotify )
00544 {
00545 textObject()->selectionChangedNotify();
00546
00547 QApplication::clipboard()->setSelectionMode( true );
00548 emit copy();
00549 QApplication::clipboard()->setSelectionMode( false );
00550 }
00551 return c2;
00552 }
00553
00554 void KoTextView::extendParagraphSelection( const QPoint& iPoint )
00555 {
00556 hideCursor();
00557 KoTextCursor oldCursor = *m_cursor;
00558 placeCursor( iPoint );
00559
00560 bool redraw = FALSE;
00561 if ( textDocument()->hasSelection( KoTextDocument::Standard ) )
00562 {
00563 redraw = textDocument()->setSelectionEnd( KoTextDocument::Standard, m_cursor );
00564 if ( textDocument()->isSelectionSwapped( KoTextDocument::Standard ) )
00565 m_cursor->setIndex( 0 );
00566 else
00567 m_cursor->setIndex( m_cursor->parag()->string()->length() - 1 );
00568 textDocument()->setSelectionEnd( KoTextDocument::Standard, m_cursor );
00569 }
00570
00571
00572
00573 if ( redraw )
00574 textObject()->selectionChangedNotify( false );
00575
00576 showCursor();
00577 }
00578
00579 QString KoTextView::wordUnderCursor( const KoTextCursor& cursor )
00580 {
00581 selectWordUnderCursor( cursor, KoTextDocument::Temp );
00582 QString text = textObject()->selectedText( KoTextDocument::Temp );
00583 bool hasCustomItems = textObject()->selectionHasCustomItems( KoTextDocument::Temp );
00584 textDocument()->removeSelection( KoTextDocument::Temp );
00585 if( !hasCustomItems )
00586 return text;
00587 return QString::null;
00588 }
00589
00590 bool KoTextView::handleMousePressEvent( QMouseEvent *e, const QPoint &iPoint, bool canStartDrag, bool insertDirectCursor )
00591 {
00592 bool addParag = false;
00593 mightStartDrag = FALSE;
00594 hideCursor();
00595
00596 if (possibleTripleClick)
00597 {
00598 handleMouseTripleClickEvent( e, iPoint );
00599 return addParag;
00600 }
00601
00602 KoTextCursor oldCursor = *m_cursor;
00603 addParag = placeCursor( iPoint, insertDirectCursor&& isReadWrite() );
00604 ensureCursorVisible();
00605
00606 if ( e->button() != LeftButton )
00607 {
00608 showCursor();
00609 return addParag;
00610 }
00611
00612 KoTextDocument * textdoc = textDocument();
00613 if ( canStartDrag && textdoc->inSelection( KoTextDocument::Standard, iPoint ) ) {
00614 mightStartDrag = TRUE;
00615 m_textobj->emitShowCursor();
00616 dragStartTimer->start( QApplication::startDragTime(), TRUE );
00617 dragStartPos = e->pos();
00618 return addParag;
00619 }
00620
00621 bool redraw = FALSE;
00622 if ( textdoc->hasSelection( KoTextDocument::Standard ) ) {
00623 if ( !( e->state() & ShiftButton ) ) {
00624 redraw = textdoc->removeSelection( KoTextDocument::Standard );
00625 textdoc->setSelectionStart( KoTextDocument::Standard, m_cursor );
00626 } else {
00627 redraw = textdoc->setSelectionEnd( KoTextDocument::Standard, m_cursor ) || redraw;
00628 }
00629 } else {
00630 if ( !( e->state() & ShiftButton ) ) {
00631 textdoc->setSelectionStart( KoTextDocument::Standard, m_cursor );
00632 } else {
00633 textdoc->setSelectionStart( KoTextDocument::Standard, &oldCursor );
00634 redraw = textdoc->setSelectionEnd( KoTextDocument::Standard, m_cursor ) || redraw;
00635 }
00636 }
00637
00638
00639 if ( !redraw ) {
00640 showCursor();
00641 } else {
00642 textObject()->selectionChangedNotify();
00643 }
00644 return addParag;
00645 }
00646
00647 void KoTextView::handleMouseMoveEvent( QMouseEvent*, const QPoint& iPoint )
00648 {
00649 hideCursor();
00650 KoTextCursor oldCursor = *m_cursor;
00651 placeCursor( iPoint );
00652
00653
00654 if ( inDoubleClick ) {
00655 KoTextCursor cl = *m_cursor;
00656 cl.gotoWordLeft();
00657 KoTextCursor cr = *m_cursor;
00658 cr.gotoWordRight();
00659
00660 int diff = QABS( oldCursor.parag()->at( oldCursor.index() )->x - iPoint.x() );
00661 int ldiff = QABS( cl.parag()->at( cl.index() )->x - iPoint.x() );
00662 int rdiff = QABS( cr.parag()->at( cr.index() )->x - iPoint.x() );
00663
00664 if ( m_cursor->parag()->lineStartOfChar( m_cursor->index() ) !=
00665 oldCursor.parag()->lineStartOfChar( oldCursor.index() ) )
00666 diff = 0xFFFFFF;
00667
00668 if ( rdiff < diff && rdiff < ldiff )
00669 *m_cursor = cr;
00670 else if ( ldiff < diff && ldiff < rdiff )
00671 *m_cursor = cl;
00672 else
00673 *m_cursor = oldCursor;
00674 }
00675
00676 bool redraw = FALSE;
00677 if ( textDocument()->hasSelection( KoTextDocument::Standard ) )
00678 redraw = textDocument()->setSelectionEnd( KoTextDocument::Standard, m_cursor ) || redraw;
00679 else
00680 textDocument()->setSelectionStart( KoTextDocument::Standard, m_cursor );
00681
00682 if ( redraw )
00683 textObject()->selectionChangedNotify( false );
00684
00685 showCursor();
00686 }
00687
00688 void KoTextView::handleMouseReleaseEvent()
00689 {
00690 if ( dragStartTimer->isActive() )
00691 dragStartTimer->stop();
00692 if ( mightStartDrag ) {
00693 textObject()->selectAll( FALSE );
00694 mightStartDrag = false;
00695 }
00696 else
00697 {
00698 if ( textDocument()->selectionStartCursor( KoTextDocument::Standard ) == textDocument()->selectionEndCursor( KoTextDocument::Standard ) )
00699 {
00700 textDocument()->removeSelection( KoTextDocument::Standard );
00701 }
00702
00703 textObject()->selectionChangedNotify();
00704
00705
00706 QApplication::clipboard()->setSelectionMode( true );
00707 emit copy();
00708 QApplication::clipboard()->setSelectionMode( false );
00709 }
00710
00711 inDoubleClick = FALSE;
00712 m_textobj->emitShowCursor();
00713 }
00714
00715 void KoTextView::handleMouseDoubleClickEvent( QMouseEvent*ev, const QPoint& i )
00716 {
00717
00718
00719 if(afterTripleClick)
00720 {
00721 handleMousePressEvent( ev, i );
00722 return;
00723 }
00724
00725 inDoubleClick = TRUE;
00726 *m_cursor = selectWordUnderCursor( *m_cursor );
00727 textObject()->selectionChangedNotify();
00728
00729 QApplication::clipboard()->setSelectionMode( true );
00730 emit copy();
00731 QApplication::clipboard()->setSelectionMode( false );
00732
00733 possibleTripleClick=true;
00734
00735 QTimer::singleShot(QApplication::doubleClickInterval(),this,SLOT(tripleClickTimeout()));
00736 }
00737
00738 void KoTextView::tripleClickTimeout()
00739 {
00740 possibleTripleClick=false;
00741 }
00742
00743 void KoTextView::handleMouseTripleClickEvent( QMouseEvent*ev, const QPoint& )
00744 {
00745 if ( ev->button() != LeftButton)
00746 {
00747 showCursor();
00748 return;
00749 }
00750 afterTripleClick= true;
00751 inDoubleClick = FALSE;
00752 *m_cursor = selectParagUnderCursor( *m_cursor );
00753 QTimer::singleShot(QApplication::doubleClickInterval(),this,SLOT(afterTripleClickTimeout()));
00754 }
00755
00756 void KoTextView::afterTripleClickTimeout()
00757 {
00758 afterTripleClick=false;
00759 }
00760
00761 bool KoTextView::maybeStartDrag( QMouseEvent* e )
00762 {
00763 if ( mightStartDrag ) {
00764 dragStartTimer->stop();
00765 if ( ( e->pos() - dragStartPos ).manhattanLength() > QApplication::startDragDistance() )
00766 startDrag();
00767 return true;
00768 }
00769 return false;
00770 }
00771
00772 bool KoTextView::insertParagraph(const QPoint &pos)
00773 {
00774 KoTextParag *last = textDocument()->lastParag();
00775 KoTextFormat *f = 0;
00776 KoStyle *style = last->style();
00777 KoParagCounter *counter = last->counter();
00778 int diff = (pos.y()- textDocument()->height());
00779 f = last->at( last->length()-1 )->format();
00780 int height =f->height();
00781 int nbParag = (diff / height);
00782 QFontMetrics fm = f->refFontMetrics();
00783 for (int i = 0; i < nbParag ;i++)
00784 {
00785 KoTextParag *s=textDocument()->createParag( textDocument(), last );
00786 if ( f )
00787 s->setFormat( 0, 1, f, TRUE );
00788 if ( style )
00789 s->setStyle( style );
00790 s->setCounter( counter );
00791 last = s;
00792 }
00793 bool createParag = (nbParag > 0 );
00794 if ( createParag )
00795 {
00796 if ( pos.x() + f->width(' ') >= textDocument()->width())
00797 {
00798
00799
00800 last->setAlignment( Qt::AlignRight );
00801 }
00802 else
00803 {
00804 int nbSpace = pos.x()/f->width(' ');
00805 QString tmp;
00806 for (int i = 0; i< nbSpace; i++)
00807 {
00808 tmp+=' ';
00809 }
00810 last->insert( 0, tmp );
00811 }
00812 }
00813 return createParag;
00814
00815 }
00816
00817 bool KoTextView::placeCursor( const QPoint &pos, bool insertDirectCursor )
00818 {
00819 bool addParag = false;
00820 m_cursor->restoreState();
00821 if ( insertDirectCursor && (pos.y()>textDocument()->height()) )
00822 addParag = insertParagraph(pos);
00823 KoTextParag *s = 0L;
00824 if ( addParag )
00825 s = textDocument()->lastParag();
00826 else
00827 s = textDocument()->firstParag();
00828 m_cursor->place( pos, s, false, &variablePosition );
00829 updateUI( true );
00830 return addParag;
00831 }
00832
00833 void KoTextView::blinkCursor()
00834 {
00835
00836
00837 if ( !m_cursorVisible )
00838 return;
00839 bool cv = m_cursorVisible;
00840 blinkCursorVisible = !blinkCursorVisible;
00841 drawCursor( blinkCursorVisible );
00842 m_cursorVisible = cv;
00843 }
00844
00845 void KoTextView::drawCursor( bool visible )
00846 {
00847 m_cursorVisible = visible;
00848
00849 }
00850
00851 void KoTextView::focusInEvent()
00852 {
00853 blinkTimer->start( QApplication::cursorFlashTime() / 2 );
00854 showCursor();
00855 }
00856
00857 void KoTextView::focusOutEvent()
00858 {
00859 blinkTimer->stop();
00860 hideCursor();
00861 }
00862
00863
00864
00865
00866
00867
00868 KCommand* KoTextView::setFormatCommand( const KoTextFormat * newFormat, int flags, bool zoomFont)
00869 {
00870 return textObject()->setFormatCommand( m_cursor, &m_currentFormat, newFormat, flags, zoomFont );
00871 }
00872
00873 void KoTextView::dragStarted()
00874 {
00875 mightStartDrag = FALSE;
00876 inDoubleClick = FALSE;
00877 }
00878
00879 void KoTextView::applyStyle( const KoStyle * style )
00880 {
00881 if ( style )
00882 {
00883 textObject()->applyStyle( m_cursor, style );
00884 showCurrentFormat();
00885 }
00886 }
00887
00888 void KoTextView::updateUI( bool updateFormat, bool )
00889 {
00890
00891
00892 if ( updateFormat )
00893 {
00894 int i = cursor()->index();
00895 if ( i > 0 )
00896 --i;
00897 #ifdef DEBUG_FORMATS
00898 if ( currentFormat() )
00899 kdDebug(32500) << "KoTextView::updateUI old currentFormat=" << currentFormat()
00900 << " " << currentFormat()->key()
00901 << " parag format=" << cursor()->parag()->at( i )->format()->key() << endl;
00902 else
00903 kdDebug(32500) << "KoTextView::updateUI old currentFormat=0" << endl;
00904 #endif
00905 if ( !currentFormat() || currentFormat()->key() != cursor()->parag()->at( i )->format()->key() )
00906 {
00907 if ( currentFormat() )
00908 currentFormat()->removeRef();
00909 #ifdef DEBUG_FORMATS
00910 kdDebug(32500) << "Setting currentFormat from format " << cursor()->parag()->at( i )->format()
00911 << " ( character " << i << " in paragraph " << cursor()->parag()->paragId() << " )" << endl;
00912 #endif
00913 setCurrentFormat( textDocument()->formatCollection()->format( cursor()->parag()->at( i )->format() ) );
00914 if ( currentFormat()->isMisspelled() ) {
00915 KoTextFormat fNoMisspelled( *currentFormat() );
00916 fNoMisspelled.setMisspelled( false );
00917 currentFormat()->removeRef();
00918 setCurrentFormat( textDocument()->formatCollection()->format( &fNoMisspelled ) );
00919 }
00920 showCurrentFormat();
00921 }
00922 }
00923 }
00924
00925 void KoTextView::showCurrentFormat()
00926 {
00927
00928 KoTextFormat format = *currentFormat();
00929
00930 showFormat( &format );
00931 }
00932
00933 KCommand * KoTextView::setCounterCommand( const KoParagCounter & counter )
00934 {
00935 return textObject()->setCounterCommand( m_cursor, counter );
00936 }
00937 KCommand * KoTextView::setAlignCommand( int align )
00938 {
00939 return textObject()->setAlignCommand( m_cursor, align );
00940 }
00941 KCommand * KoTextView::setLineSpacingCommand( double spacing, KoParagLayout::SpacingType _type)
00942 {
00943 return textObject()->setLineSpacingCommand( m_cursor, spacing, _type);
00944 }
00945 KCommand * KoTextView::setBordersCommand( const KoBorder& leftBorder, const KoBorder& rightBorder, const KoBorder& bottomBorder, const KoBorder& topBorder )
00946 {
00947 return textObject()->setBordersCommand( m_cursor, leftBorder, rightBorder, bottomBorder, topBorder );
00948 }
00949 KCommand * KoTextView::setMarginCommand( QStyleSheetItem::Margin m, double margin )
00950 {
00951 return textObject()->setMarginCommand( m_cursor, m, margin );
00952 }
00953 KCommand * KoTextView::setTabListCommand( const KoTabulatorList & tabList )
00954 {
00955 return textObject()->setTabListCommand( m_cursor, tabList );
00956 }
00957
00958 KoTextDocument * KoTextView::textDocument() const
00959 {
00960 return textObject()->textDocument();
00961 }
00962
00963 KoVariable *KoTextView::variable()
00964 {
00965 if ( variablePosition > -1 )
00966 {
00967 KoTextStringChar * ch = m_cursor->parag()->at( variablePosition );
00968 ch = m_cursor->parag()->at( variablePosition );
00969 if(ch->isCustom())
00970 return dynamic_cast<KoVariable *>(ch->customItem());
00971 }
00972 return 0L;
00973 }
00974
00975 KoLinkVariable * KoTextView::linkVariable()
00976 {
00977 return dynamic_cast<KoLinkVariable *>(variable());
00978 }
00979
00980 QPtrList<KAction> KoTextView::dataToolActionList(KInstance * instance, const QString& word, bool & _singleWord )
00981 {
00982 m_singleWord = false;
00983 m_wordUnderCursor = QString::null;
00984 m_refLink= QString::null;
00985 KoLinkVariable* linkVar = linkVariable();
00986 if(linkVar)
00987 m_refLink = linkVar->url();
00988 QString text;
00989 if ( textObject()->hasSelection() )
00990 {
00991 text = textObject()->selectedText();
00992 if ( text.find(' ') == -1 && text.find('\t') == -1 && text.find(KoTextObject::customItemChar()) == -1 )
00993 {
00994 m_singleWord = true;
00995 }
00996 else
00997 {
00998 m_singleWord = false;
00999
01000 if( text.find(KoTextObject::customItemChar())!=-1)
01001 text = QString::null;
01002 }
01003 }
01004 else
01005 {
01006 if ( !word.isEmpty() )
01007 {
01008 m_singleWord = true;
01009 m_wordUnderCursor = word;
01010 text = word;
01011 }
01012 }
01013
01014 if ( text.isEmpty() || textObject()->protectContent())
01015 return QPtrList<KAction>();
01016
01017
01018 QValueList<KDataToolInfo> tools;
01019 tools +=KDataToolInfo::query( "QString", "text/plain", instance );
01020
01021
01022 if ( m_singleWord )
01023 {
01024 _singleWord = true;
01025 tools += KDataToolInfo::query( "QString", "application/x-singleword", instance );
01026 }
01027
01028 tools += KDataToolInfo::query( "KoTextString", "application/x-qrichtext", instance );
01029
01030 return KDataToolAction::dataToolActionList( tools, this, SLOT( slotToolActivated( const KDataToolInfo &, const QString & ) ) );
01031 }
01032
01033 QString KoTextView::underCursorWord()
01034 {
01035 QString text;
01036 if ( textObject()->hasSelection() )
01037 text = textObject()->selectedText();
01038 else
01039 text = m_wordUnderCursor;
01040 return text;
01041 }
01042
01043 void KoTextView::slotToolActivated( const KDataToolInfo & info, const QString & command )
01044 {
01045 KDataTool* tool = info.createTool( );
01046 if ( !tool )
01047 {
01048 kdWarning() << "Could not create Tool !" << endl;
01049 return;
01050 }
01051
01052 kdDebug(32500) << "KWTextFrameSetEdit::slotToolActivated command=" << command
01053 << " dataType=" << info.dataType() << endl;
01054
01055 QString text;
01056 if ( textObject()->hasSelection() )
01057 text = textObject()->selectedText();
01058 else
01059 text = m_wordUnderCursor;
01060
01061
01062 QString mimetype = "application/x-qrichtext";
01063 QString datatype = "KoTextString";
01064
01065 if ( !info.mimeTypes().contains( mimetype ) )
01066 {
01067 mimetype = "text/plain";
01068 datatype = "QString";
01069 }
01070
01071 if ( !info.mimeTypes().contains( mimetype ) && m_singleWord )
01072 mimetype = "application/x-singleword";
01073
01074 kdDebug(32500) << "Running tool with datatype=" << datatype << " mimetype=" << mimetype << endl;
01075
01076 QString origText = text;
01077 if ( tool->run( command, &text, datatype, mimetype) )
01078 {
01079 kdDebug(32500) << "Tool ran. Text is now " << text << endl;
01080 if ( origText != text )
01081 {
01082 if ( !textObject()->hasSelection() )
01083 {
01084
01085 selectWordUnderCursor( *m_cursor );
01086 }
01087
01088 textObject()->emitNewCommand( textObject()->replaceSelectionCommand(
01089 cursor(), text, KoTextDocument::Standard, i18n("Replace Word") ));
01090 }
01091 }
01092 delete tool;
01093 }
01094
01095 void KoTextView::openLink()
01096 {
01097 KURL url( m_refLink );
01098 if( url.isValid() )
01099 (void) new KRun( url );
01100 else
01101 KMessageBox::sorry(0L,i18n("%1 is not a valid link.").arg(m_refLink));
01102 }
01103
01104
01105 void KoTextView::insertSoftHyphen()
01106 {
01107 textObject()->insert( cursor(), currentFormat(), QChar(0xad) ,
01108 false , true, i18n("Insert Soft Hyphen") );
01109 }
01110
01111 void KoTextView::insertLineBreak()
01112 {
01113 textObject()->insert( cursor(), currentFormat(), QChar('\n'),
01114 false , true, i18n("Insert Line Break") );
01115 }
01116
01117 void KoTextView::insertNonbreakingSpace()
01118 {
01119 textObject()->insert( cursor(), currentFormat(), QChar(0xa0) ,
01120 false , true, i18n("Insert Non-Breaking Space") );
01121 }
01122
01123 void KoTextView::insertSpecialChar(QChar _c, const QString& font)
01124 {
01125 KoTextFormat * newFormat = new KoTextFormat(*currentFormat());
01126 newFormat->setFamily( font );
01127 if ( textObject()->hasSelection() )
01128 {
01129 KoTextFormat * lastFormat = currentFormat();
01130
01131 KCommand *cmd = textObject()->setFormatCommand( cursor(), &lastFormat, newFormat, KoTextFormat::Family );
01132
01133 KMacroCommand* macroCmd = new KMacroCommand( i18n("Insert Special Char") );
01134 macroCmd->addCommand( cmd );
01135 macroCmd->addCommand( textObject()->replaceSelectionCommand(
01136 cursor(), _c, KoTextDocument::Standard, QString::null) );
01137 textObject()->emitNewCommand( macroCmd );
01138 }
01139 else
01140 {
01141 textObject()->insert( cursor(), newFormat, _c, false, true, i18n("Insert Special Char"));
01142 delete newFormat;
01143 }
01144 }
01145
01146 const KoParagLayout * KoTextView::currentParagLayoutFormat() const
01147 {
01148 KoTextParag * parag = m_cursor->parag();
01149 return &(parag->paragLayout());
01150 }
01151
01152 bool KoTextView::rtl() const
01153 {
01154 return m_cursor->parag()->string()->isRightToLeft();
01155 }
01156
01157
01158 KCommand* KoTextView::setParagLayoutFormatCommand( KoParagLayout *newLayout,int flags,int marginIndex)
01159 {
01160 #if 0
01161 KCommand *cmd =0L;
01162 KoParagCounter c;
01163 if(newLayout->counter)
01164 c=*newLayout->counter;
01165 switch(flags)
01166 {
01167 case KoParagLayout::Alignment:
01168 {
01169 cmd = textObject()->setAlignCommand( m_cursor, newLayout->alignment );
01170 break;
01171 }
01172 case KoParagLayout::Tabulator:
01173 cmd= textObject()->setTabListCommand( m_cursor, newLayout->tabList() );
01174 break;
01175 case KoParagLayout::Margins:
01176 cmd= textObject()->setMarginCommand(m_cursor,(QStyleSheetItem::Margin)marginIndex, newLayout->margins[marginIndex] );
01177 break;
01178 case KoParagLayout::BulletNumber:
01179 cmd= textObject()->setCounterCommand( m_cursor, c );
01180 break;
01181 default:
01182 break;
01183 }
01184 if (cmd)
01185 textObject()->emitNewCommand( cmd );
01186 #endif
01187 return textObject()->setParagLayoutFormatCommand( m_cursor, KoTextDocument::Standard, newLayout, flags, marginIndex );
01188 }
01189
01190 KCommand *KoTextView::setChangeCaseOfTextCommand(KoChangeCaseDia::TypeOfCase _type)
01191 {
01192 QString text;
01193 if ( textObject()->hasSelection() )
01194 text = textObject()->selectedText();
01195 if(!text.isEmpty())
01196 return textObject()->changeCaseOfText(cursor(), _type);
01197 else
01198 return 0L;
01199 }
01200
01201 KCommand *KoTextView::dropEvent( KoTextObject *tmp, KoTextCursor dropCursor, bool dropInSameObj)
01202 {
01203 KMacroCommand *macroCmd=new KMacroCommand(i18n("Paste Text"));
01204 if ( tmp->hasSelection() )
01205 {
01206
01207 KoTextCursor startSel = textDocument()->selectionStartCursor( KoTextDocument::Standard );
01208 KoTextCursor endSel = textDocument()->selectionEndCursor( KoTextDocument::Standard );
01209 bool inSelection = false;
01210 if ( startSel.parag() == endSel.parag() )
01211 inSelection = dropInSameObj
01212 && ( dropCursor.parag() == startSel.parag() )
01213 && dropCursor.index() >= startSel.index()
01214 && dropCursor.index() <= endSel.index();
01215 else
01216 {
01217
01218 inSelection = dropInSameObj && dropCursor.parag() == startSel.parag() && dropCursor.index() >= startSel.index();
01219 if ( !inSelection )
01220 {
01221
01222 KoTextParag *p = startSel.parag()->next();
01223 while ( !inSelection && p && p != endSel.parag() )
01224 {
01225 inSelection = ( p == dropCursor.parag() );
01226 p = p->next();
01227 }
01228
01229 if ( !inSelection )
01230 inSelection = dropCursor.parag() == endSel.parag() && dropCursor.index() <= endSel.index();
01231 }
01232 }
01233 if ( inSelection || m_textobj->protectContent() )
01234 {
01235 delete macroCmd;
01236 tmp->textDocument()->removeSelection( KoTextDocument::Standard );
01237 tmp->selectionChangedNotify();
01238 hideCursor();
01239 *cursor() = dropCursor;
01240 showCursor();
01241 ensureCursorVisible();
01242 return 0L;
01243 }
01244 if ( tmp->protectContent())
01245 {
01246 tmp->textDocument()->removeSelection( KoTextDocument::Standard );
01247 tmp->selectionChangedNotify();
01248 }
01249
01250
01251
01252 if ( endSel.parag() == dropCursor.parag() )
01253 {
01254
01255 if ( startSel.parag() != dropCursor.parag() || startSel.index() < dropCursor.index() )
01256 {
01257
01258
01259
01260 int dropIndex = dropCursor.index();
01261 dropCursor.setParag( startSel.parag() );
01262
01263 dropCursor.setIndex( dropIndex - QMIN( endSel.index(), dropIndex ) + startSel.index() );
01264 }
01265 kdDebug(32500) << "dropCursor: parag=" << dropCursor.parag()->paragId() << " index=" << dropCursor.index() << endl;
01266 }
01267 macroCmd->addCommand(tmp->removeSelectedTextCommand( cursor(), KoTextDocument::Standard ));
01268 }
01269 hideCursor();
01270 *cursor() = dropCursor;
01271 showCursor();
01272 kdDebug(32500) << "cursor set back to drop cursor: parag=" << cursor()->parag()->paragId() << " index=" << cursor()->index() << endl;
01273
01274 return macroCmd;
01275 }
01276
01277
01278 void KoTextView::copyTextOfComment()
01279 {
01280 KoTextStringChar * ch = m_cursor->parag()->at( variablePosition );
01281 if(ch->isCustom())
01282 {
01283 KoNoteVariable *var=dynamic_cast<KoNoteVariable *>(ch->customItem());
01284 if( var )
01285 {
01286 KURL::List lst;
01287 lst.append( var->note() );
01288 QApplication::clipboard()->setSelectionMode(true);
01289 QApplication::clipboard()->setData( new KURLDrag(lst, 0, 0) );
01290 QApplication::clipboard()->setSelectionMode(false);
01291 QApplication::clipboard()->setData( new KURLDrag(lst, 0, 0) );
01292 }
01293 }
01294 }
01295
01296 void KoTextView::removeComment()
01297 {
01298 KoTextStringChar * ch = m_cursor->parag()->at( variablePosition );
01299 if(ch->isCustom())
01300 {
01301 KoNoteVariable *var=dynamic_cast<KoNoteVariable *>(ch->customItem());
01302 if( var )
01303 {
01304 if( variablePosition == m_cursor->index() )
01305 m_cursor->setIndex( m_cursor->index() );
01306 else
01307 m_cursor->setIndex( m_cursor->index() -1 );
01308
01309 textDocument()->setSelectionStart( KoTextDocument::Temp, m_cursor );
01310
01311 if( variablePosition == m_cursor->index() )
01312 m_cursor->setIndex( m_cursor->index() +1);
01313 else
01314 m_cursor->setIndex( m_cursor->index() );
01315
01316 textDocument()->setSelectionEnd( KoTextDocument::Temp, m_cursor );
01317
01318 textObject()->removeSelectedText( m_cursor, KoTextDocument::Temp, i18n("Remove Comment") );
01319 }
01320 }
01321 }
01322
01323 KoStyle * KoTextView::createStyleFromSelection(const QString & name)
01324 {
01325 KoTextCursor cursor = *m_cursor;
01326 if ( textDocument()->hasSelection( KoTextDocument::Standard ) )
01327 cursor = textDocument()->selectionStartCursor( KoTextDocument::Standard );
01328 KoStyle * style = new KoStyle (name);
01329 KoParagLayout layout(cursor.parag()->paragLayout());
01330 layout.style = style;
01331 style->setFollowingStyle( style );
01332 style->format() = *(cursor.parag()->at(cursor.index())->format());
01333
01334 style->paragLayout() = layout;
01335
01336 cursor.parag()->setParagLayout( style->paragLayout() );
01337 return style;
01338 }
01339
01340 void KoTextView::updateStyleFromSelection( KoStyle* style )
01341 {
01342 KoTextCursor cursor = *m_cursor;
01343 if ( textDocument()->hasSelection( KoTextDocument::Standard ) )
01344 cursor = textDocument()->selectionStartCursor( KoTextDocument::Standard );
01345
01346 style->paragLayout() = cursor.parag()->paragLayout();
01347 style->paragLayout().style = style;
01348 style->format() = *(cursor.parag()->at(cursor.index())->format());
01349 }
01350
01351 void KoTextView::addBookmarks(const QString &url)
01352 {
01353 QString filename = locateLocal( "data", QString::fromLatin1("konqueror/bookmarks.xml") );
01354 KBookmarkManager *bookManager = KBookmarkManager::managerForFile( filename,false );
01355 KBookmarkGroup group = bookManager->root();
01356 group.addBookmark( bookManager, url, KURL( url));
01357 bookManager->save();
01358
01359 }
01360
01361 void KoTextView::copyLink()
01362 {
01363 KoLinkVariable * var=linkVariable();
01364 if(var)
01365 {
01366 KURL::List lst;
01367 lst.append( var->url() );
01368 QApplication::clipboard()->setSelectionMode(true);
01369 QApplication::clipboard()->setData( new KURLDrag(lst, 0, 0) );
01370 QApplication::clipboard()->setSelectionMode(false);
01371 QApplication::clipboard()->setData( new KURLDrag(lst, 0, 0) );
01372 }
01373 }
01374
01375 void KoTextView::removeLink()
01376 {
01377 KoLinkVariable * var=linkVariable();
01378 if(var)
01379 {
01380 KoTextCursor c1 = *m_cursor;
01381 KoTextCursor c2 = *m_cursor;
01382 c1.setIndex(var->index());
01383 c2.setIndex(var->index()+1);
01384 textDocument()->setSelectionStart( KoTextDocument::Temp, &c1 );
01385 textDocument()->setSelectionEnd( KoTextDocument::Temp, &c2 );
01386 KCommand *cmd=textObject()->replaceSelectionCommand( &c1, var->value(),
01387 KoTextDocument::Temp, i18n("Remove Link") );
01388 if ( cmd )
01389 textObject()->emitNewCommand( cmd );
01390 }
01391 }
01392
01393
01394 #include "kotextview.moc"