00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "KoTextObject.h"
00022 #include "KoTextParag.h"
00023 #include "KoParagCounter.h"
00024 #include "KoTextZoomHandler.h"
00025 #include "KoTextCommand.h"
00026 #include "KoStyleCollection.h"
00027 #include "KoFontDia.h"
00028 #include "KoOasisContext.h"
00029 #include "KoVariable.h"
00030 #include "KoAutoFormat.h"
00031 #include <KoXmlNS.h>
00032 #include <KoDom.h>
00033
00034 #include <klocale.h>
00035 #include <kdebug.h>
00036 #include <kapplication.h>
00037
00038 #include <qtimer.h>
00039 #include <qregexp.h>
00040 #include <qprogressdialog.h>
00041
00042 #include <assert.h>
00043
00044
00045
00046
00047 const char KoTextObject::s_customItemChar = '#';
00048
00049 struct KoTextObject::KoTextObjectPrivate
00050 {
00051 public:
00052 KoTextObjectPrivate() {
00053 afterFormattingEmitted = false;
00054 abortFormatting = false;
00055 }
00056 bool afterFormattingEmitted;
00057 bool abortFormatting;
00058 };
00059
00060 KoTextObject::KoTextObject( KoTextZoomHandler *zh, const QFont& defaultFont,
00061 const QString &defaultLanguage, bool hyphenation,
00062 KoParagStyle* defaultStyle, int tabStopWidth,
00063 QObject* parent, const char *name )
00064 : QObject( parent, name ), m_defaultStyle( defaultStyle ), undoRedoInfo( this )
00065 {
00066 textdoc = new KoTextDocument( zh, new KoTextFormatCollection( defaultFont, QColor(),defaultLanguage, hyphenation ) );
00067 if ( tabStopWidth != -1 )
00068 textdoc->setTabStops( tabStopWidth );
00069 init();
00070 }
00071
00072 KoTextObject::KoTextObject( KoTextDocument* _textdoc, KoParagStyle* defaultStyle,
00073 QObject* parent, const char *name )
00074 : QObject( parent, name ), m_defaultStyle( defaultStyle ), undoRedoInfo( this )
00075 {
00076 textdoc = _textdoc;
00077 init();
00078 }
00079
00080 void KoTextObject::init()
00081 {
00082 d = new KoTextObjectPrivate;
00083 m_needsSpellCheck = true;
00084 m_protectContent = false;
00085 m_visible=true;
00086 m_availableHeight = -1;
00087 m_lastFormatted = textdoc->firstParag();
00088 m_highlightSelectionAdded = false;
00089 interval = 0;
00090 changeIntervalTimer = new QTimer( this );
00091 connect( changeIntervalTimer, SIGNAL( timeout() ),
00092 this, SLOT( doChangeInterval() ) );
00093
00094 formatTimer = new QTimer( this );
00095 connect( formatTimer, SIGNAL( timeout() ),
00096 this, SLOT( formatMore() ) );
00097
00098
00099 if ( m_lastFormatted && m_defaultStyle )
00100 m_lastFormatted->applyStyle( m_defaultStyle );
00101
00102 connect( textdoc, SIGNAL( paragraphDeleted( KoTextParag* ) ),
00103 this, SIGNAL( paragraphDeleted( KoTextParag* ) ) );
00104 connect( textdoc, SIGNAL( paragraphDeleted( KoTextParag* ) ),
00105 this, SLOT( slotParagraphDeleted( KoTextParag* ) ) );
00106 connect( textdoc, SIGNAL( newCommand( KCommand* ) ),
00107 this, SIGNAL( newCommand( KCommand* ) ) );
00108 connect( textdoc, SIGNAL( repaintChanged() ),
00109 this, SLOT( emitRepaintChanged() ) );
00110
00111 connect( this, SIGNAL(paragraphModified( KoTextParag*, int, int , int ) ),
00112 this, SLOT(slotParagraphModified(KoTextParag *, int, int , int)));
00113 connect( this, SIGNAL(paragraphCreated( KoTextParag* )),
00114 this, SLOT(slotParagraphCreated(KoTextParag *)));
00115 }
00116
00117 KoTextObject::~KoTextObject()
00118 {
00119
00120
00121 undoRedoInfo.clear();
00122 delete textdoc; textdoc = 0;
00123 delete d;
00124 }
00125
00126 int KoTextObject::availableHeight() const
00127 {
00128 if ( m_availableHeight == -1 )
00129 emit const_cast<KoTextObject *>(this)->availableHeightNeeded();
00130 Q_ASSERT( m_availableHeight != -1 );
00131 return m_availableHeight;
00132 }
00133
00134 void KoTextObject::slotParagraphModified(KoTextParag * , int _type, int , int)
00135 {
00136 if ( _type == ChangeFormat)
00137 return;
00138 m_needsSpellCheck = true;
00139 }
00140
00141 void KoTextObject::slotParagraphCreated(KoTextParag * )
00142 {
00143 m_needsSpellCheck = true;
00144 }
00145
00146 void KoTextObject::slotParagraphDeleted(KoTextParag * parag)
00147 {
00148 if ( m_lastFormatted == parag )
00149 m_lastFormatted = parag->next();
00150
00151
00152
00153 }
00154
00155 int KoTextObject::docFontSize( KoTextFormat * format ) const
00156 {
00157 Q_ASSERT( format );
00158 return format->pointSize();
00159 }
00160
00161 int KoTextObject::zoomedFontSize( int docFontSize ) const
00162 {
00163 kdDebug(32500) << "KoTextObject::zoomedFontSize: docFontSize=" << docFontSize
00164 << " - in LU: " << KoTextZoomHandler::ptToLayoutUnitPt( docFontSize ) << endl;
00165 return KoTextZoomHandler::ptToLayoutUnitPt( docFontSize );
00166 }
00167
00168
00169 class KoHasCustomItemVisitor : public KoParagVisitor
00170 {
00171 public:
00172 KoHasCustomItemVisitor() : KoParagVisitor() { }
00173
00174 virtual bool visit( KoTextParag *parag, int start, int end )
00175 {
00176 for ( int i = start ; i < end ; ++i )
00177 {
00178 KoTextStringChar * ch = parag->at( i );
00179 if ( ch->isCustom() )
00180 return false;
00181 }
00182 return true;
00183 }
00184 };
00185
00186 bool KoTextObject::selectionHasCustomItems( KoTextDocument::SelectionId selectionId ) const
00187 {
00188 KoHasCustomItemVisitor visitor;
00189 bool noneFound = textdoc->visitSelection( selectionId, &visitor );
00190 return !noneFound;
00191 }
00192
00193 void KoTextObject::slotAfterUndoRedo()
00194 {
00195 formatMore( 2 );
00196 emit repaintChanged( this );
00197 emit updateUI( true );
00198 emit showCursor();
00199 emit ensureCursorVisible();
00200 }
00201
00202 void KoTextObject::clearUndoRedoInfo()
00203 {
00204 undoRedoInfo.clear();
00205 }
00206
00207
00208 void KoTextObject::checkUndoRedoInfo( KoTextCursor * cursor, UndoRedoInfo::Type t )
00209 {
00210 if ( undoRedoInfo.valid() && ( t != undoRedoInfo.type || cursor != undoRedoInfo.cursor ) ) {
00211 undoRedoInfo.clear();
00212 }
00213 undoRedoInfo.type = t;
00214 undoRedoInfo.cursor = cursor;
00215 }
00216
00217 void KoTextObject::undo()
00218 {
00219 undoRedoInfo.clear();
00220 emit hideCursor();
00221 KoTextCursor *cursor = new KoTextCursor( textdoc );
00222 KoTextCursor *c = textdoc->undo( cursor );
00223 if ( !c ) {
00224 delete cursor;
00225 emit showCursor();
00226 return;
00227 }
00228
00229
00230
00231 emit setCursor( c );
00232 setLastFormattedParag( textdoc->firstParag() );
00233 delete cursor;
00234 QTimer::singleShot( 0, this, SLOT( slotAfterUndoRedo() ) );
00235 }
00236
00237 void KoTextObject::redo()
00238 {
00239 undoRedoInfo.clear();
00240 emit hideCursor();
00241 KoTextCursor *cursor = new KoTextCursor( textdoc );
00242 KoTextCursor *c = textdoc->redo( cursor );
00243 if ( !c ) {
00244 delete cursor;
00245 emit showCursor();
00246 return;
00247 }
00248 emit setCursor( c );
00249 setLastFormattedParag( textdoc->firstParag() );
00250 delete cursor;
00251 QTimer::singleShot( 0, this, SLOT( slotAfterUndoRedo() ) );
00252 }
00253
00254 KoTextObject::UndoRedoInfo::UndoRedoInfo( KoTextObject *to )
00255 : type( Invalid ), textobj(to), cursor( 0 )
00256 {
00257 text = QString::null;
00258 id = -1;
00259 index = -1;
00260 placeHolderCmd = 0L;
00261 }
00262
00263 bool KoTextObject::UndoRedoInfo::valid() const
00264 {
00265 return text.length() > 0 && id >= 0 && index >= 0;
00266 }
00267
00268 void KoTextObject::UndoRedoInfo::clear()
00269 {
00270 if ( valid() ) {
00271 KoTextDocument* textdoc = textobj->textDocument();
00272 switch (type) {
00273 case Insert:
00274 case Return:
00275 {
00276 KoTextDocCommand * cmd = new KoTextInsertCommand( textdoc, id, index, text.rawData(), customItemsMap, oldParagLayouts );
00277 textdoc->addCommand( cmd );
00278 Q_ASSERT( placeHolderCmd );
00279
00280 if ( !customItemsMap.isEmpty() )
00281 {
00282 CustomItemsMap::Iterator it = customItemsMap.begin();
00283 for ( ; it != customItemsMap.end(); ++it )
00284 {
00285 KoTextCustomItem * item = it.data();
00286 KCommand * itemCmd = item->createCommand();
00287 if ( itemCmd )
00288 placeHolderCmd->addCommand( itemCmd );
00289 }
00290 placeHolderCmd->addCommand( new KoTextCommand( textobj, QString::null ) );
00291 }
00292 else
00293 {
00294 placeHolderCmd->addCommand( new KoTextCommand( textobj, QString::null ) );
00295 }
00296 } break;
00297 case Delete:
00298 case RemoveSelected:
00299 {
00300 KoTextDocCommand * cmd = textobj->deleteTextCommand( textdoc, id, index, text.rawData(), customItemsMap, oldParagLayouts );
00301 textdoc->addCommand( cmd );
00302 Q_ASSERT( placeHolderCmd );
00303 placeHolderCmd->addCommand( new KoTextCommand( textobj, QString::null ) );
00304
00305 if ( !customItemsMap.isEmpty() )
00306 {
00307 customItemsMap.deleteAll( placeHolderCmd );
00308 }
00309 } break;
00310 case Invalid:
00311 break;
00312 }
00313 }
00314 type = Invalid;
00315
00316
00317 text = QString::null;
00318 id = -1;
00319 index = -1;
00320 oldParagLayouts.clear();
00321 customItemsMap.clear();
00322 placeHolderCmd = 0L;
00323 }
00324
00325 void KoTextObject::copyCharFormatting( KoTextParag *parag, int position, int index , bool moveCustomItems )
00326 {
00327 KoTextStringChar * ch = parag->at( position );
00328 if ( ch->format() ) {
00329 ch->format()->addRef();
00330 undoRedoInfo.text.at( index ).setFormat( ch->format() );
00331 }
00332 if ( ch->isCustom() )
00333 {
00334 kdDebug(32500) << "KoTextObject::copyCharFormatting moving custom item " << ch->customItem() << " to text's " << index << " char" << endl;
00335 undoRedoInfo.customItemsMap.insert( index, ch->customItem() );
00336
00337
00338 if ( moveCustomItems )
00339 parag->removeCustomItem(position);
00340
00341 }
00342 }
00343
00344
00345 void KoTextObject::readFormats( KoTextCursor &c1, KoTextCursor &c2, bool copyParagLayouts, bool moveCustomItems )
00346 {
00347
00348 int oldLen = undoRedoInfo.text.length();
00349 if ( c1.parag() == c2.parag() ) {
00350 undoRedoInfo.text += c1.parag()->string()->toString().mid( c1.index(), c2.index() - c1.index() );
00351 for ( int i = c1.index(); i < c2.index(); ++i )
00352 copyCharFormatting( c1.parag(), i, oldLen + i - c1.index(), moveCustomItems );
00353 } else {
00354 int lastIndex = oldLen;
00355 int i;
00356
00357
00358 undoRedoInfo.text += c1.parag()->string()->toString().mid( c1.index(), c1.parag()->length() - 1 - c1.index() ) + '\n';
00359 for ( i = c1.index(); i < c1.parag()->length(); ++i, ++lastIndex )
00360 copyCharFormatting( c1.parag(), i, lastIndex, moveCustomItems );
00361
00362 KoTextParag *p = c1.parag()->next();
00363 while ( p && p != c2.parag() ) {
00364 undoRedoInfo.text += p->string()->toString().left( p->length() - 1 ) + '\n';
00365
00366 for ( i = 0; i < p->length(); ++i )
00367 copyCharFormatting( p, i, i + lastIndex, moveCustomItems );
00368 lastIndex += p->length();
00369
00370 p = p->next();
00371 }
00372
00373 undoRedoInfo.text += c2.parag()->string()->toString().left( c2.index() );
00374 for ( i = 0; i < c2.index(); ++i )
00375 copyCharFormatting( c2.parag(), i, i + lastIndex, moveCustomItems );
00376 }
00377
00378 if ( copyParagLayouts ) {
00379 KoTextParag *p = c1.parag();
00380 while ( p ) {
00381 undoRedoInfo.oldParagLayouts << p->paragLayout();
00382 if ( p == c2.parag() )
00383 break;
00384 p = p->next();
00385 }
00386 }
00387 }
00388
00389 void KoTextObject::newPlaceHolderCommand( const QString & name )
00390 {
00391 Q_ASSERT( !undoRedoInfo.placeHolderCmd );
00392 if ( undoRedoInfo.placeHolderCmd ) kdDebug(32500) << kdBacktrace();
00393 undoRedoInfo.placeHolderCmd = new KMacroCommand( name );
00394 emit newCommand( undoRedoInfo.placeHolderCmd );
00395 }
00396
00397 void KoTextObject::storeParagUndoRedoInfo( KoTextCursor * cursor, KoTextDocument::SelectionId selectionId )
00398 {
00399 undoRedoInfo.clear();
00400 undoRedoInfo.oldParagLayouts.clear();
00401 undoRedoInfo.text = " ";
00402 undoRedoInfo.index = 1;
00403 if ( cursor && !textdoc->hasSelection( selectionId, true ) ) {
00404 KoTextParag * p = cursor->parag();
00405 undoRedoInfo.id = p->paragId();
00406 undoRedoInfo.eid = p->paragId();
00407 undoRedoInfo.oldParagLayouts << p->paragLayout();
00408 }
00409 else{
00410 Q_ASSERT( textdoc->hasSelection( selectionId, true ) );
00411 KoTextParag *start = textdoc->selectionStart( selectionId );
00412 KoTextParag *end = textdoc->selectionEnd( selectionId );
00413 undoRedoInfo.id = start->paragId();
00414 undoRedoInfo.eid = end->paragId();
00415 for ( ; start && start != end->next() ; start = start->next() )
00416 {
00417 undoRedoInfo.oldParagLayouts << start->paragLayout();
00418
00419 }
00420 }
00421 }
00422
00423 void KoTextObject::doKeyboardAction( KoTextCursor * cursor, KoTextFormat * & , KeyboardAction action )
00424 {
00425 KoTextParag * parag = cursor->parag();
00426 setLastFormattedParag( parag );
00427 emit hideCursor();
00428 bool doUpdateCurrentFormat = true;
00429 switch ( action ) {
00430 case ActionDelete: {
00431 checkUndoRedoInfo( cursor, UndoRedoInfo::Delete );
00432 if ( !undoRedoInfo.valid() ) {
00433 newPlaceHolderCommand( i18n("Delete Text") );
00434 undoRedoInfo.id = parag->paragId();
00435 undoRedoInfo.index = cursor->index();
00436 undoRedoInfo.text = QString::null;
00437 undoRedoInfo.oldParagLayouts << parag->paragLayout();
00438 }
00439 if ( !cursor->atParagEnd() )
00440 {
00441 KoTextStringChar * ch = parag->at( cursor->index() );
00442 undoRedoInfo.text += ch->c;
00443 copyCharFormatting( parag, cursor->index(), undoRedoInfo.text.length()-1, true );
00444 }
00445 KoParagLayout paragLayout;
00446 if ( parag->next() )
00447 paragLayout = parag->next()->paragLayout();
00448
00449 KoTextParag *old = cursor->parag();
00450 if ( cursor->remove() ) {
00451 if ( old != cursor->parag() && m_lastFormatted == old )
00452 m_lastFormatted = cursor->parag() ? cursor->parag()->prev() : 0;
00453 undoRedoInfo.text += "\n";
00454 undoRedoInfo.oldParagLayouts << paragLayout;
00455 } else
00456 emit paragraphModified( old, RemoveChar, cursor->index(), 1 );
00457 } break;
00458 case ActionBackspace: {
00459
00460 if ( parag->counter() && parag->counter()->style() != KoParagCounter::STYLE_NONE && cursor->index() == 0 ) {
00461
00462
00463 KoParagCounter c;
00464 c.setDepth( parag->counter()->depth() );
00465 KCommand *cmd=setCounterCommand( cursor, c );
00466 if(cmd)
00467 emit newCommand(cmd);
00468 }
00469 else if ( !cursor->atParagStart() )
00470 {
00471 checkUndoRedoInfo( cursor, UndoRedoInfo::Delete );
00472 if ( !undoRedoInfo.valid() ) {
00473 newPlaceHolderCommand( i18n("Delete Text") );
00474 undoRedoInfo.id = parag->paragId();
00475 undoRedoInfo.index = cursor->index();
00476 undoRedoInfo.text = QString::null;
00477 undoRedoInfo.oldParagLayouts << parag->paragLayout();
00478 }
00479 undoRedoInfo.text.insert( 0, cursor->parag()->at( cursor->index()-1 ) );
00480 copyCharFormatting( cursor->parag(), cursor->index()-1, 0, true );
00481 undoRedoInfo.index = cursor->index()-1;
00482
00483 cursor->removePreviousChar();
00484 emit paragraphModified( cursor->parag(), RemoveChar, cursor->index(),1 );
00485 m_lastFormatted = cursor->parag();
00486 } else if ( parag->prev() ) {
00487 emit paragraphDeleted( cursor->parag() );
00488 clearUndoRedoInfo();
00489 textdoc->setSelectionStart( KoTextDocument::Temp, cursor );
00490 cursor->gotoPreviousLetter();
00491 textdoc->setSelectionEnd( KoTextDocument::Temp, cursor );
00492 removeSelectedText( cursor, KoTextDocument::Temp, i18n( "Delete Text" ) );
00493 emit paragraphModified( cursor->parag(), AddChar, cursor->index(), cursor->parag()->length() - cursor->index() );
00494 }
00495 } break;
00496 case ActionReturn: {
00497 checkUndoRedoInfo( cursor, UndoRedoInfo::Return );
00498 if ( !undoRedoInfo.valid() ) {
00499 newPlaceHolderCommand( i18n("Insert Text") );
00500 undoRedoInfo.id = cursor->parag()->paragId();
00501 undoRedoInfo.index = cursor->index();
00502 undoRedoInfo.text = QString::null;
00503 }
00504 undoRedoInfo.text += "\n";
00505 if ( cursor->parag() )
00506 {
00507 QString last_line = cursor->parag()->toString();
00508 last_line.remove(0,last_line.find(' ')+1);
00509
00510 if( last_line.isEmpty() && cursor->parag()->counter() && cursor->parag()->counter()->numbering() == KoParagCounter::NUM_LIST )
00511 {
00512 KoParagCounter c;
00513 KCommand *cmd=setCounterCommand( cursor, c );
00514 if(cmd)
00515 emit newCommand(cmd);
00516 setLastFormattedParag( cursor->parag() );
00517 cursor->parag()->setNoCounter();
00518
00519 formatMore( 2 );
00520 emit repaintChanged( this );
00521 emit ensureCursorVisible();
00522 emit showCursor();
00523 emit updateUI( doUpdateCurrentFormat );
00524 return;
00525 }
00526 else
00527 cursor->splitAndInsertEmptyParag();
00528 }
00529
00530 Q_ASSERT( cursor->parag()->prev() );
00531 setLastFormattedParag( cursor->parag() );
00532
00533 doUpdateCurrentFormat = false;
00534 KoParagStyle * style = cursor->parag()->prev()->style();
00535 if ( style )
00536 {
00537 KoParagStyle * newStyle = style->followingStyle();
00538 if ( newStyle && style != newStyle )
00539 {
00540 doUpdateCurrentFormat = true;
00541
00542
00543 }
00544 }
00545 if ( cursor->parag()->joinBorder() && cursor->parag()->bottomBorder().width() > 0 )
00546 cursor->parag()->prev()->setChanged( true );
00547 if ( cursor->parag()->joinBorder() && cursor->parag()->next() && cursor->parag()->next()->joinBorder() && cursor->parag()->bottomBorder() == cursor->parag()->next()->bottomBorder())
00548 cursor->parag()->next()->setChanged( true );
00549 emit paragraphCreated( cursor->parag() );
00550
00551 } break;
00552 case ActionKill:
00553
00554 if ( !cursor->atParagEnd() || cursor->parag()->next() ) {
00555 checkUndoRedoInfo( cursor, UndoRedoInfo::Delete );
00556 if ( !undoRedoInfo.valid() ) {
00557 newPlaceHolderCommand( i18n("Delete Text") );
00558 undoRedoInfo.id = cursor->parag()->paragId();
00559 undoRedoInfo.index = cursor->index();
00560 undoRedoInfo.text = QString::null;
00561 undoRedoInfo.oldParagLayouts << parag->paragLayout();
00562 }
00563 if ( cursor->atParagEnd() ) {
00564
00565 KoParagLayout paragLayout = parag->next()->paragLayout();
00566 if ( cursor->remove() )
00567 {
00568 m_lastFormatted = cursor->parag();
00569 undoRedoInfo.text += "\n";
00570 undoRedoInfo.oldParagLayouts << paragLayout;
00571 }
00572 } else {
00573 int oldLen = undoRedoInfo.text.length();
00574 undoRedoInfo.text += cursor->parag()->string()->toString().mid( cursor->index() );
00575 for ( int i = cursor->index(); i < cursor->parag()->length(); ++i )
00576 copyCharFormatting( cursor->parag(), i, oldLen + i - cursor->index(), true );
00577 cursor->killLine();
00578 emit paragraphModified( cursor->parag(), RemoveChar, cursor->index(), cursor->parag()->length()-cursor->index() );
00579 }
00580 }
00581 break;
00582 }
00583
00584 if ( !undoRedoInfo.customItemsMap.isEmpty() )
00585 clearUndoRedoInfo();
00586
00587 formatMore( 2 );
00588 emit repaintChanged( this );
00589 emit ensureCursorVisible();
00590 emit showCursor();
00591 emit updateUI( doUpdateCurrentFormat );
00592 }
00593
00594 void KoTextObject::insert( KoTextCursor * cursor, KoTextFormat * currentFormat,
00595 const QString &txt, const QString & commandName, KoTextDocument::SelectionId selectionId,
00596 int insertFlags, CustomItemsMap customItemsMap )
00597 {
00598 if ( protectContent() )
00599 return;
00600 const bool checkNewLine = insertFlags & CheckNewLine;
00601 const bool removeSelected = ( insertFlags & DoNotRemoveSelected ) == 0;
00602 const bool repaint = ( insertFlags & DoNotRepaint ) == 0;
00603
00604 bool tinyRepaint = !checkNewLine;
00605 if ( repaint )
00606 emit hideCursor();
00607 if ( textdoc->hasSelection( selectionId, true ) && removeSelected ) {
00608 kdDebug() << k_funcinfo << "removing selection " << selectionId << endl;
00609
00610 emitNewCommand(replaceSelectionCommand( cursor, txt, commandName, selectionId, insertFlags, customItemsMap ));
00611 return;
00612 }
00613
00614 if ( insertFlags & OverwriteMode ) {
00615 textdoc->setSelectionStart( KoTextDocument::Temp, cursor );
00616 KoTextCursor oc = *cursor;
00617 kdDebug(32500) << "overwrite: going to insert " << txt.length() << " chars; idx=" << oc.index() << endl;
00618 oc.setIndex( QMIN( oc.index() + (int)txt.length(), oc.parag()->lastCharPos() + 1 ) );
00619 kdDebug(32500) << "overwrite: removing from " << cursor->index() << " to " << oc.index() << endl;
00620 if ( oc.index() > cursor->index() )
00621 {
00622 textdoc->setSelectionEnd( KoTextDocument::Temp, &oc );
00623 int newInsertFlags = insertFlags & ~OverwriteMode;
00624 newInsertFlags &= ~DoNotRemoveSelected;
00625 emitNewCommand(replaceSelectionCommand( cursor, txt, commandName, KoTextDocument::Temp, newInsertFlags, customItemsMap ));
00626 return;
00627 }
00628 }
00629 KoTextCursor c2 = *cursor;
00630
00631 if ( !customItemsMap.isEmpty() )
00632 clearUndoRedoInfo();
00633 checkUndoRedoInfo( cursor, UndoRedoInfo::Insert );
00634 if ( !undoRedoInfo.valid() ) {
00635 if ( !commandName.isNull() )
00636 newPlaceHolderCommand( commandName );
00637 undoRedoInfo.id = cursor->parag()->paragId();
00638 undoRedoInfo.index = cursor->index();
00639 undoRedoInfo.text = QString::null;
00640 }
00641 int oldLen = undoRedoInfo.text.length();
00642 KoTextCursor oldCursor = *cursor;
00643 bool wasChanged = cursor->parag()->hasChanged();
00644 int origLine;
00645 oldCursor.parag()->lineStartOfChar( oldCursor.index(), 0, &origLine );
00646
00647
00648 cursor->insert( txt, checkNewLine );
00649
00650 setLastFormattedParag( checkNewLine ? oldCursor.parag() : cursor->parag() );
00651
00652 if ( !customItemsMap.isEmpty() ) {
00653 customItemsMap.insertItems( oldCursor, txt.length() );
00654 undoRedoInfo.customItemsMap = customItemsMap;
00655 tinyRepaint = false;
00656 }
00657
00658 textdoc->setSelectionStart( KoTextDocument::Temp, &oldCursor );
00659 textdoc->setSelectionEnd( KoTextDocument::Temp, cursor );
00660
00661 textdoc->setFormat( KoTextDocument::Temp, currentFormat, KoTextFormat::Format );
00662 textdoc->setFormat( KoTextDocument::InputMethodPreedit, currentFormat, KoTextFormat::Format );
00663 textdoc->removeSelection( KoTextDocument::Temp );
00664
00665 if ( !customItemsMap.isEmpty() ) {
00666
00667 CustomItemsMap::Iterator it = customItemsMap.begin();
00668 for ( ; it != customItemsMap.end(); ++it )
00669 it.data()->resize();
00670 }
00671
00672
00673
00674
00675 #if 0
00676 KoTextParag *parag = cursor->parag();
00677 if ( !checkNewLine && m_lastFormatted == parag && ( !parag->next() || parag->next()->isValid() ) )
00678 {
00679 parag->format();
00680 m_lastFormatted = m_lastFormatted->next();
00681 }
00682 #endif
00683
00684
00685 ensureFormatted( cursor->parag() );
00686
00687
00688
00689
00690 if ( !checkNewLine && tinyRepaint && !wasChanged )
00691 {
00692
00693
00694 Q_ASSERT( cursor->parag() == oldCursor.parag() );
00695 KoTextParag* parag = cursor->parag();
00696
00697
00698
00699 parag->setChanged( false );
00700 parag->setLineChanged( origLine - 1 );
00701 }
00702
00703 if ( repaint ) {
00704 emit repaintChanged( this );
00705 emit ensureCursorVisible();
00706 emit showCursor();
00707
00708 if ( oldCursor.index() == 0 && oldCursor.parag()->alignment() == Qt::AlignAuto )
00709 emit updateUI( true );
00710
00711 }
00712 undoRedoInfo.text += txt;
00713 for ( int i = 0; i < (int)txt.length(); ++i ) {
00714 if ( txt[ oldLen + i ] != '\n' )
00715 copyCharFormatting( c2.parag(), c2.index(), oldLen + i, false );
00716 c2.gotoNextLetter();
00717 }
00718
00719 if ( !removeSelected ) {
00720
00721
00722 if ( textdoc->removeSelection( selectionId ) && repaint )
00723 selectionChangedNotify();
00724 }
00725 if ( !customItemsMap.isEmpty() ) {
00726 clearUndoRedoInfo();
00727 }
00728
00729
00730 emit paragraphModified( oldCursor.parag(), AddChar, cursor->index(), txt.length() );
00731 if (checkNewLine) {
00732 KoTextParag* p = oldCursor.parag()->next();
00733 while ( p && p != cursor->parag() ) {
00734 emit paragraphCreated( p );
00735 p = p->next();
00736 }
00737 }
00738 }
00739
00740 void KoTextObject::pasteText( KoTextCursor * cursor, const QString & text, KoTextFormat * currentFormat, bool removeSelected )
00741 {
00742 if ( protectContent() )
00743 return;
00744 kdDebug(32500) << "KoTextObject::pasteText cursor parag=" << cursor->parag()->paragId() << endl;
00745 QString t = text;
00746
00747 QRegExp crlf( QString::fromLatin1("\r\n") );
00748 t.replace( crlf, QChar('\n') );
00749
00750 for ( int i=0; (uint) i<t.length(); i++ ) {
00751 if ( t[ i ] < ' ' && t[ i ] != '\n' && t[ i ] != '\t' )
00752 t[ i ] = ' ';
00753 }
00754 if ( !t.isEmpty() )
00755 {
00756 int insertFlags = CheckNewLine;
00757 if ( !removeSelected )
00758 insertFlags |= DoNotRemoveSelected;
00759 insert( cursor, currentFormat, t, i18n("Paste Text"),
00760 KoTextDocument::Standard, insertFlags );
00761 formatMore( 2 );
00762 emit repaintChanged( this );
00763 }
00764 }
00765
00766 KCommand* KoTextObject::setParagLayoutCommand( KoTextCursor * cursor, const KoParagLayout& paragLayout,
00767 KoTextDocument::SelectionId selectionId, int paragLayoutFlags,
00768 int marginIndex, bool createUndoRedo )
00769 {
00770 if ( protectContent() )
00771 return 0;
00772 storeParagUndoRedoInfo( cursor, selectionId );
00773 undoRedoInfo.type = UndoRedoInfo::Invalid;
00774 if ( paragLayoutFlags != 0 )
00775 {
00776 emit hideCursor();
00777 if ( !textdoc->hasSelection( selectionId, true ) ) {
00778 cursor->parag()->setParagLayout( paragLayout, paragLayoutFlags, marginIndex );
00779 setLastFormattedParag( cursor->parag() );
00780 } else {
00781 KoTextParag *start = textdoc->selectionStart( selectionId );
00782 KoTextParag *end = textdoc->selectionEnd( selectionId );
00783 for ( ; start && start != end->next() ; start = start->next() ) {
00784 if ( paragLayoutFlags == KoParagLayout::BulletNumber && start->length() <= 1 )
00785 continue;
00786 start->setParagLayout( paragLayout, paragLayoutFlags, marginIndex );
00787 }
00788 setLastFormattedParag( start );
00789 }
00790
00791 formatMore( 2 );
00792 emit repaintChanged( this );
00793 emit showCursor();
00794 emit updateUI( true );
00795
00796 if ( createUndoRedo )
00797 {
00798
00799 KoTextDocCommand * cmd = new KoTextParagCommand( textdoc, undoRedoInfo.id, undoRedoInfo.eid,
00800 undoRedoInfo.oldParagLayouts,
00801 paragLayout, paragLayoutFlags,
00802 (QStyleSheetItem::Margin)marginIndex );
00803 textdoc->addCommand( cmd );
00804 return new KoTextCommand( this, "related to KoTextParagCommand" );
00805 }
00806 }
00807 return 0;
00808 }
00809
00810
00811 void KoTextObject::applyStyle( KoTextCursor * cursor, const KoParagStyle * newStyle,
00812 KoTextDocument::SelectionId selectionId,
00813 int paragLayoutFlags, int formatFlags,
00814 bool createUndoRedo, bool interactive )
00815 {
00816 KCommand *cmd = applyStyleCommand( cursor, newStyle, selectionId,
00817 paragLayoutFlags, formatFlags,
00818 createUndoRedo, interactive );
00819 if ( createUndoRedo && cmd )
00820 emit newCommand( cmd );
00821 else
00822 Q_ASSERT( !cmd );
00823 }
00824
00825 KCommand *KoTextObject::applyStyleCommand( KoTextCursor * cursor, const KoParagStyle * newStyle,
00826 KoTextDocument::SelectionId selectionId,
00827 int paragLayoutFlags, int formatFlags,
00828 bool createUndoRedo, bool interactive )
00829 {
00830 if ( protectContent())
00831 return 0L;
00832 if ( interactive )
00833 emit hideCursor();
00834 if ( !textdoc->hasSelection( selectionId, true ) && !cursor)
00835 return 0L;
00841 KMacroCommand * macroCmd = createUndoRedo ? new KMacroCommand( i18n("Apply Style %1").
00842 arg(newStyle->displayName() ) ) : 0;
00843
00844
00845
00846 KCommand* cmd = setParagLayoutCommand( cursor, newStyle->paragLayout(), selectionId, paragLayoutFlags, -1, createUndoRedo );
00847 if ( cmd )
00848 macroCmd->addCommand( cmd );
00849
00850
00851
00852 KoTextParag * firstParag;
00853 KoTextParag * lastParag;
00854 if ( !textdoc->hasSelection( selectionId, true ) ) {
00855
00856 firstParag = cursor->parag();
00857 lastParag = cursor->parag();
00858 }
00859 else
00860 {
00861 firstParag = textdoc->selectionStart( selectionId );
00862 lastParag = textdoc->selectionEnd( selectionId );
00863 }
00864
00865 if ( formatFlags != 0 )
00866 {
00867 KoTextFormat * newFormat = textdoc->formatCollection()->format( &newStyle->format() );
00868
00869 if ( createUndoRedo )
00870 {
00871 QValueList<KoTextFormat *> lstFormats;
00872
00873 for ( KoTextParag * parag = firstParag ; parag && parag != lastParag->next() ; parag = parag->next() )
00874 {
00875
00876 lstFormats.append( parag->paragFormat() );
00877 }
00878 KoTextCursor c1( textdoc );
00879 c1.setParag( firstParag );
00880 c1.setIndex( 0 );
00881 KoTextCursor c2( textdoc );
00882 c2.setParag( lastParag );
00883 c2.setIndex( lastParag->string()->length() );
00884 undoRedoInfo.clear();
00885 undoRedoInfo.type = UndoRedoInfo::Invalid;
00886 readFormats( c1, c2 );
00887
00888 KoTextDocCommand * cmd = new KoTextFormatCommand( textdoc, firstParag->paragId(), 0,
00889 lastParag->paragId(), c2.index(),
00890 undoRedoInfo.text.rawData(), newFormat,
00891 formatFlags );
00892 textdoc->addCommand( cmd );
00893 macroCmd->addCommand( new KoTextCommand( this, "related to KoTextFormatCommand" ) );
00894
00895
00896 cmd = new KoParagFormatCommand( textdoc, firstParag->paragId(), lastParag->paragId(),
00897 lstFormats, newFormat );
00898 textdoc->addCommand( cmd );
00899 macroCmd->addCommand( new KoTextCommand( this, "related to KoParagFormatCommand" ) );
00900 }
00901
00902
00903 for ( KoTextParag * parag = firstParag ; parag && parag != lastParag->next() ; parag = parag->next() )
00904 {
00905
00906
00907 parag->setFormat( 0, parag->string()->length(), newFormat, true, formatFlags );
00908 parag->setFormat( newFormat );
00909 }
00910
00911
00912 }
00913
00914
00915 QPtrListIterator<KoTextCustomItem> cit( textdoc->allCustomItems() );
00916 for ( ; cit.current() ; ++cit )
00917 cit.current()->resize();
00918
00919
00920 if ( interactive )
00921 {
00922 setLastFormattedParag( firstParag );
00923 formatMore( 2 );
00924 emit repaintChanged( this );
00925 emit updateUI( true );
00926 emit showCursor();
00927 }
00928
00929 undoRedoInfo.clear();
00930
00931 return macroCmd;
00932 }
00933
00934 void KoTextObject::applyStyleChange( KoStyleChangeDefMap changed )
00935 {
00936 #if 0 //#ifndef NDEBUG
00937 kdDebug(32500) << "KoTextObject::applyStyleChange " << changed.count() << " styles." << endl;
00938 for( KoStyleChangeDefMap::const_iterator it = changed.begin(); it != changed.end(); ++it ) {
00939 kdDebug(32500) << " " << it.key()->name()
00940 << " paragLayoutChanged=" << (*it).paragLayoutChanged
00941 << " formatChanged=" << (*it).formatChanged
00942 << endl;
00943 }
00944 #endif
00945
00946 KoTextParag *p = textdoc->firstParag();
00947 while ( p ) {
00948 KoStyleChangeDefMap::Iterator it = changed.find( p->style() );
00949 if ( it != changed.end() )
00950 {
00951 if ( (*it).paragLayoutChanged == -1 || (*it).formatChanged == -1 )
00952 {
00953 p->setStyle( m_defaultStyle );
00954
00955 }
00956 else
00957 {
00958
00959 KoTextCursor cursor( textdoc );
00960 cursor.setParag( p );
00961 cursor.setIndex( 0 );
00962
00963 applyStyle( &cursor, it.key(),
00964 KoTextDocument::Temp,
00965 (*it).paragLayoutChanged, (*it).formatChanged,
00966 false, false );
00967 }
00968 } else {
00969
00970 }
00971
00972 p = p->next();
00973 }
00974 setLastFormattedParag( textdoc->firstParag() );
00975 formatMore( 2 );
00976 emit repaintChanged( this );
00977 emit updateUI( true );
00978 }
00979
00981 KCommand *KoTextObject::setFormatCommand( const KoTextFormat *format, int flags, bool zoomFont )
00982 {
00983 textdoc->selectAll( KoTextDocument::Temp );
00984 KCommand *cmd = setFormatCommand( 0L, 0L, format, flags, zoomFont, KoTextDocument::Temp );
00985 textdoc->removeSelection( KoTextDocument::Temp );
00986 return cmd;
00987 }
00988
00989 KCommand * KoTextObject::setFormatCommand( KoTextCursor * cursor, KoTextFormat ** pCurrentFormat, const KoTextFormat *format, int flags, bool , KoTextDocument::SelectionId selectionId )
00990 {
00991 KCommand *ret = 0;
00992 if ( protectContent() )
00993 return ret;
00994
00995 KoTextFormat* newFormat = 0;
00996
00997
00998
00999 bool isNewFormat = ( pCurrentFormat && *pCurrentFormat && (*pCurrentFormat)->key() != format->key() );
01000 if ( isNewFormat || !pCurrentFormat )
01001 {
01002 #if 0
01003 int origFontSize = 0;
01004 if ( zoomFont )
01005 {
01006 origFontSize = format->pointSize();
01007 format->setPointSize( zoomedFontSize( origFontSize ) );
01008
01009 }
01010 #endif
01011
01012 if ( pCurrentFormat )
01013 (*pCurrentFormat)->removeRef();
01014
01015 newFormat = textdoc->formatCollection()->format( format );
01016 if ( newFormat->isMisspelled() ) {
01017 KoTextFormat fNoMisspelled( *newFormat );
01018 newFormat->removeRef();
01019 fNoMisspelled.setMisspelled( false );
01020 newFormat = textdoc->formatCollection()->format( &fNoMisspelled );
01021 }
01022 if ( pCurrentFormat )
01023 (*pCurrentFormat) = newFormat;
01024 }
01025
01026 if ( textdoc->hasSelection( selectionId, true ) ) {
01027 emit hideCursor();
01028 KoTextCursor c1 = textdoc->selectionStartCursor( selectionId );
01029 KoTextCursor c2 = textdoc->selectionEndCursor( selectionId );
01030 undoRedoInfo.clear();
01031 int id = c1.parag()->paragId();
01032 int index = c1.index();
01033 int eid = c2.parag()->paragId();
01034 int eindex = c2.index();
01035 readFormats( c1, c2 );
01036
01037 textdoc->setFormat( selectionId, format, flags );
01038 if ( !undoRedoInfo.customItemsMap.isEmpty() )
01039 {
01040
01041 CustomItemsMap::Iterator it = undoRedoInfo.customItemsMap.begin();
01042 for ( ; it != undoRedoInfo.customItemsMap.end(); ++it )
01043 it.data()->resize();
01044 }
01045 KoTextFormatCommand *cmd = new KoTextFormatCommand(
01046 textdoc, id, index, eid, eindex, undoRedoInfo.text.rawData(),
01047 format, flags );
01048 textdoc->addCommand( cmd );
01049 ret = new KoTextCommand( this, i18n("Format Text") );
01050 undoRedoInfo.clear();
01051 setLastFormattedParag( c1.parag() );
01052 formatMore( 2 );
01053 emit repaintChanged( this );
01054 emit showCursor();
01055 }
01056 if ( isNewFormat ) {
01057 emit showCurrentFormat();
01058
01059 if ( cursor && cursor->index() == cursor->parag()->length() - 1 ) {
01060 newFormat->addRef();
01061 cursor->parag()->string()->setFormat( cursor->index(), newFormat, TRUE );
01062 if ( cursor->parag()->length() == 1 ) {
01063 newFormat->addRef();
01064 cursor->parag()->setFormat( newFormat );
01065 cursor->parag()->invalidate(0);
01066 cursor->parag()->format();
01067 emit repaintChanged( this );
01068 }
01069 }
01070 }
01071 return ret;
01072 }
01073
01074 void KoTextObject::setFormat( KoTextCursor * cursor, KoTextFormat ** currentFormat, KoTextFormat *format, int flags, bool zoomFont )
01075 {
01076 if ( protectContent() )
01077 return;
01078 KCommand *cmd = setFormatCommand( cursor, currentFormat, format, flags, zoomFont );
01079 if (cmd)
01080 emit newCommand( cmd );
01081 }
01082
01083 void KoTextObject::emitNewCommand(KCommand *cmd)
01084 {
01085 if(cmd)
01086 emit newCommand( cmd );
01087 }
01088
01089 KCommand *KoTextObject::setCounterCommand( KoTextCursor * cursor, const KoParagCounter & counter, KoTextDocument::SelectionId selectionId )
01090 {
01091 if ( protectContent() )
01092 return 0L;
01093 const KoParagCounter * curCounter = 0L;
01094 if(cursor)
01095 curCounter=cursor->parag()->counter();
01096 if ( !textdoc->hasSelection( selectionId, true ) &&
01097 curCounter && counter == *curCounter ) {
01098 return 0L;
01099 }
01100 emit hideCursor();
01101 storeParagUndoRedoInfo( cursor, selectionId );
01102 if ( !textdoc->hasSelection( selectionId, true ) && cursor) {
01103 cursor->parag()->setCounter( counter );
01104 setLastFormattedParag( cursor->parag() );
01105 } else {
01106 KoTextParag *start = textdoc->selectionStart( selectionId );
01107 KoTextParag *end = textdoc->selectionEnd( selectionId );
01108 #if 0
01109
01110 if ( start != end && end->length() <= 1 )
01111 {
01112 end = end->prev();
01113 undoRedoInfo.eid = end->paragId();
01114 }
01115 #endif
01116 setLastFormattedParag( start );
01117 for ( ; start && start != end->next() ; start = start->next() )
01118 {
01119 if ( start->length() > 1 )
01120 start->setCounter( counter );
01121 }
01122 }
01123 formatMore( 2 );
01124 emit repaintChanged( this );
01125 if ( !undoRedoInfo.newParagLayout.counter )
01126 undoRedoInfo.newParagLayout.counter = new KoParagCounter;
01127 *undoRedoInfo.newParagLayout.counter = counter;
01128 KoTextParagCommand *cmd = new KoTextParagCommand(
01129 textdoc, undoRedoInfo.id, undoRedoInfo.eid,
01130 undoRedoInfo.oldParagLayouts, undoRedoInfo.newParagLayout,
01131 KoParagLayout::BulletNumber );
01132 textdoc->addCommand( cmd );
01133
01134 undoRedoInfo.clear();
01135 emit showCursor();
01136 emit updateUI( true );
01137 return new KoTextCommand( this, i18n("Change List Type") );
01138 }
01139
01140 KCommand * KoTextObject::setAlignCommand( KoTextCursor * cursor, int align, KoTextDocument::SelectionId selectionId )
01141 {
01142 if ( protectContent() )
01143 return 0L;
01144 if ( !textdoc->hasSelection( selectionId, true ) && cursor &&
01145 (int)cursor->parag()->alignment() == align )
01146 return 0L;
01147
01148 emit hideCursor();
01149 storeParagUndoRedoInfo( cursor ,selectionId );
01150 if ( !textdoc->hasSelection( selectionId, true ) &&cursor ) {
01151 cursor->parag()->setAlign(align);
01152 setLastFormattedParag( cursor->parag() );
01153 }
01154 else
01155 {
01156 KoTextParag *start = textdoc->selectionStart( selectionId );
01157 KoTextParag *end = textdoc->selectionEnd( selectionId );
01158 setLastFormattedParag( start );
01159 for ( ; start && start != end->next() ; start = start->next() )
01160 start->setAlign(align);
01161 }
01162 formatMore( 2 );
01163 emit repaintChanged( this );
01164 undoRedoInfo.newParagLayout.alignment = align;
01165 KoTextParagCommand *cmd = new KoTextParagCommand(
01166 textdoc, undoRedoInfo.id, undoRedoInfo.eid,
01167 undoRedoInfo.oldParagLayouts, undoRedoInfo.newParagLayout,
01168 KoParagLayout::Alignment );
01169 textdoc->addCommand( cmd );
01170 undoRedoInfo.clear();
01171 emit showCursor();
01172 emit updateUI( true );
01173 return new KoTextCommand( this, i18n("Change Alignment") );
01174 }
01175
01176 KCommand * KoTextObject::setMarginCommand( KoTextCursor * cursor, QStyleSheetItem::Margin m, double margin , KoTextDocument::SelectionId selectionId ) {
01177 if ( protectContent() )
01178 return 0L;
01179
01180
01181
01182 if ( !textdoc->hasSelection( selectionId, true ) && cursor &&
01183 cursor->parag()->margin(m) == margin )
01184 return 0L;
01185
01186 emit hideCursor();
01187 storeParagUndoRedoInfo( cursor, selectionId );
01188 if ( !textdoc->hasSelection( selectionId, true )&&cursor ) {
01189 cursor->parag()->setMargin(m, margin);
01190 setLastFormattedParag( cursor->parag() );
01191 }
01192 else
01193 {
01194 KoTextParag *start = textdoc->selectionStart( selectionId );
01195 KoTextParag *end = textdoc->selectionEnd( selectionId );
01196 setLastFormattedParag( start );
01197 for ( ; start && start != end->next() ; start = start->next() )
01198 start->setMargin(m, margin);
01199 }
01200 formatMore( 2 );
01201 emit repaintChanged( this );
01202 undoRedoInfo.newParagLayout.margins[m] = margin;
01203 KoTextParagCommand *cmd = new KoTextParagCommand(
01204 textdoc, undoRedoInfo.id, undoRedoInfo.eid,
01205 undoRedoInfo.oldParagLayouts, undoRedoInfo.newParagLayout,
01206 KoParagLayout::Margins, m );
01207 textdoc->addCommand( cmd );
01208 QString name;
01209 if ( m == QStyleSheetItem::MarginFirstLine )
01210 name = i18n("Change First Line Indent");
01211 else if ( m == QStyleSheetItem::MarginLeft || m == QStyleSheetItem::MarginRight )
01212 name = i18n("Change Indent");
01213 else
01214 name = i18n("Change Paragraph Spacing");
01215 undoRedoInfo.clear();
01216 emit showCursor();
01217 emit updateUI( true );
01218 return new KoTextCommand( this, name );
01219 }
01220
01221 KCommand * KoTextObject::setBackgroundColorCommand( KoTextCursor * cursor,
01222 const QColor & color,
01223 KoTextDocument::SelectionId selectionId ) {
01224 if ( protectContent() )
01225 return 0L;
01226
01227 if ( !textdoc->hasSelection( selectionId, true ) && cursor &&
01228 cursor->parag()->backgroundColor() == color )
01229 return 0L;
01230
01231 emit hideCursor();
01232 storeParagUndoRedoInfo( cursor, selectionId );
01233 if ( !textdoc->hasSelection( selectionId, true )&&cursor )
01234 {
01235
01236 cursor->parag()->setBackgroundColor(color);
01237 setLastFormattedParag( cursor->parag() );
01238 }
01239 else
01240 {
01241
01242 KoTextParag *start = textdoc->selectionStart( selectionId );
01243 KoTextParag *end = textdoc->selectionEnd( selectionId );
01244 setLastFormattedParag( start );
01245 for ( ; start && start != end->next() ; start = start->next() )
01246 start->setBackgroundColor(color);
01247 }
01248 formatMore( 2 );
01249 emit repaintChanged( this );
01250
01251
01252 undoRedoInfo.newParagLayout.backgroundColor = color;
01253 KoTextParagCommand *cmd = new KoTextParagCommand(
01254 textdoc, undoRedoInfo.id, undoRedoInfo.eid,
01255 undoRedoInfo.oldParagLayouts, undoRedoInfo.newParagLayout,
01256 KoParagLayout::BackgroundColor );
01257 textdoc->addCommand( cmd );
01258 undoRedoInfo.clear();
01259
01260 emit showCursor();
01261 emit updateUI( true );
01262 return new KoTextCommand( this, i18n("Change Paragraph Background Color" ) );
01263 }
01264
01265 KCommand * KoTextObject::setLineSpacingCommand( KoTextCursor * cursor, double spacing, KoParagLayout::SpacingType _type, KoTextDocument::SelectionId selectionId )
01266 {
01267 if ( protectContent() )
01268 return 0L;
01269
01270
01271
01272
01273 if ( !textdoc->hasSelection( selectionId, true ) && cursor &&
01274 cursor->parag()->kwLineSpacing() == spacing
01275 && cursor->parag()->kwLineSpacingType() == _type)
01276 return 0L;
01277
01278 emit hideCursor();
01279 storeParagUndoRedoInfo( cursor, selectionId );
01280 if ( !textdoc->hasSelection( selectionId, true ) && cursor ) {
01281 cursor->parag()->setLineSpacing(spacing);
01282 cursor->parag()->setLineSpacingType( _type);
01283 setLastFormattedParag( cursor->parag() );
01284 }
01285 else
01286 {
01287 KoTextParag *start = textdoc->selectionStart( selectionId );
01288 KoTextParag *end = textdoc->selectionEnd( selectionId );
01289 setLastFormattedParag( start );
01290 for ( ; start && start != end->next() ; start = start->next() )
01291 {
01292 start->setLineSpacing(spacing);
01293 start->setLineSpacingType( _type);
01294 }
01295 }
01296 formatMore( 2 );
01297 emit repaintChanged( this );
01298 undoRedoInfo.newParagLayout.setLineSpacingValue( spacing );
01299 undoRedoInfo.newParagLayout.lineSpacingType = _type;
01300 KoTextParagCommand *cmd = new KoTextParagCommand(
01301 textdoc, undoRedoInfo.id, undoRedoInfo.eid,
01302 undoRedoInfo.oldParagLayouts, undoRedoInfo.newParagLayout,
01303 KoParagLayout::LineSpacing );
01304 textdoc->addCommand( cmd );
01305
01306 undoRedoInfo.clear();
01307 emit showCursor();
01308 return new KoTextCommand( this, i18n("Change Line Spacing") );
01309 }
01310
01311
01312 KCommand * KoTextObject::setBordersCommand( KoTextCursor * cursor, const KoBorder& leftBorder, const KoBorder& rightBorder, const KoBorder& topBorder, const KoBorder& bottomBorder , KoTextDocument::SelectionId selectionId )
01313 {
01314 if ( protectContent() )
01315 return 0L;
01316 if ( !textdoc->hasSelection( selectionId, true ) && cursor &&
01317 cursor->parag()->leftBorder() ==leftBorder &&
01318 cursor->parag()->rightBorder() ==rightBorder &&
01319 cursor->parag()->topBorder() ==topBorder &&
01320 cursor->parag()->bottomBorder() ==bottomBorder )
01321 return 0L;
01322
01323 emit hideCursor();
01324 bool borderOutline = false;
01325 storeParagUndoRedoInfo( cursor, selectionId );
01326 if ( !textdoc->hasSelection( selectionId, true ) ) {
01327 cursor->parag()->setLeftBorder(leftBorder);
01328 cursor->parag()->setRightBorder(rightBorder);
01329 cursor->parag()->setBottomBorder(bottomBorder);
01330 cursor->parag()->setTopBorder(topBorder);
01331 setLastFormattedParag( cursor->parag() );
01332
01333 if ( cursor->parag()->next() )
01334 cursor->parag()->next()->setChanged( true );
01335 if ( cursor->parag()->prev() )
01336 cursor->parag()->prev()->setChanged( true );
01337 }
01338 else
01339 {
01340 KoTextParag *start = textdoc->selectionStart( selectionId );
01341 KoTextParag *end = textdoc->selectionEnd( selectionId );
01342 setLastFormattedParag( start );
01343 KoBorder tmpBorder;
01344 tmpBorder.setPenWidth(0);
01345 for ( ; start && start != end->next() ; start = start->next() )
01346 {
01347 start->setLeftBorder(leftBorder);
01348 start->setRightBorder(rightBorder);
01349
01350 start->setTopBorder(tmpBorder);
01351 start->setBottomBorder(tmpBorder);
01352 }
01353 end->setBottomBorder(bottomBorder);
01354 textdoc->selectionStart( selectionId )->setTopBorder(topBorder);
01355 borderOutline = true;
01356
01357 if ( start && start->prev() )
01358 start->prev()->setChanged( true );
01359 if ( end && end->next() )
01360 end->next()->setChanged( true );
01361 }
01362 formatMore( 2 );
01363 emit repaintChanged( this );
01364 undoRedoInfo.newParagLayout.leftBorder=leftBorder;
01365 undoRedoInfo.newParagLayout.rightBorder=rightBorder;
01366 undoRedoInfo.newParagLayout.topBorder=topBorder;
01367 undoRedoInfo.newParagLayout.bottomBorder=bottomBorder;
01368
01369 KoTextParagCommand *cmd = new KoTextParagCommand(
01370 textdoc, undoRedoInfo.id, undoRedoInfo.eid,
01371 undoRedoInfo.oldParagLayouts, undoRedoInfo.newParagLayout,
01372 KoParagLayout::Borders, (QStyleSheetItem::Margin)-1, borderOutline);
01373 textdoc->addCommand( cmd );
01374
01375 undoRedoInfo.clear();
01376 emit showCursor();
01377 emit updateUI( true );
01378 return new KoTextCommand( this, i18n("Change Borders") );
01379 }
01380
01381 KCommand * KoTextObject::setJoinBordersCommand( KoTextCursor * cursor, bool join, KoTextDocument::SelectionId selectionId )
01382 {
01383 if ( protectContent() )
01384 return 0L;
01385 if ( !textdoc->hasSelection( selectionId, true ) &&
01386 cursor && cursor->parag()->joinBorder() == join )
01387 return 0L;
01388
01389 emit hideCursor();
01390 bool borderOutline = false;
01391 storeParagUndoRedoInfo( cursor, KoTextDocument::Standard );
01392 if ( !textdoc->hasSelection( selectionId, true ) )
01393 {
01394 cursor->parag()->setJoinBorder( join );
01395 setLastFormattedParag( cursor->parag() );
01396
01397 if ( cursor->parag()->next() )
01398 cursor->parag()->next()->setChanged( true );
01399 if ( cursor->parag()->prev() )
01400 cursor->parag()->prev()->setChanged( true );
01401 }
01402 else
01403 {
01404 KoTextParag *start = textdoc->selectionStart( selectionId );
01405 KoTextParag *end = textdoc->selectionEnd( selectionId );
01406 setLastFormattedParag( start );
01407 for ( ; start && start != end->next() ; start = start->next() )
01408 {
01409 start->setJoinBorder( true );
01410 }
01411 end->setJoinBorder ( true );
01412 borderOutline = true;
01413
01414 if ( start && start->prev() )
01415 start->prev()->setChanged( true );
01416 if ( end && end->next() )
01417 end->next()->setChanged( true );
01418 }
01419 formatMore( 2 );
01420
01421 emit repaintChanged( this );
01422 undoRedoInfo.newParagLayout.joinBorder=join;
01423
01424 KoTextParagCommand *cmd = new KoTextParagCommand(
01425 textdoc, undoRedoInfo.id, undoRedoInfo.eid,
01426 undoRedoInfo.oldParagLayouts, undoRedoInfo.newParagLayout,
01427 KoParagLayout::Borders, (QStyleSheetItem::Margin)-1, borderOutline);
01428 textdoc->addCommand( cmd );
01429
01430 undoRedoInfo.clear();
01431 emit ensureCursorVisible();
01432 emit showCursor();
01433 emit updateUI( true );
01434 return new KoTextCommand( this, i18n("Change Join Borders") );
01435 }
01436
01437
01438 KCommand * KoTextObject::setTabListCommand( KoTextCursor * cursor, const KoTabulatorList &tabList, KoTextDocument::SelectionId selectionId )
01439 {
01440 if ( protectContent() )
01441 return 0L;
01442 if ( !textdoc->hasSelection( selectionId, true ) && cursor &&
01443 cursor->parag()->tabList() == tabList )
01444 return 0L;
01445
01446 emit hideCursor();
01447 storeParagUndoRedoInfo( cursor, selectionId );
01448
01449 if ( !textdoc->hasSelection( selectionId, true ) && cursor ) {
01450 cursor->parag()->setTabList( tabList );
01451 setLastFormattedParag( cursor->parag() );
01452 }
01453 else
01454 {
01455 KoTextParag *start = textdoc->selectionStart( selectionId );
01456 KoTextParag *end = textdoc->selectionEnd( selectionId );
01457 setLastFormattedParag( start );
01458 for ( ; start && start != end->next() ; start = start->next() )
01459 start->setTabList( tabList );
01460 }
01461
01462 formatMore( 2 );
01463 emit repaintChanged( this );
01464 undoRedoInfo.newParagLayout.setTabList( tabList );
01465 KoTextParagCommand *cmd = new KoTextParagCommand(
01466 textdoc, undoRedoInfo.id, undoRedoInfo.eid,
01467 undoRedoInfo.oldParagLayouts, undoRedoInfo.newParagLayout,
01468 KoParagLayout::Tabulator);
01469 textdoc->addCommand( cmd );
01470 undoRedoInfo.clear();
01471 emit showCursor();
01472 emit updateUI( true );
01473 return new KoTextCommand( this, i18n("Change Tabulator") );
01474 }
01475
01476 KCommand * KoTextObject::setParagDirectionCommand( KoTextCursor * cursor, QChar::Direction d, KoTextDocument::SelectionId selectionId )
01477 {
01478 if ( protectContent() )
01479 return 0L;
01480 if ( !textdoc->hasSelection( selectionId, true ) && cursor &&
01481 cursor->parag()->direction() == d )
01482 return 0L;
01483
01484 emit hideCursor();
01485 storeParagUndoRedoInfo( cursor, selectionId );
01486
01487 if ( !textdoc->hasSelection( selectionId, true ) && cursor ) {
01488 cursor->parag()->setDirection( d );
01489 setLastFormattedParag( cursor->parag() );
01490 }
01491 else
01492 {
01493 KoTextParag *start = textdoc->selectionStart( selectionId );
01494 KoTextParag *end = textdoc->selectionEnd( selectionId );
01495 setLastFormattedParag( start );
01496 for ( ; start && start != end->next() ; start = start->next() )
01497 start->setDirection( d );
01498 }
01499
01500 formatMore( 2 );
01501 emit repaintChanged( this );
01503 #if 0
01504 undoRedoInfo.newParagLayout.direction = d;
01505 KoTextParagCommand *cmd = new KoTextParagCommand(
01506 textdoc, undoRedoInfo.id, undoRedoInfo.eid,
01507 undoRedoInfo.oldParagLayouts, undoRedoInfo.newParagLayout,
01508 KoParagLayout::Shadow);
01509 textdoc->addCommand( cmd );
01510 #endif
01511 undoRedoInfo.clear();
01512 emit showCursor();
01513 emit updateUI( true );
01514 #if 0
01515 return new KoTextCommand( this, i18n("Change Shadow") );
01516 #else
01517 return 0L;
01518 #endif
01519 }
01520
01521 void KoTextObject::removeSelectedText( KoTextCursor * cursor, KoTextDocument::SelectionId selectionId, const QString & cmdName, bool createUndoRedo )
01522 {
01523 if ( protectContent() )
01524 return ;
01525 emit hideCursor();
01526 if( createUndoRedo)
01527 {
01528 checkUndoRedoInfo( cursor, UndoRedoInfo::RemoveSelected );
01529 if ( !undoRedoInfo.valid() ) {
01530 textdoc->selectionStart( selectionId, undoRedoInfo.id, undoRedoInfo.index );
01531 undoRedoInfo.text = QString::null;
01532 newPlaceHolderCommand( cmdName.isNull() ? i18n("Remove Selected Text") : cmdName );
01533 }
01534 }
01535 KoTextCursor c1 = textdoc->selectionStartCursor( selectionId );
01536 KoTextCursor c2 = textdoc->selectionEndCursor( selectionId );
01537 readFormats( c1, c2, true, true );
01538
01539
01540 textdoc->removeSelectedText( selectionId, cursor );
01541
01542 setLastFormattedParag( cursor->parag() );
01543 formatMore( 2 );
01544 emit repaintChanged( this );
01545 emit ensureCursorVisible();
01546 emit updateUI( true );
01547 emit showCursor();
01548 if(selectionId==KoTextDocument::Standard || selectionId==KoTextDocument::InputMethodPreedit)
01549 selectionChangedNotify();
01550 if ( createUndoRedo)
01551 undoRedoInfo.clear();
01552 }
01553
01554 KCommand * KoTextObject::removeSelectedTextCommand( KoTextCursor * cursor, KoTextDocument::SelectionId selectionId, bool repaint )
01555 {
01556 if ( protectContent() )
01557 return 0L;
01558 if ( !textdoc->hasSelection( selectionId, true ) )
01559 return 0L;
01560
01561 undoRedoInfo.clear();
01562 textdoc->selectionStart( selectionId, undoRedoInfo.id, undoRedoInfo.index );
01563 Q_ASSERT( undoRedoInfo.id >= 0 );
01564
01565 KoTextCursor c1 = textdoc->selectionStartCursor( selectionId );
01566 KoTextCursor c2 = textdoc->selectionEndCursor( selectionId );
01567 readFormats( c1, c2, true, true );
01568
01569 textdoc->removeSelectedText( selectionId, cursor );
01570
01571 KMacroCommand *macroCmd = new KMacroCommand( i18n("Remove Selected Text") );
01572
01573 KoTextDocCommand *cmd = deleteTextCommand( textdoc, undoRedoInfo.id, undoRedoInfo.index,
01574 undoRedoInfo.text.rawData(),
01575 undoRedoInfo.customItemsMap,
01576 undoRedoInfo.oldParagLayouts );
01577 textdoc->addCommand(cmd);
01578 macroCmd->addCommand(new KoTextCommand( this, QString::null ));
01579
01580 if(!undoRedoInfo.customItemsMap.isEmpty())
01581 undoRedoInfo.customItemsMap.deleteAll( macroCmd );
01582
01583 undoRedoInfo.type = UndoRedoInfo::Invalid;
01584 undoRedoInfo.clear();
01585 if ( repaint )
01586 selectionChangedNotify();
01587 return macroCmd;
01588 }
01589
01590 KCommand* KoTextObject::replaceSelectionCommand( KoTextCursor * cursor, const QString & replacement,
01591 const QString & cmdName,
01592 KoTextDocument::SelectionId selectionId,
01593 int insertFlags,
01594 CustomItemsMap customItemsMap )
01595 {
01596 if ( protectContent() )
01597 return 0L;
01598 Q_ASSERT( ( insertFlags & DoNotRemoveSelected ) == 0 );
01599 const bool repaint = ( insertFlags & DoNotRepaint ) == 0;
01600 if ( repaint )
01601 emit hideCursor();
01602
01603 KMacroCommand * macroCmd = new KMacroCommand( cmdName );
01604
01605
01606 KoTextCursor c1 = textdoc->selectionStartCursor( selectionId );
01607 KoTextFormat * format = c1.parag()->at( c1.index() )->format();
01608 format->addRef();
01609
01610
01611 KCommand* removeSelCmd = removeSelectedTextCommand( cursor, selectionId, repaint );
01612 if ( removeSelCmd )
01613 macroCmd->addCommand( removeSelCmd );
01614
01615
01616 if ( !customItemsMap.isEmpty() )
01617 insert( cursor, format,
01618 replacement, KoTextObject::customItemChar() ,
01619 selectionId, insertFlags | DoNotRemoveSelected, customItemsMap );
01620 else
01621 insert( cursor, format,
01622 replacement, QString::null ,
01623 selectionId, insertFlags | DoNotRemoveSelected, customItemsMap );
01624
01625 KoTextDocCommand * cmd = new KoTextInsertCommand( textdoc, undoRedoInfo.id, undoRedoInfo.index,
01626 undoRedoInfo.text.rawData(),
01627 CustomItemsMap(), undoRedoInfo.oldParagLayouts );
01628 textdoc->addCommand( cmd );
01629 macroCmd->addCommand( new KoTextCommand( this, QString::null ) );
01630
01631 undoRedoInfo.type = UndoRedoInfo::Invalid;
01632 undoRedoInfo.clear();
01633
01634 format->removeRef();
01635
01636 setLastFormattedParag( c1.parag() );
01637 if ( repaint )
01638 {
01639 formatMore( 2 );
01640 emit repaintChanged( this );
01641 emit ensureCursorVisible();
01642 emit updateUI( true );
01643 emit showCursor();
01644 if(selectionId==KoTextDocument::Standard)
01645 selectionChangedNotify();
01646 }
01647 return macroCmd;
01648 }
01649
01650 KCommand * KoTextObject::insertParagraphCommand( KoTextCursor *cursor )
01651 {
01652 if ( protectContent() )
01653 return 0L;
01654 return replaceSelectionCommand( cursor, "\n", QString::null, KoTextDocument::Standard, CheckNewLine );
01655 }
01656
01657 void KoTextObject::highlightPortion( KoTextParag * parag, int index, int length, bool repaint )
01658 {
01659 if ( !m_highlightSelectionAdded )
01660 {
01661 textdoc->addSelection( KoTextDocument::HighlightSelection );
01662 textdoc->setSelectionColor( KoTextDocument::HighlightSelection,
01663 QApplication::palette().color( QPalette::Active, QColorGroup::Dark ) );
01664 textdoc->setInvertSelectionText( KoTextDocument::HighlightSelection, true );
01665 m_highlightSelectionAdded = true;
01666 }
01667
01668 removeHighlight(repaint);
01669 KoTextCursor cursor( textdoc );
01670 cursor.setParag( parag );
01671 cursor.setIndex( index );
01672 textdoc->setSelectionStart( KoTextDocument::HighlightSelection, &cursor );
01673 cursor.setIndex( index + length );
01674 textdoc->setSelectionEnd( KoTextDocument::HighlightSelection, &cursor );
01675 if ( repaint ) {
01676 parag->setChanged( true );
01677 emit repaintChanged( this );
01678 }
01679 }
01680
01681 void KoTextObject::removeHighlight(bool repaint)
01682 {
01683 if ( textdoc->hasSelection( KoTextDocument::HighlightSelection, true ) )
01684 {
01685 KoTextParag * oldParag = textdoc->selectionStart( KoTextDocument::HighlightSelection );
01686 oldParag->setChanged( true );
01687 textdoc->removeSelection( KoTextDocument::HighlightSelection );
01688 }
01689 if ( repaint )
01690 emit repaintChanged( this );
01691 }
01692
01693 void KoTextObject::selectAll( bool select )
01694 {
01695 if ( !select )
01696 textdoc->removeSelection( KoTextDocument::Standard );
01697 else
01698 textdoc->selectAll( KoTextDocument::Standard );
01699 selectionChangedNotify();
01700 }
01701
01702 void KoTextObject::selectionChangedNotify( bool enableActions )
01703 {
01704 emit repaintChanged( this );
01705 if ( enableActions )
01706 emit selectionChanged( hasSelection() );
01707 }
01708
01709 void KoTextObject::setViewArea( QWidget* w, int maxY )
01710 {
01711 m_mapViewAreas.replace( w, maxY );
01712 }
01713
01714 void KoTextObject::setLastFormattedParag( KoTextParag *parag )
01715 {
01716
01717 if ( !m_lastFormatted || !parag || m_lastFormatted->paragId() >= parag->paragId() ) {
01718 m_lastFormatted = parag;
01719 }
01720 }
01721
01722 void KoTextObject::ensureFormatted( KoTextParag * parag, bool emitAfterFormatting )
01723 {
01724 if ( !textdoc->lastParag() )
01725 return;
01726
01727 if ( !parag->isValid() && m_lastFormatted == 0 )
01728 m_lastFormatted = parag;
01729
01730 while ( !parag->isValid() )
01731 {
01732 if ( !m_lastFormatted ) {
01733 kdWarning() << "ensureFormatted for parag " << parag << " " << parag->paragId() << " still not formatted, but m_lastFormatted==0" << endl;
01734 return;
01735 }
01736
01737 bool ret = formatMore( QMAX( 1, parag->paragId() - m_lastFormatted->paragId() ), emitAfterFormatting );
01738 if ( !ret ) {
01739
01740 break;
01741 }
01742 }
01743
01744 }
01745
01746 bool KoTextObject::formatMore( int count , bool emitAfterFormatting )
01747 {
01748 if ( ( !m_lastFormatted && d->afterFormattingEmitted )
01749 || !m_visible || m_availableHeight == -1 )
01750 return false;
01751
01752 if ( !textdoc->lastParag() )
01753 return false;
01754
01755 if ( d->abortFormatting ) {
01756 d->abortFormatting = false;
01757 return false;
01758 }
01759
01760 if ( count == 0 )
01761 {
01762 formatTimer->start( interval, TRUE );
01763 return true;
01764 }
01765
01766 int bottom = 0;
01767 if ( m_lastFormatted )
01768 {
01769 d->afterFormattingEmitted = false;
01770
01771 int viewsBottom = 0;
01772 QMapIterator<QWidget *, int> mapIt = m_mapViewAreas.begin();
01773 for ( ; mapIt != m_mapViewAreas.end() ; ++mapIt )
01774 viewsBottom = QMAX( viewsBottom, mapIt.data() );
01775
01776 #ifdef DEBUG_FORMAT_MORE
01777 kdDebug(32500) << "formatMore " << name()
01778 << " lastFormatted id=" << m_lastFormatted->paragId()
01779 << " lastFormatted's top=" << m_lastFormatted->rect().top()
01780 << " lastFormatted's height=" << m_lastFormatted->rect().height()
01781 << " count=" << count << " viewsBottom=" << viewsBottom
01782 << " availableHeight=" << m_availableHeight << endl;
01783 #endif
01784 if ( m_lastFormatted->prev() == 0 )
01785 {
01786 emit formattingFirstParag();
01787 #ifdef TIMING_FORMAT
01788 kdDebug(32500) << "formatMore " << name() << ". First parag -> starting timer" << endl;
01789 m_time.start();
01790 #endif
01791 }
01792
01793
01794
01795
01796 int i;
01797 for ( i = 0;
01798 m_lastFormatted && bottom + m_lastFormatted->rect().height() <= m_availableHeight &&
01799 ( i < count || bottom <= viewsBottom ) ; ++i )
01800 {
01801 KoTextParag* parag = m_lastFormatted;
01802 #ifdef DEBUG_FORMAT_MORE
01803 kdDebug(32500) << "formatMore formatting " << parag << " id=" << parag->paragId() << endl;
01804 #endif
01805 assert( parag->string() );
01806 parag->format();
01807 bottom = parag->rect().top() + parag->rect().height();
01808 #if 0 //def DEBUG_FORMAT_MORE
01809 kdDebug(32500) << "formatMore(inside) top=" << parag->rect().top()
01810 << " height=" << parag->rect().height()
01811 << " bottom=" << bottom << " m_lastFormatted(next parag) = " << m_lastFormatted->next() << endl;
01812 #endif
01813
01814
01815 if ( parag->counter() && parag->counter()->numbering() == KoParagCounter::NUM_CHAPTER
01816 && parag->counter()->depth() == 0 )
01817 emit chapterParagraphFormatted( parag );
01818
01819 if ( d->abortFormatting ) {
01820 #ifdef DEBUG_FORMAT_MORE
01821 kdDebug(32500) << "formatMore formatting aborted. " << endl;
01822 #endif
01823 d->abortFormatting = false;
01824 return false;
01825 }
01826
01827 if ( parag != m_lastFormatted )
01828 kdWarning() << "Some code changed m_lastFormatted during formatting! Was " << parag->paragId() << ", is now " << m_lastFormatted->paragId() << endl;
01829 #if 0 // This happens now that formatting can 'abort' (e.g. due to page not yet created)
01830 else if (!parag->isValid())
01831 kdWarning() << "PARAGRAPH " << parag->paragId() << " STILL INVALID AFTER FORMATTING" << endl;
01832 #endif
01833 m_lastFormatted = parag->next();
01834 }
01835 }
01836 else
01837 {
01838 QRect rect = textdoc->lastParag()->rect();
01839 bottom = rect.top() + rect.height();
01840 }
01841 #ifdef DEBUG_FORMAT_MORE
01842 QString id;
01843 if ( m_lastFormatted ) id = QString(" (%1)").arg(m_lastFormatted->paragId());
01844 kdDebug(32500) << "formatMore finished formatting. "
01845 << " bottom=" << bottom
01846 << " m_lastFormatted=" << m_lastFormatted << id
01847 << endl;
01848 #endif
01849
01850 if ( emitAfterFormatting )
01851 {
01852 d->afterFormattingEmitted = true;
01853 bool needMoreSpace = false;
01854
01855 if ( ( bottom > m_availableHeight ) ||
01856 ( m_lastFormatted && bottom + m_lastFormatted->rect().height() > m_availableHeight ) )
01857 needMoreSpace = true;
01858
01859 bool abort = needMoreSpace;
01860 emit afterFormatting( bottom, m_lastFormatted, &abort );
01861 if ( abort )
01862 return false;
01863 else if ( needMoreSpace && m_lastFormatted )
01864 return formatMore( 2 );
01865 }
01866
01867
01868 if ( m_lastFormatted )
01869 {
01870 formatTimer->start( interval, TRUE );
01871 #ifdef DEBUG_FORMAT_MORE
01872 kdDebug(32500) << name() << " formatMore: will have to format more. formatTimer->start with interval=" << interval << endl;
01873 #endif
01874 }
01875 else
01876 {
01877 interval = QMAX( 0, interval );
01878 #ifdef DEBUG_FORMAT_MORE
01879 kdDebug(32500) << name() << " formatMore: all formatted interval=" << interval << endl;
01880 #endif
01881 #ifdef TIMING_FORMAT
01882
01883 kdDebug(32500) << "formatMore: " << name() << " all formatted. Took "
01884 << (double)(m_time.elapsed()) / 1000 << " seconds." << endl;
01885 #endif
01886 }
01887 return true;
01888 }
01889
01890 void KoTextObject::abortFormatting()
01891 {
01892 d->abortFormatting = true;
01893 }
01894
01895 void KoTextObject::doChangeInterval()
01896 {
01897
01898 interval = 0;
01899 }
01900
01901 void KoTextObject::typingStarted()
01902 {
01903
01904 changeIntervalTimer->stop();
01905 interval = 10;
01906 }
01907
01908 void KoTextObject::typingDone()
01909 {
01910 changeIntervalTimer->start( 100, TRUE );
01911 }
01912
01913
01914
01915 KCommand *KoTextObject::changeCaseOfTextParag( int cursorPosStart, int cursorPosEnd,
01916 KoChangeCaseDia::TypeOfCase _type,
01917 KoTextCursor *cursor, KoTextParag *parag )
01918 {
01919 if ( protectContent() )
01920 return 0L;
01921
01922 KMacroCommand * macroCmd = new KMacroCommand( i18n("Change Case") );
01923 KoTextFormat *curFormat = parag->paragraphFormat();
01924 const QString text = parag->string()->toString().mid( cursorPosStart, cursorPosEnd - cursorPosStart );
01925 int posStart = cursorPosStart;
01926 int posEnd = cursorPosStart;
01927 KoTextCursor c1( textdoc );
01928 KoTextCursor c2( textdoc );
01929
01930 for ( int i = cursorPosStart; i < cursorPosEnd; ++i )
01931 {
01932 KoTextStringChar & ch = *(parag->at(i));
01933 KoTextFormat * newFormat = ch.format();
01934 if( ch.isCustom() )
01935 {
01936 posEnd = i;
01937 c1.setParag( parag );
01938 c1.setIndex( posStart );
01939 c2.setParag( parag );
01940 c2.setIndex( posEnd );
01941
01942
01943 const QString repl = text.mid( posStart, posEnd - posStart );
01944 textdoc->setSelectionStart( KoTextDocument::Temp, &c1 );
01945 textdoc->setSelectionEnd( KoTextDocument::Temp, &c2 );
01946 macroCmd->addCommand(replaceSelectionCommand(
01947 cursor, textChangedCase(repl,_type),
01948 QString::null, KoTextDocument::Temp));
01949 do
01950 {
01951 ++i;
01952 }
01953 while( parag->at(i)->isCustom() && i != cursorPosEnd);
01954 posStart=i;
01955 posEnd=i;
01956 }
01957 else
01958 {
01959 if ( newFormat != curFormat )
01960 {
01961 posEnd=i;
01962 c1.setParag( parag );
01963 c1.setIndex( posStart );
01964 c2.setParag( parag );
01965 c2.setIndex( posEnd );
01966
01967
01968 const QString repl = text.mid( posStart, posEnd - posStart );
01969 textdoc->setSelectionStart( KoTextDocument::Temp, &c1 );
01970 textdoc->setSelectionEnd( KoTextDocument::Temp, &c2 );
01971 macroCmd->addCommand(replaceSelectionCommand(
01972 cursor, textChangedCase(repl,_type),
01973 QString::null, KoTextDocument::Temp));
01974 posStart=i;
01975 posEnd=i;
01976 curFormat = newFormat;
01977 }
01978 }
01979 }
01980 if ( posStart != cursorPosEnd )
01981 {
01982
01983 c1.setParag( parag );
01984 c1.setIndex( posStart );
01985 c2.setParag( parag );
01986 c2.setIndex( cursorPosEnd );
01987
01988 textdoc->setSelectionStart( KoTextDocument::Temp, &c1 );
01989 textdoc->setSelectionEnd( KoTextDocument::Temp, &c2 );
01990 const QString repl = text.mid( posStart, cursorPosEnd - posStart );
01991 macroCmd->addCommand(replaceSelectionCommand(
01992 cursor, textChangedCase(repl,_type),
01993 QString::null, KoTextDocument::Temp));
01994 }
01995 return macroCmd;
01996
01997 }
01998
01999 KCommand *KoTextObject::changeCaseOfText(KoTextCursor *cursor,KoChangeCaseDia::TypeOfCase _type)
02000 {
02001 if ( protectContent() )
02002 return 0L;
02003 KMacroCommand * macroCmd = new KMacroCommand( i18n("Change Case") );
02004
02005 KoTextCursor start = textdoc->selectionStartCursor( KoTextDocument::Standard );
02006 KoTextCursor end = textdoc->selectionEndCursor( KoTextDocument::Standard );
02007 emit hideCursor();
02008
02009 if ( start.parag() == end.parag() )
02010 {
02011 int endIndex = QMIN( start.parag()->length() - 1, end.index() );
02012 macroCmd->addCommand( changeCaseOfTextParag( start.index(), endIndex, _type,
02013 cursor, start.parag() ) );
02014 }
02015 else
02016 {
02017 macroCmd->addCommand( changeCaseOfTextParag( start.index(), start.parag()->length() - 1, _type,
02018 cursor, start.parag() ) );
02019 KoTextParag *p = start.parag()->next();
02020 while ( p && p != end.parag() )
02021 {
02022 macroCmd->addCommand( changeCaseOfTextParag(0, p->length() - 1, _type, cursor, p ) );
02023 p = p->next();
02024 }
02025 if ( p )
02026 {
02027 int endIndex = QMIN( p->length() - 1, end.index() );
02028 macroCmd->addCommand( changeCaseOfTextParag(0, endIndex, _type, cursor, end.parag() ));
02029 }
02030 }
02031 formatMore( 2 );
02032 emit repaintChanged( this );
02033 emit ensureCursorVisible();
02034 emit updateUI( true );
02035 emit showCursor();
02036 return macroCmd;
02037 }
02038
02039 QString KoTextObject::textChangedCase(const QString& _text,KoChangeCaseDia::TypeOfCase _type)
02040 {
02041 QString text(_text);
02042 switch(_type)
02043 {
02044 case KoChangeCaseDia::UpperCase:
02045 text=text.upper();
02046 break;
02047 case KoChangeCaseDia::LowerCase:
02048 text=text.lower();
02049 break;
02050 case KoChangeCaseDia::TitleCase:
02051 for(uint i=0;i<text.length();i++)
02052 {
02053 if(text.at(i)!=' ')
02054 {
02055 QChar prev = text.at(QMAX(i-1,0));
02056 if(i==0 || prev == ' ' || prev == '\n' || prev == '\t')
02057 text=text.replace(i, 1, text.at(i).upper() );
02058 else
02059 text=text.replace(i, 1, text.at(i).lower() );
02060 }
02061 }
02062 break;
02063 case KoChangeCaseDia::ToggleCase:
02064 for(uint i=0;i<text.length();i++)
02065 {
02066 QString repl=QString(text.at(i));
02067 if(text.at(i)!=text.at(i).upper())
02068 repl=repl.upper();
02069 else if(text.at(i).lower()!=text.at(i))
02070 repl=repl.lower();
02071 text=text.replace(i, 1, repl );
02072 }
02073 break;
02074 case KoChangeCaseDia::SentenceCase:
02075 for(uint i=0;i<text.length();i++)
02076 {
02077 if(text.at(i)!=' ')
02078 {
02079 QChar prev = text.at(QMAX(i-1,0));
02080 if(i==0 || prev == '\n' ||prev.isPunct())
02081 text=text.replace(i, 1, text.at(i).upper() );
02082 }
02083 }
02084 break;
02085 default:
02086 kdDebug(32500)<<"Error in changeCaseOfText !\n";
02087 break;
02088
02089 }
02090 return text;
02091 }
02092
02093
02094 KoTextFormat * KoTextObject::currentFormat() const
02095 {
02096
02097
02098 KoTextStringChar *ch = textdoc->firstParag()->at( 0 );
02099 return ch->format();
02100 }
02101
02102 const KoParagLayout * KoTextObject::currentParagLayoutFormat() const
02103 {
02104 KoTextParag * parag = textdoc->firstParag();
02105 return &(parag->paragLayout());
02106 }
02107
02108 bool KoTextObject::rtl() const
02109 {
02110 return textdoc->firstParag()->string()->isRightToLeft();
02111 }
02112
02113 void KoTextObject::loadOasisContent( const QDomElement &bodyElem, KoOasisContext& context, KoStyleCollection * styleColl )
02114 {
02115 textDocument()->clear(false);
02116 setLastFormattedParag( 0L );
02117
02118 KoTextParag *lastParagraph = textDocument()->loadOasisText( bodyElem, context, 0, styleColl, 0 );
02119
02120 if ( !lastParagraph )
02121 {
02122
02123 textDocument()->clear( true );
02124 textDocument()->firstParag()->setStyle( styleColl->findStyle( "Standard" ) );
02125 }
02126 else
02127 textDocument()->setLastParag( lastParagraph );
02128
02129 setLastFormattedParag( textDocument()->firstParag() );
02130 }
02131
02132 KoTextCursor KoTextObject::pasteOasisText( const QDomElement &bodyElem, KoOasisContext& context,
02133 KoTextCursor& cursor, KoStyleCollection * styleColl )
02134 {
02135 KoTextCursor resultCursor( cursor );
02136 KoTextParag* lastParagraph = cursor.parag();
02137 bool removeNewline = false;
02138 uint pos = cursor.index();
02139 if ( pos == 0 && lastParagraph->length() <= 1 ) {
02140
02141 lastParagraph = lastParagraph->prev();
02142 lastParagraph = textDocument()->loadOasisText( bodyElem, context, lastParagraph, styleColl, cursor.parag() );
02143 if ( lastParagraph ) {
02144 resultCursor.setParag( lastParagraph );
02145 resultCursor.setIndex( lastParagraph->length() - 1 );
02146 }
02147 removeNewline = true;
02148 } else {
02149
02150
02151 for ( QDomNode text (bodyElem.firstChild()); !text.isNull(); text = text.nextSibling() )
02152 {
02153 QDomElement tag = text.toElement();
02154 if ( tag.isNull() ) continue;
02155
02156
02157
02158 QDomElement tagToLoad = tag;
02159 if ( tag.localName() == "numbered-paragraph" ) {
02160 QDomElement npchild;
02161 forEachElement( npchild, tag )
02162 {
02163 if ( npchild.localName() == "p" || npchild.localName() == "h" ) {
02164 tagToLoad = npchild;
02165 break;
02166 }
02167 }
02168 }
02169
02170 if ( tagToLoad.localName() == "p" || tagToLoad.localName() == "h" ) {
02171 context.styleStack().save();
02172 context.fillStyleStack( tagToLoad, KoXmlNS::text, "style-name", "paragraph" );
02173 lastParagraph->loadOasisSpan( tagToLoad, context, pos );
02174 context.styleStack().restore();
02175
02176 lastParagraph->setChanged( true );
02177 lastParagraph->invalidate( 0 );
02178
02179
02180 resultCursor.setParag( lastParagraph );
02181 resultCursor.setIndex( pos );
02182 resultCursor.splitAndInsertEmptyParag( FALSE, TRUE );
02183 removeNewline = true;
02184
02185
02186 const_cast<QDomElement &>( bodyElem ).removeChild( tag );
02187 }
02188 break;
02189 }
02190 resultCursor.setParag( lastParagraph );
02191 resultCursor.setIndex( pos );
02192
02193 lastParagraph = textDocument()->loadOasisText( bodyElem, context, lastParagraph, styleColl, lastParagraph->next() );
02194 if ( lastParagraph != resultCursor.parag() )
02195 {
02196 removeNewline = true;
02197 resultCursor.setParag( lastParagraph );
02198 resultCursor.setIndex( lastParagraph->length() - 1 );
02199 }
02200 }
02201 KoTextParag* p = resultCursor.parag();
02202 if ( p ) p = p->next();
02203
02204 if ( removeNewline && resultCursor.remove() ) {
02205 if ( m_lastFormatted == p ) {
02206 m_lastFormatted = resultCursor.parag();
02207 }
02208 }
02209 return resultCursor;
02210 }
02211
02212 void KoTextObject::saveOasisContent( KoXmlWriter& writer, KoSavingContext& context ) const
02213 {
02214 textDocument()->saveOasisContent( writer, context );
02215 }
02216
02217 KCommand *KoTextObject::setParagLayoutFormatCommand( KoParagLayout *newLayout,int flags,int marginIndex)
02218 {
02219 if ( protectContent() )
02220 return 0L;
02221 textdoc->selectAll( KoTextDocument::Temp );
02222 KoTextCursor *cursor = new KoTextCursor( textdoc );
02223 KCommand* cmd = setParagLayoutCommand( cursor, *newLayout, KoTextDocument::Temp,
02224 flags, marginIndex, true );
02225 textdoc->removeSelection( KoTextDocument::Temp );
02226 delete cursor;
02227 return cmd;
02228 }
02229
02230 void KoTextObject::setFormat( KoTextFormat * newFormat, int flags, bool zoomFont )
02231 {
02232 if ( protectContent() )
02233 return ;
02234
02235 textdoc->selectAll( KoTextDocument::Temp );
02236 KCommand *cmd = setFormatCommand( 0L, 0L, newFormat,
02237 flags, zoomFont, KoTextDocument::Temp );
02238 textdoc->removeSelection( KoTextDocument::Temp );
02239 if (cmd)
02240 emit newCommand( cmd );
02241
02242 KoTextFormat format = *currentFormat();
02243
02244 emit showFormatObject(format);
02245 }
02246
02247 KCommand *KoTextObject::setChangeCaseOfTextCommand(KoChangeCaseDia::TypeOfCase _type)
02248 {
02249 if ( protectContent() )
02250 return 0L;
02251 textdoc->selectAll( KoTextDocument::Standard );
02252 KoTextCursor *cursor = new KoTextCursor( textdoc );
02253 KCommand* cmd = changeCaseOfText(cursor, _type);
02254 textdoc->removeSelection( KoTextDocument::Standard );
02255 delete cursor;
02256 return cmd;
02257 }
02258
02259 void KoTextObject::setNeedSpellCheck(bool b)
02260 {
02261 m_needsSpellCheck = b;
02262 for (KoTextParag * parag = textdoc->firstParag(); parag ; parag = parag->next())
02263 parag->string()->setNeedsSpellCheck( b );
02264 }
02265
02266 bool KoTextObject::statistics( QProgressDialog *progress, ulong & charsWithSpace, ulong & charsWithoutSpace, ulong & words, ulong & sentences, ulong & syllables, ulong & lines, bool selected )
02267 {
02268
02269
02270
02271 QStringList subs_syl;
02272 subs_syl << "cial" << "tia" << "cius" << "cious" << "giu" << "ion" << "iou";
02273 QStringList subs_syl_regexp;
02274 subs_syl_regexp << "sia$" << "ely$";
02275
02276 QStringList add_syl;
02277 add_syl << "ia" << "riet" << "dien" << "iu" << "io" << "ii";
02278 QStringList add_syl_regexp;
02279 add_syl_regexp << "[aeiouym]bl$" << "[aeiou]{3}" << "^mc" << "ism$"
02280 << "[^l]lien" << "^coa[dglx]." << "[^gq]ua[^auieo]" << "dnt$";
02281
02282 QString s;
02283 KoTextParag * parag = textdoc->firstParag();
02284 for ( ; parag ; parag = parag->next() )
02285 {
02286 if ( progress )
02287 {
02288 progress->setProgress(progress->progress()+1);
02289
02290 kapp->processEvents();
02291 if ( progress->wasCancelled() )
02292 return false;
02293 }
02294
02295
02296
02297
02298
02299
02300
02301 bool hasTrailingSpace = true;
02302 if ( !selected ) {
02303 s = parag->string()->toString();
02304 lines += parag->lines();
02305 } else {
02306 if ( parag->hasSelection( KoTextDocument::Standard ) ) {
02307 hasTrailingSpace = false;
02308 s = parag->string()->toString();
02309 if ( !( parag->fullSelected( KoTextDocument::Standard ) ) ) {
02310 s = s.mid( parag->selectionStart( KoTextDocument::Standard ), parag->selectionEnd( KoTextDocument::Standard ) - parag->selectionStart( KoTextDocument::Standard ) );
02311 lines+=numberOfparagraphLineSelected(parag);
02312 }
02313 else
02314 lines += parag->lines();
02315 } else {
02316 continue;
02317 }
02318 }
02319
02320
02321 for ( uint i = 0 ; i < s.length() - ( hasTrailingSpace ? 1 : 0 ) ; ++i )
02322 {
02323 QChar ch = s[i];
02324 ++charsWithSpace;
02325 if ( !ch.isSpace() )
02326 ++charsWithoutSpace;
02327 }
02328
02329
02330
02331
02332
02333
02334
02335 QRegExp re("\\s+");
02336 QStringList wordlist = QStringList::split(re, s);
02337 words += wordlist.count();
02338 re.setCaseSensitive(false);
02339 for ( QStringList::Iterator it = wordlist.begin(); it != wordlist.end(); ++it ) {
02340 QString word = *it;
02341 re.setPattern("[!?.,:_\"-]");
02342 word.remove(re);
02343 if ( word.length() <= 3 ) {
02344 syllables++;
02345 continue;
02346 }
02347 re.setPattern("e$");
02348 word.remove(re);
02349 re.setPattern("[^aeiouy]+");
02350 QStringList syls = QStringList::split(re, word);
02351 int word_syllables = 0;
02352 for ( QStringList::Iterator it = subs_syl.begin(); it != subs_syl.end(); ++it ) {
02353 if( word.find(*it, 0, false) != -1 )
02354 word_syllables--;
02355 }
02356 for ( QStringList::Iterator it = subs_syl_regexp.begin(); it != subs_syl_regexp.end(); ++it ) {
02357 re.setPattern(*it);
02358 if( word.find(re) != -1 )
02359 word_syllables--;
02360 }
02361 for ( QStringList::Iterator it = add_syl.begin(); it != add_syl.end(); ++it ) {
02362 if( word.find(*it, 0, false) != -1 )
02363 word_syllables++;
02364 }
02365 for ( QStringList::Iterator it = add_syl_regexp.begin(); it != add_syl_regexp.end(); ++it ) {
02366 re.setPattern(*it);
02367 if( word.find(re) != -1 )
02368 word_syllables++;
02369 }
02370 word_syllables += syls.count();
02371 if ( word_syllables == 0 )
02372 word_syllables = 1;
02373 syllables += word_syllables;
02374 }
02375 re.setCaseSensitive(true);
02376
02377
02378
02379 s = s.stripWhiteSpace();
02380 QChar lastchar = s.at(s.length());
02381 if( ! s.isEmpty() && ! KoAutoFormat::isMark( lastchar ) ) {
02382 s = s + ".";
02383 }
02384 re.setPattern("[.?!]+");
02385 s.replace(re, ".");
02386 re.setPattern("\\d\\.\\d");
02387 s.replace(re, "0,0");
02388 re.setPattern("[A-Z]\\.+");
02389 s.replace(re, "*");
02390 for ( uint i = 0 ; i < s.length() ; ++i )
02391 {
02392 QChar ch = s[i];
02393 if ( KoAutoFormat::isMark( ch ) )
02394 ++sentences;
02395 }
02396 }
02397 return true;
02398 }
02399
02400 int KoTextObject::numberOfparagraphLineSelected( KoTextParag *parag)
02401 {
02402 int indexOfLineStart;
02403 int lineStart;
02404 int lineEnd;
02405 KoTextCursor c1 = textdoc->selectionStartCursor( KoTextDocument::Standard );
02406 KoTextCursor c2 = textdoc->selectionEndCursor( KoTextDocument::Standard );
02407 parag->lineStartOfChar( c1.index(), &indexOfLineStart, &lineStart );
02408
02409 parag->lineStartOfChar( c2.index(), &indexOfLineStart, &lineEnd );
02410 return (lineEnd - lineStart+1);
02411 }
02412
02413 KoVariable* KoTextObject::variableAtPoint( const QPoint& iPoint ) const
02414 {
02415 KoTextCursor cursor( textDocument() );
02416 int variablePosition = -1;
02417 cursor.place( iPoint, textDocument()->firstParag(), false, &variablePosition );
02418 if ( variablePosition == -1 )
02419 return 0;
02420 return variableAtPosition( cursor.parag(), variablePosition );
02421 }
02422
02423 KoVariable* KoTextObject::variableAtPosition( KoTextParag* parag, int index ) const
02424 {
02425 KoTextStringChar * ch = parag->at( index );
02426 if ( ch->isCustom() )
02427 return dynamic_cast<KoVariable *>( ch->customItem() );
02428 return 0;
02429 }
02430
02431 const char * KoTextObject::acceptSelectionMimeType()
02432 {
02433 return "application/vnd.oasis.opendocument.";
02434 }
02435
02436 QCString KoTextObject::providesOasis( QMimeSource* mime )
02437 {
02438 const char* fmt;
02439 const char* acceptMimeType = acceptSelectionMimeType();
02440 for ( int i = 0; (fmt = mime->format(i)); ++i )
02441 {
02442 if ( QString( fmt ).startsWith( acceptMimeType ) )
02443 {
02444 return fmt;
02445 }
02446 }
02447 return "";
02448 }
02449
02450 #ifndef NDEBUG
02451 void KoTextObject::printRTDebug(int info)
02452 {
02453 KoTextParag* lastParag = 0;
02454 for (KoTextParag * parag = textdoc->firstParag(); parag ; parag = parag->next())
02455 {
02456 assert( parag->prev() == lastParag );
02457 parag->printRTDebug( info );
02458 lastParag = parag;
02459 }
02460 if ( info == 1 )
02461 textdoc->formatCollection()->debug();
02462 }
02463 #endif
02464
02466
02467 KCommand *KoTextFormatInterface::setBoldCommand(bool on)
02468 {
02469 KoTextFormat format( *currentFormat() );
02470 format.setBold( on );
02471 return setFormatCommand( &format, KoTextFormat::Bold );
02472 }
02473
02474 KCommand *KoTextFormatInterface::setItalicCommand( bool on)
02475 {
02476 KoTextFormat format( *currentFormat() );
02477 format.setItalic( on );
02478 return setFormatCommand( &format, KoTextFormat::Italic );
02479 }
02480
02481 KCommand *KoTextFormatInterface::setUnderlineCommand( bool on )
02482 {
02483 KoTextFormat format( *currentFormat() );
02484 format.setUnderlineType( on ? KoTextFormat::U_SIMPLE : KoTextFormat::U_NONE);
02485 return setFormatCommand( &format, KoTextFormat::ExtendUnderLine );
02486 }
02487
02488 KCommand *KoTextFormatInterface::setUnderlineColorCommand( const QColor &color )
02489 {
02490 KoTextFormat format( *currentFormat() );
02491 format.setTextUnderlineColor( color);
02492 return setFormatCommand( &format, KoTextFormat::ExtendUnderLine );
02493 }
02494
02495 KCommand *KoTextFormatInterface::setDoubleUnderlineCommand( bool on )
02496 {
02497 KoTextFormat format( *currentFormat() );
02498 format.setUnderlineType( on ? KoTextFormat::U_DOUBLE : KoTextFormat::U_NONE);
02499 return setFormatCommand( &format, KoTextFormat::ExtendUnderLine );
02500 }
02501
02502 KCommand *KoTextFormatInterface::setStrikeOutCommand( bool on )
02503 {
02504 KoTextFormat format( *currentFormat() );
02505 format.setStrikeOutType( on ? KoTextFormat::S_SIMPLE : KoTextFormat::S_NONE);
02506 return setFormatCommand( &format, KoTextFormat::StrikeOut );
02507 }
02508
02509 KCommand *KoTextFormatInterface::setTextBackgroundColorCommand(const QColor & col)
02510 {
02511 KoTextFormat format( *currentFormat() );
02512 format.setTextBackgroundColor( col );
02513 return setFormatCommand( &format, KoTextFormat::TextBackgroundColor );
02514 }
02515
02516 KCommand *KoTextFormatInterface::setPointSizeCommand( int s )
02517 {
02518 KoTextFormat format( *currentFormat() );
02519 format.setPointSize( s );
02520 return setFormatCommand( &format, KoTextFormat::Size, true );
02521 }
02522
02523 KCommand *KoTextFormatInterface::setFamilyCommand(const QString &font)
02524 {
02525 KoTextFormat format( *currentFormat() );
02526 format.setFamily( font );
02527 return setFormatCommand( &format, KoTextFormat::Family );
02528 }
02529
02530 QColor KoTextFormatInterface::textBackgroundColor() const
02531 {
02532 return currentFormat()->textBackgroundColor();
02533 }
02534
02535 QColor KoTextFormatInterface::textUnderlineColor()const
02536 {
02537 return currentFormat()->textUnderlineColor();
02538 }
02539
02540 QColor KoTextFormatInterface::textColor() const
02541 {
02542 return currentFormat()->color();
02543 }
02544
02545 bool KoTextFormatInterface::textUnderline()const
02546 {
02547 return currentFormat()->underline();
02548 }
02549
02550 bool KoTextFormatInterface::textDoubleUnderline()const
02551 {
02552 return currentFormat()->doubleUnderline();
02553 }
02554
02555 bool KoTextFormatInterface::textBold()const
02556 {
02557 return currentFormat()->font().bold();
02558 }
02559
02560 bool KoTextFormatInterface::textStrikeOut()const
02561 {
02562 return currentFormat()->font().strikeOut();
02563 }
02564
02565 bool KoTextFormatInterface::textItalic() const
02566 {
02567 return currentFormat()->font().italic();
02568 }
02569
02570 bool KoTextFormatInterface::textSubScript() const
02571 {
02572 return (currentFormat()->vAlign()==KoTextFormat::AlignSubScript);
02573 }
02574
02575 bool KoTextFormatInterface::textSuperScript() const
02576 {
02577 return (currentFormat()->vAlign()==KoTextFormat::AlignSuperScript);
02578 }
02579
02580 double KoTextFormatInterface::shadowDistanceX() const
02581 {
02582 return currentFormat()->shadowDistanceX();
02583 }
02584
02585 double KoTextFormatInterface::shadowDistanceY() const
02586 {
02587 return currentFormat()->shadowDistanceY();
02588 }
02589
02590 QColor KoTextFormatInterface::shadowColor() const
02591 {
02592 return currentFormat()->shadowColor();
02593 }
02594
02595 KoTextFormat::AttributeStyle KoTextFormatInterface::fontAttribute() const
02596 {
02597 return currentFormat()->attributeFont();
02598 }
02599
02600 double KoTextFormatInterface::relativeTextSize() const
02601 {
02602 return currentFormat()->relativeTextSize();
02603 }
02604
02605 int KoTextFormatInterface::offsetFromBaseLine()const
02606 {
02607 return currentFormat()->offsetFromBaseLine();
02608 }
02609
02610 bool KoTextFormatInterface::wordByWord()const
02611 {
02612 return currentFormat()->wordByWord();
02613 }
02614
02615 bool KoTextFormatInterface::hyphenation()const
02616 {
02617 return currentFormat()->hyphenation();
02618 }
02619
02620 KoTextFormat::UnderlineType KoTextFormatInterface::underlineType()const
02621 {
02622 return currentFormat()->underlineType();
02623 }
02624
02625 KoTextFormat::StrikeOutType KoTextFormatInterface::strikeOutType()const
02626 {
02627 return currentFormat()->strikeOutType();
02628 }
02629
02630 KoTextFormat::UnderlineStyle KoTextFormatInterface::underlineStyle()const
02631 {
02632 return currentFormat()->underlineStyle();
02633 }
02634
02635 KoTextFormat::StrikeOutStyle KoTextFormatInterface::strikeOutStyle()const
02636 {
02637 return currentFormat()->strikeOutStyle();
02638 }
02639
02640 QFont KoTextFormatInterface::textFont() const
02641 {
02642 QFont fn( currentFormat()->font() );
02643
02644
02645 return fn;
02646 }
02647
02648 QString KoTextFormatInterface::textFontFamily()const
02649 {
02650 return currentFormat()->font().family();
02651 }
02652
02653 QString KoTextFormatInterface::language() const
02654 {
02655 return currentFormat()->language();
02656 }
02657
02658 KCommand *KoTextFormatInterface::setTextColorCommand(const QColor &color)
02659 {
02660 KoTextFormat format( *currentFormat() );
02661 format.setColor( color );
02662 return setFormatCommand( &format, KoTextFormat::Color );
02663 }
02664
02665 KCommand *KoTextFormatInterface::setTextSubScriptCommand(bool on)
02666 {
02667 KoTextFormat format( *currentFormat() );
02668 if(!on)
02669 format.setVAlign(KoTextFormat::AlignNormal);
02670 else
02671 format.setVAlign(KoTextFormat::AlignSubScript);
02672 return setFormatCommand( &format, KoTextFormat::VAlign );
02673 }
02674
02675 KCommand *KoTextFormatInterface::setTextSuperScriptCommand(bool on)
02676 {
02677 KoTextFormat format( *currentFormat() );
02678 if(!on)
02679 format.setVAlign(KoTextFormat::AlignNormal);
02680 else
02681 format.setVAlign(KoTextFormat::AlignSuperScript);
02682 return setFormatCommand( &format, KoTextFormat::VAlign );
02683 }
02684
02685 KCommand *KoTextFormatInterface::setDefaultFormatCommand()
02686 {
02687 KoTextFormatCollection * coll = currentFormat()->parent();
02688 Q_ASSERT(coll);
02689 if(coll)
02690 {
02691 KoTextFormat * format = coll->defaultFormat();
02692 return setFormatCommand( format, KoTextFormat::Format );
02693 } else {
02694 kdDebug() << "useless call to setDefaultFormatCommand at: " << kdBacktrace() << endl;
02695 }
02696 return 0;
02697 }
02698
02699 KCommand *KoTextFormatInterface::setAlignCommand(int align)
02700 {
02701 KoParagLayout format( *currentParagLayoutFormat() );
02702 format.alignment=align;
02703 return setParagLayoutFormatCommand(&format,KoParagLayout::Alignment);
02704 }
02705
02706 KCommand *KoTextFormatInterface::setHyphenationCommand( bool _b )
02707 {
02708 KoTextFormat format( *currentFormat() );
02709 format.setHyphenation( _b );
02710 return setFormatCommand( &format, KoTextFormat::Hyphenation);
02711 }
02712
02713
02714 KCommand *KoTextFormatInterface::setShadowTextCommand( double shadowDistanceX, double shadowDistanceY, const QColor& shadowColor )
02715 {
02716 KoTextFormat format( *currentFormat() );
02717 format.setShadow( shadowDistanceX, shadowDistanceY, shadowColor );
02718 return setFormatCommand( &format, KoTextFormat::ShadowText );
02719 }
02720
02721 KCommand *KoTextFormatInterface::setFontAttributeCommand( KoTextFormat::AttributeStyle _att)
02722 {
02723 KoTextFormat format( *currentFormat() );
02724 format.setAttributeFont( _att );
02725 return setFormatCommand( &format, KoTextFormat::Attribute );
02726 }
02727
02728 KCommand *KoTextFormatInterface::setRelativeTextSizeCommand( double _size )
02729 {
02730 KoTextFormat format( *currentFormat() );
02731 format.setRelativeTextSize( _size );
02732 return setFormatCommand( &format, KoTextFormat::VAlign );
02733 }
02734
02735 KCommand *KoTextFormatInterface::setOffsetFromBaseLineCommand( int _offset )
02736 {
02737 KoTextFormat format( *currentFormat() );
02738 format.setOffsetFromBaseLine( _offset );
02739 return setFormatCommand( &format, KoTextFormat::OffsetFromBaseLine );
02740 }
02741
02742 KCommand *KoTextFormatInterface::setWordByWordCommand( bool _b )
02743 {
02744 KoTextFormat format( *currentFormat() );
02745 format.setWordByWord( _b );
02746 return setFormatCommand( &format, KoTextFormat::WordByWord );
02747 }
02748
02749 #if 0
02750 void KoTextFormatInterface::setAlign(int align)
02751 {
02752 KCommand *cmd = setAlignCommand( align );
02753 emitNewCommand( cmd );
02754 }
02755
02756 void KoTextFormatInterface::setMargin(QStyleSheetItem::Margin m, double margin)
02757 {
02758 KCommand *cmd = setMarginCommand( m, margin );
02759 emitNewCommand( cmd );
02760 }
02761
02762 void KoTextFormatInterface::setTabList(const KoTabulatorList & tabList )
02763 {
02764 KCommand *cmd = setTabListCommand( tabList );
02765 emitNewCommand( cmd );
02766 }
02767
02768 void KoTextFormatInterface::setCounter(const KoParagCounter & counter )
02769 {
02770 KCommand *cmd = setCounterCommand( counter );
02771 emitNewCommand( cmd );
02772 }
02773
02774 void KoTextFormatInterface::setParagLayoutFormat( KoParagLayout *newLayout, int flags, int marginIndex)
02775 {
02776 KCommand *cmd = setParagLayoutFormatCommand(newLayout, flags, marginIndex);
02777 emitNewCommand( cmd );
02778 }
02779 #endif
02780
02781 KCommand *KoTextFormatInterface::setMarginCommand(QStyleSheetItem::Margin m, double margin)
02782 {
02783 KoParagLayout format( *currentParagLayoutFormat() );
02784 format.margins[m]=margin;
02785 return setParagLayoutFormatCommand(&format,KoParagLayout::Margins,(int)m);
02786 }
02787
02788 KCommand *KoTextFormatInterface::setTabListCommand(const KoTabulatorList & tabList )
02789 {
02790 KoParagLayout format( *currentParagLayoutFormat() );
02791 format.setTabList(tabList);
02792 return setParagLayoutFormatCommand(&format,KoParagLayout::Tabulator);
02793 }
02794
02795 KCommand *KoTextFormatInterface::setCounterCommand(const KoParagCounter & counter )
02796 {
02797 KoParagLayout format( *currentParagLayoutFormat() );
02798 if(!format.counter)
02799 format.counter = new KoParagCounter;
02800 *format.counter = counter;
02801 return setParagLayoutFormatCommand(&format,KoParagLayout::BulletNumber);
02802 }
02803
02804 KCommand *KoTextFormatInterface::setLanguageCommand(const QString &_lang)
02805 {
02806 KoTextFormat format( *currentFormat() );
02807 format.setLanguage(_lang);
02808 return setFormatCommand( &format, KoTextFormat::Language );
02809 }
02810
02811 KoTextDocCommand *KoTextFormatInterface::deleteTextCommand( KoTextDocument *textdoc, int id, int index, const QMemArray<KoTextStringChar> & str, const CustomItemsMap & customItemsMap, const QValueList<KoParagLayout> & oldParagLayouts )
02812 {
02813 return textdoc->deleteTextCommand( textdoc, id, index, str, customItemsMap, oldParagLayouts );
02814 }
02815
02816 #include "KoTextObject.moc"