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