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