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