lib Library API Documentation

kotextobject.cc

00001 /* This file is part of the KDE project 00002 Copyright (C) 2001 David Faure <faure@kde.org> 00003 00004 This library is free software; you can redistribute it and/or 00005 modify it under the terms of the GNU Library General Public 00006 License as published by the Free Software Foundation; either 00007 version 2 of the License, or (at your option) any later version. 00008 00009 This library is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 Library General Public License for more details. 00013 00014 You should have received a copy of the GNU Library General Public License 00015 along with this library; see the file COPYING.LIB. If not, write to 00016 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00017 Boston, MA 02111-1307, USA. 00018 */ 00019 00020 #include <qtimer.h> 00021 #include <qregexp.h> 00022 #include "kotextobject.h" 00023 #include "koparagcounter.h" 00024 #include "kozoomhandler.h" 00025 #include "kocommand.h" 00026 #include "kostyle.h" 00027 #include <klocale.h> 00028 #include <kdebug.h> 00029 #include "koFontDia.h" 00030 //#define DEBUG_FORMATS 00031 //#define DEBUG_FORMAT_MORE 00032 00033 const char KoTextObject::s_customItemChar = '#'; // Has to be transparent to kspell but still be saved (not space) 00034 00035 struct KoTextObject::KoTextObjectPrivate 00036 { 00037 public: 00038 KoTextObjectPrivate() { 00039 afterFormattingEmitted = false; 00040 abortFormatting = false; 00041 } 00042 bool afterFormattingEmitted; 00043 bool abortFormatting; 00044 }; 00045 00046 KoTextObject::KoTextObject( KoZoomHandler *zh, const QFont& defaultFont, const QString &defaultLanguage, bool hyphenation, double ulw, KoStyle* defaultStyle, int _tabStopWidth, 00047 QObject* parent, const char *name ) 00048 : QObject( parent, name ), m_defaultStyle( defaultStyle ), undoRedoInfo( this ) 00049 { 00050 textdoc = new KoTextDocument( zh, new KoTextFormatCollection( defaultFont, QColor(),defaultLanguage, hyphenation, ulw ) ); 00051 if ( _tabStopWidth != -1 ) 00052 textdoc->setTabStops( _tabStopWidth ); 00053 init(); 00054 } 00055 00056 KoTextObject::KoTextObject( KoTextDocument* _textdoc, KoStyle* defaultStyle, 00057 QObject* parent, const char *name ) 00058 : QObject( parent, name ), m_defaultStyle( defaultStyle ), undoRedoInfo( this ) 00059 { 00060 textdoc = _textdoc; 00061 init(); 00062 } 00063 00064 void KoTextObject::init() 00065 { 00066 d = new KoTextObjectPrivate; 00067 m_needsSpellCheck = true; 00068 m_protectContent = false; 00069 m_visible=true; 00070 m_availableHeight = -1; 00071 m_lastFormatted = textdoc->firstParag(); 00072 m_highlightSelectionAdded = false; 00073 interval = 0; 00074 changeIntervalTimer = new QTimer( this ); 00075 connect( changeIntervalTimer, SIGNAL( timeout() ), 00076 this, SLOT( doChangeInterval() ) ); 00077 00078 formatTimer = new QTimer( this ); 00079 connect( formatTimer, SIGNAL( timeout() ), 00080 this, SLOT( formatMore() ) ); 00081 00082 // Apply default style to initial paragraph 00083 if ( m_lastFormatted && m_defaultStyle ) 00084 m_lastFormatted->applyStyle( m_defaultStyle ); 00085 00086 connect( textdoc, SIGNAL( paragraphDeleted( KoTextParag* ) ), 00087 this, SIGNAL( paragraphDeleted( KoTextParag* ) ) ); 00088 connect( textdoc, SIGNAL( paragraphDeleted( KoTextParag* ) ), 00089 this, SLOT( slotParagraphDeleted( KoTextParag* ) ) ); 00090 connect( textdoc, SIGNAL( newCommand( KCommand* ) ), 00091 this, SIGNAL( newCommand( KCommand* ) ) ); 00092 connect( textdoc, SIGNAL( repaintChanged() ), 00093 this, SLOT( emitRepaintChanged() ) ); 00094 00095 connect( this, SIGNAL(paragraphModified( KoTextParag*, int, int , int ) ), 00096 this, SLOT(slotParagraphModified(KoTextParag *, int, int , int))); 00097 connect( this, SIGNAL(paragraphCreated( KoTextParag* )), 00098 this, SLOT(slotParagraphCreated(KoTextParag *))); 00099 00100 00101 } 00102 00103 KoTextObject::~KoTextObject() 00104 { 00105 // Avoid crash in KoTextString::clear -> accessing deleted format collection, 00106 // if ~UndoRedoInfo still has a string to clear. 00107 undoRedoInfo.clear(); 00108 delete textdoc; textdoc = 0; 00109 delete d; 00110 } 00111 00112 int KoTextObject::availableHeight() const 00113 { 00114 if ( m_availableHeight == -1 ) 00115 emit const_cast<KoTextObject *>(this)->availableHeightNeeded(); 00116 Q_ASSERT( m_availableHeight != -1 ); 00117 return m_availableHeight; 00118 } 00119 00120 void KoTextObject::slotParagraphModified(KoTextParag *parag, int /*ParagModifyType*/ _type, int , int) 00121 { 00122 if ( _type == ChangeFormat) 00123 return; 00124 m_needsSpellCheck = true; 00125 if (parag ) 00126 parag->string()->setNeedsSpellCheck( true ); 00127 } 00128 00129 void KoTextObject::slotParagraphCreated(KoTextParag * parag) 00130 { 00131 m_needsSpellCheck = true; 00132 if (parag ) 00133 parag->string()->setNeedsSpellCheck( true ); 00134 } 00135 00136 void KoTextObject::slotParagraphDeleted(KoTextParag * /*parag*/) 00137 { 00138 // ### TODO: remove from kwbgspellcheck 00139 } 00140 00141 int KoTextObject::docFontSize( KoTextFormat * format ) const 00142 { 00143 Q_ASSERT( format ); 00144 return format->pointSize(); 00145 } 00146 00147 int KoTextObject::zoomedFontSize( int docFontSize ) const 00148 { 00149 kdDebug(32500) << "KoTextObject::zoomedFontSize: docFontSize=" << docFontSize 00150 << " - in LU: " << KoTextZoomHandler::ptToLayoutUnitPt( docFontSize ) << endl; 00151 return KoTextZoomHandler::ptToLayoutUnitPt( docFontSize ); 00152 } 00153 00154 // A visitor that looks for custom items in e.g. a selection 00155 class KoHasCustomItemVisitor : public KoParagVisitor // see kotextdocument.h 00156 { 00157 public: 00158 KoHasCustomItemVisitor() : KoParagVisitor() { } 00159 // returns false when cancelled, i.e. an item was _found_, and true if it proceeded to the end(!) 00160 virtual bool visit( KoTextParag *parag, int start, int end ) 00161 { 00162 for ( int i = start ; i < end ; ++i ) 00163 { 00164 KoTextStringChar * ch = parag->at( i ); 00165 if ( ch->isCustom() ) 00166 return false; // found one -> stop here 00167 } 00168 return true; 00169 } 00170 }; 00171 00172 bool KoTextObject::selectionHasCustomItems( int selectionId ) const 00173 { 00174 KoHasCustomItemVisitor visitor; 00175 bool noneFound = textdoc->visitSelection( selectionId, &visitor ); 00176 return !noneFound; 00177 } 00178 00179 void KoTextObject::slotAfterUndoRedo() 00180 { 00181 formatMore( 2 ); 00182 emit repaintChanged( this ); 00183 emit updateUI( true ); 00184 emit showCursor(); 00185 emit ensureCursorVisible(); 00186 } 00187 00188 void KoTextObject::clearUndoRedoInfo() 00189 { 00190 undoRedoInfo.clear(); 00191 } 00192 00193 00194 void KoTextObject::checkUndoRedoInfo( KoTextCursor * cursor, UndoRedoInfo::Type t ) 00195 { 00196 if ( undoRedoInfo.valid() && ( t != undoRedoInfo.type || cursor != undoRedoInfo.cursor ) ) { 00197 undoRedoInfo.clear(); 00198 } 00199 undoRedoInfo.type = t; 00200 undoRedoInfo.cursor = cursor; 00201 } 00202 00203 void KoTextObject::undo() 00204 { 00205 undoRedoInfo.clear(); 00206 emit hideCursor(); 00207 KoTextCursor *cursor = new KoTextCursor( textdoc ); // Kindof a dummy cursor 00208 KoTextCursor *c = textdoc->undo( cursor ); 00209 if ( !c ) { 00210 delete cursor; 00211 emit showCursor(); 00212 return; 00213 } 00214 // We have to set this new cursor position in all views :( 00215 // It sucks a bit for useability, but otherwise one view might still have 00216 // a cursor inside a deleted paragraph -> crash. 00217 emit setCursor( c ); 00218 setLastFormattedParag( textdoc->firstParag() ); 00219 delete cursor; 00220 QTimer::singleShot( 0, this, SLOT( slotAfterUndoRedo() ) ); 00221 } 00222 00223 void KoTextObject::redo() 00224 { 00225 undoRedoInfo.clear(); 00226 emit hideCursor(); 00227 KoTextCursor *cursor = new KoTextCursor( textdoc ); // Kindof a dummy cursor 00228 KoTextCursor *c = textdoc->redo( cursor ); 00229 if ( !c ) { 00230 delete cursor; 00231 emit showCursor(); 00232 return; 00233 } 00234 emit setCursor( c ); // see undo 00235 setLastFormattedParag( textdoc->firstParag() ); 00236 delete cursor; 00237 QTimer::singleShot( 0, this, SLOT( slotAfterUndoRedo() ) ); 00238 } 00239 00240 KoTextObject::UndoRedoInfo::UndoRedoInfo( KoTextObject *to ) 00241 : type( Invalid ), textobj(to), cursor( 0 ) 00242 { 00243 text = QString::null; 00244 id = -1; 00245 index = -1; 00246 placeHolderCmd = 0L; 00247 } 00248 00249 bool KoTextObject::UndoRedoInfo::valid() const 00250 { 00251 return text.length() > 0 && id >= 0 && index >= 0; 00252 } 00253 00254 void KoTextObject::UndoRedoInfo::clear() 00255 { 00256 if ( valid() ) { 00257 KoTextDocument* textdoc = textobj->textDocument(); 00258 switch (type) { 00259 case Insert: 00260 case Return: 00261 { 00262 KoTextDocCommand * cmd = new KoTextInsertCommand( textdoc, id, index, text.rawData(), customItemsMap, oldParagLayouts ); 00263 textdoc->addCommand( cmd ); 00264 Q_ASSERT( placeHolderCmd ); 00265 // Inserting any custom items -> macro command, to let custom items add their command 00266 if ( !customItemsMap.isEmpty() ) 00267 { 00268 CustomItemsMap::Iterator it = customItemsMap.begin(); 00269 for ( ; it != customItemsMap.end(); ++it ) 00270 { 00271 KoTextCustomItem * item = it.data(); 00272 KCommand * itemCmd = item->createCommand(); 00273 if ( itemCmd ) 00274 placeHolderCmd->addCommand( itemCmd ); 00275 } 00276 placeHolderCmd->addCommand( new KoTextCommand( textobj, /*cmd, */QString::null ) ); 00277 } 00278 else 00279 { 00280 placeHolderCmd->addCommand( new KoTextCommand( textobj, /*cmd, */QString::null ) ); 00281 } 00282 } break; 00283 case Delete: 00284 case RemoveSelected: 00285 { 00286 KoTextDocCommand * cmd = textobj->deleteTextCommand( textdoc, id, index, text.rawData(), customItemsMap, oldParagLayouts ); 00287 textdoc->addCommand( cmd ); 00288 Q_ASSERT( placeHolderCmd ); 00289 placeHolderCmd->addCommand( new KoTextCommand( textobj, /*cmd, */QString::null ) ); 00290 // Deleting any custom items -> let them add their command 00291 if ( !customItemsMap.isEmpty() ) 00292 { 00293 customItemsMap.deleteAll( placeHolderCmd ); 00294 } 00295 } break; 00296 case Invalid: 00297 break; 00298 } 00299 } 00300 type = Invalid; 00301 // Before Qt-3.2.0, this called KoTextString::clear(), which called resize(0) on the array, which _detached_. Tricky. 00302 // Since Qt-3.2.0, resize(0) doesn't detach anymore -> KoTextDocDeleteCommand calls copy() itself. 00303 text = QString::null; 00304 id = -1; 00305 index = -1; 00306 oldParagLayouts.clear(); 00307 customItemsMap.clear(); 00308 placeHolderCmd = 0L; 00309 } 00310 00311 void KoTextObject::copyCharFormatting( KoTextParag *parag, int position, int index /*in text*/, bool moveCustomItems ) 00312 { 00313 KoTextStringChar * ch = parag->at( position ); 00314 if ( ch->format() ) { 00315 ch->format()->addRef(); 00316 undoRedoInfo.text.at( index ).setFormat( ch->format() ); 00317 } 00318 if ( ch->isCustom() ) 00319 { 00320 kdDebug(32500) << "KoTextObject::copyCharFormatting moving custom item " << ch->customItem() << " to text's " << index << " char" << endl; 00321 undoRedoInfo.customItemsMap.insert( index, ch->customItem() ); 00322 // We copy the custom item to customItemsMap in all cases (see setFormat) 00323 // We only remove from 'ch' if moveCustomItems was specified 00324 if ( moveCustomItems ) 00325 parag->removeCustomItem(position); 00326 //ch->loseCustomItem(); 00327 } 00328 } 00329 00330 // Based on QTextView::readFormats - with all code duplication moved to copyCharFormatting 00331 void KoTextObject::readFormats( KoTextCursor &c1, KoTextCursor &c2, bool copyParagLayouts, bool moveCustomItems ) 00332 { 00333 //kdDebug(32500) << "KoTextObject::readFormats moveCustomItems=" << moveCustomItems << endl; 00334 c2.restoreState(); 00335 c1.restoreState(); 00336 int oldLen = undoRedoInfo.text.length(); 00337 if ( c1.parag() == c2.parag() ) { 00338 undoRedoInfo.text += c1.parag()->string()->toString().mid( c1.index(), c2.index() - c1.index() ); 00339 for ( int i = c1.index(); i < c2.index(); ++i ) 00340 copyCharFormatting( c1.parag(), i, oldLen + i - c1.index(), moveCustomItems ); 00341 } else { 00342 int lastIndex = oldLen; 00343 int i; 00344 //kdDebug(32500) << "KoTextObject::readFormats copying from " << c1.index() << " to " << c1.parag()->length()-1 << " into lastIndex=" << lastIndex << endl; 00345 // Replace the trailing spaces with '\n'. That char carries the formatting for the trailing space. 00346 undoRedoInfo.text += c1.parag()->string()->toString().mid( c1.index(), c1.parag()->length() - 1 - c1.index() ) + '\n'; 00347 for ( i = c1.index(); i < c1.parag()->length(); ++i, ++lastIndex ) 00348 copyCharFormatting( c1.parag(), i, lastIndex, moveCustomItems ); 00349 //++lastIndex; // skip the '\n'. 00350 KoTextParag *p = c1.parag()->next(); 00351 while ( p && p != c2.parag() ) { 00352 undoRedoInfo.text += p->string()->toString().left( p->length() - 1 ) + '\n'; 00353 //kdDebug(32500) << "KoTextObject::readFormats (mid) copying from 0 to " << p->length()-1 << " into i+" << lastIndex << endl; 00354 for ( i = 0; i < p->length(); ++i ) 00355 copyCharFormatting( p, i, i + lastIndex, moveCustomItems ); 00356 lastIndex += p->length(); // + 1; // skip the '\n' 00357 //kdDebug(32500) << "KoTextObject::readFormats lastIndex now " << lastIndex << " - text is now " << undoRedoInfo.text.toString() << endl; 00358 p = p->next(); 00359 } 00360 //kdDebug(32500) << "KoTextObject::readFormats copying [last] from 0 to " << c2.index() << " into i+" << lastIndex << endl; 00361 undoRedoInfo.text += c2.parag()->string()->toString().left( c2.index() ); 00362 for ( i = 0; i < c2.index(); ++i ) 00363 copyCharFormatting( c2.parag(), i, i + lastIndex, moveCustomItems ); 00364 } 00365 00366 if ( copyParagLayouts ) { 00367 KoTextParag *p = c1.parag(); 00368 while ( p ) { 00369 undoRedoInfo.oldParagLayouts << p->paragLayout(); 00370 if ( p == c2.parag() ) 00371 break; 00372 p = p->next(); 00373 } 00374 } 00375 } 00376 00377 void KoTextObject::newPlaceHolderCommand( const QString & name ) 00378 { 00379 Q_ASSERT( !undoRedoInfo.placeHolderCmd ); 00380 if ( undoRedoInfo.placeHolderCmd ) kdDebug(32500) << kdBacktrace(); 00381 undoRedoInfo.placeHolderCmd = new KMacroCommand( name ); 00382 emit newCommand( undoRedoInfo.placeHolderCmd ); 00383 } 00384 00385 void KoTextObject::storeParagUndoRedoInfo( KoTextCursor * cursor, int selectionId ) 00386 { 00387 undoRedoInfo.clear(); 00388 undoRedoInfo.oldParagLayouts.clear(); 00389 undoRedoInfo.text = " "; 00390 undoRedoInfo.index = 1; 00391 if ( cursor && !textdoc->hasSelection( selectionId, true ) ) { 00392 KoTextParag * p = cursor->parag(); 00393 undoRedoInfo.id = p->paragId(); 00394 undoRedoInfo.eid = p->paragId(); 00395 undoRedoInfo.oldParagLayouts << p->paragLayout(); 00396 } 00397 else{ 00398 Q_ASSERT( textdoc->hasSelection( selectionId, true ) ); 00399 KoTextParag *start = textdoc->selectionStart( selectionId ); 00400 KoTextParag *end = textdoc->selectionEnd( selectionId ); 00401 undoRedoInfo.id = start->paragId(); 00402 undoRedoInfo.eid = end->paragId(); 00403 for ( ; start && start != end->next() ; start = start->next() ) 00404 { 00405 undoRedoInfo.oldParagLayouts << start->paragLayout(); 00406 //kdDebug(32500) << "KoTextObject:storeParagUndoRedoInfo storing counter " << start->paragLayout().counter.counterType << endl; 00407 } 00408 } 00409 } 00410 00411 void KoTextObject::doKeyboardAction( KoTextCursor * cursor, KoTextFormat * & /*currentFormat*/, KeyboardAction action ) 00412 { 00413 KoTextParag * parag = cursor->parag(); 00414 setLastFormattedParag( parag ); 00415 emit hideCursor(); 00416 bool doUpdateCurrentFormat = true; 00417 switch ( action ) { 00418 case ActionDelete: { 00419 checkUndoRedoInfo( cursor, UndoRedoInfo::Delete ); 00420 if ( !undoRedoInfo.valid() ) { 00421 newPlaceHolderCommand( i18n("Delete Text") ); 00422 undoRedoInfo.id = parag->paragId(); 00423 undoRedoInfo.index = cursor->index(); 00424 undoRedoInfo.text = QString::null; 00425 undoRedoInfo.oldParagLayouts << parag->paragLayout(); 00426 } 00427 if ( !cursor->atParagEnd() ) 00428 { 00429 KoTextStringChar * ch = parag->at( cursor->index() ); 00430 undoRedoInfo.text += ch->c; 00431 copyCharFormatting( parag, cursor->index(), undoRedoInfo.text.length()-1, true ); 00432 } 00433 KoParagLayout paragLayout; 00434 if ( parag->next() ) 00435 paragLayout = parag->next()->paragLayout(); 00436 00437 KoTextParag *old = cursor->parag(); 00438 if ( cursor->remove() ) { 00439 if ( old != cursor->parag() && m_lastFormatted == old ) // 'old' has been deleted 00440 m_lastFormatted = cursor->parag() ? cursor->parag()->prev() : 0; 00441 undoRedoInfo.text += "\n"; 00442 undoRedoInfo.oldParagLayouts << paragLayout; 00443 } else 00444 emit paragraphModified( old, RemoveChar, cursor->index(), 1 ); 00445 } break; 00446 case ActionBackspace: { 00447 // Remove counter 00448 if ( parag->counter() && parag->counter()->style() != KoParagCounter::STYLE_NONE && cursor->index() == 0 ) { 00449 // parag->decDepth(); // We don't have support for nested lists at the moment 00450 // (only in titles, but you don't want Backspace to move it up) 00451 KoParagCounter c; 00452 KCommand *cmd=setCounterCommand( cursor, c ); 00453 if(cmd) 00454 emit newCommand(cmd); 00455 } 00456 else if ( !cursor->atParagStart() ) 00457 { 00458 checkUndoRedoInfo( cursor, UndoRedoInfo::Delete ); 00459 if ( !undoRedoInfo.valid() ) { 00460 newPlaceHolderCommand( i18n("Delete Text") ); 00461 undoRedoInfo.id = parag->paragId(); 00462 undoRedoInfo.index = cursor->index(); 00463 undoRedoInfo.text = QString::null; 00464 undoRedoInfo.oldParagLayouts << parag->paragLayout(); 00465 } 00466 undoRedoInfo.text.insert( 0, cursor->parag()->at( cursor->index()-1 ) ); 00467 copyCharFormatting( cursor->parag(), cursor->index()-1, 0, true ); 00468 undoRedoInfo.index = cursor->index()-1; 00469 //KoParagLayout paragLayout = cursor->parag()->paragLayout(); 00470 cursor->removePreviousChar(); 00471 emit paragraphModified( cursor->parag(), RemoveChar, cursor->index(),1 ); 00472 m_lastFormatted = cursor->parag(); 00473 } else if ( parag->prev() ) { // joining paragraphs 00474 emit paragraphDeleted( cursor->parag() ); 00475 clearUndoRedoInfo(); 00476 textdoc->setSelectionStart( KoTextDocument::Temp, cursor ); 00477 cursor->gotoPreviousLetter(); 00478 textdoc->setSelectionEnd( KoTextDocument::Temp, cursor ); 00479 removeSelectedText( cursor, KoTextDocument::Temp, i18n( "Delete Text" ) ); 00480 emit paragraphModified( cursor->parag(), AddChar, cursor->index(), cursor->parag()->length() - cursor->index() ); 00481 } 00482 } break; 00483 case ActionReturn: { 00484 checkUndoRedoInfo( cursor, UndoRedoInfo::Return ); 00485 if ( !undoRedoInfo.valid() ) { 00486 newPlaceHolderCommand( i18n("Insert Text") ); 00487 undoRedoInfo.id = cursor->parag()->paragId(); 00488 undoRedoInfo.index = cursor->index(); 00489 undoRedoInfo.text = QString::null; 00490 } 00491 undoRedoInfo.text += "\n"; 00492 cursor->splitAndInsertEmptyParag(); 00493 Q_ASSERT( cursor->parag()->prev() ); 00494 if ( cursor->parag()->prev() ) 00495 setLastFormattedParag( cursor->parag()->prev() ); 00496 00497 doUpdateCurrentFormat = false; 00498 KoStyle * style = cursor->parag()->prev()->style(); 00499 if ( style ) 00500 { 00501 KoStyle * newStyle = style->followingStyle(); 00502 if ( newStyle && style != newStyle ) // different "following style" applied 00503 { 00504 doUpdateCurrentFormat = true; 00505 //currentFormat = textdoc->formatCollection()->format( cursor->parag()->paragFormat() ); 00506 //kdDebug(32500) << "KoTextFrameSet::doKeyboardAction currentFormat=" << currentFormat << " " << currentFormat->key() << endl; 00507 } 00508 } 00509 emit paragraphCreated( cursor->parag() ); 00510 00511 } break; 00512 case ActionKill: 00513 // Nothing to kill if at end of very last paragraph 00514 if ( !cursor->atParagEnd() || cursor->parag()->next() ) { 00515 checkUndoRedoInfo( cursor, UndoRedoInfo::Delete ); 00516 if ( !undoRedoInfo.valid() ) { 00517 newPlaceHolderCommand( i18n("Delete Text") ); 00518 undoRedoInfo.id = cursor->parag()->paragId(); 00519 undoRedoInfo.index = cursor->index(); 00520 undoRedoInfo.text = QString::null; 00521 undoRedoInfo.oldParagLayouts << parag->paragLayout(); 00522 } 00523 if ( cursor->atParagEnd() ) { 00524 // Get paraglayout from next parag (next can't be 0 here) 00525 KoParagLayout paragLayout = parag->next()->paragLayout(); 00526 if ( cursor->remove() ) 00527 { 00528 m_lastFormatted = cursor->parag(); 00529 undoRedoInfo.text += "\n"; 00530 undoRedoInfo.oldParagLayouts << paragLayout; 00531 } 00532 } else { 00533 int oldLen = undoRedoInfo.text.length(); 00534 undoRedoInfo.text += cursor->parag()->string()->toString().mid( cursor->index() ); 00535 for ( int i = cursor->index(); i < cursor->parag()->length(); ++i ) 00536 copyCharFormatting( cursor->parag(), i, oldLen + i - cursor->index(), true ); 00537 cursor->killLine(); 00538 emit paragraphModified( cursor->parag(), RemoveChar, cursor->index(), cursor->parag()->length()-cursor->index() ); 00539 } 00540 } 00541 break; 00542 } 00543 00544 if ( !undoRedoInfo.customItemsMap.isEmpty() ) 00545 clearUndoRedoInfo(); 00546 00547 formatMore( 2 ); 00548 emit repaintChanged( this ); 00549 emit ensureCursorVisible(); 00550 emit showCursor(); 00551 emit updateUI( doUpdateCurrentFormat ); 00552 } 00553 00554 void KoTextObject::insert( KoTextCursor * cursor, KoTextFormat * currentFormat, 00555 const QString &txt, bool checkNewLine, 00556 bool removeSelected, const QString & commandName, 00557 CustomItemsMap customItemsMap, int selectionId, bool repaint ) 00558 { 00559 if ( protectContent() ) 00560 return; 00561 //kdDebug(32500) << "KoTextObject::insert txt=" << txt << endl; 00562 bool tinyRepaint = !checkNewLine; 00563 if ( repaint ) 00564 emit hideCursor(); 00565 if ( textdoc->hasSelection( selectionId, true ) && removeSelected ) { 00566 if( customItemsMap.isEmpty()) 00567 { 00568 emitNewCommand(replaceSelectionCommand( cursor, txt, selectionId, commandName, repaint )); 00569 return; 00570 } 00571 else 00572 { 00573 KCommand* removeSelCmd = removeSelectedTextCommand( cursor, selectionId ); 00574 if (removeSelCmd) 00575 emitNewCommand( removeSelCmd ); 00576 tinyRepaint = false; 00577 } 00578 } 00579 KoTextCursor c2 = *cursor; 00580 if ( !customItemsMap.isEmpty() ) 00581 clearUndoRedoInfo(); 00582 checkUndoRedoInfo( cursor, UndoRedoInfo::Insert ); 00583 if ( !undoRedoInfo.valid() ) { 00584 if ( !commandName.isNull() ) // see replace-selection 00585 newPlaceHolderCommand( commandName ); 00586 undoRedoInfo.id = cursor->parag()->paragId(); 00587 undoRedoInfo.index = cursor->index(); 00588 undoRedoInfo.text = QString::null; 00589 } 00590 int oldLen = undoRedoInfo.text.length(); 00591 KoTextCursor oldCursor = *cursor; 00592 bool wasChanged = cursor->parag()->hasChanged(); 00593 int origLine; // the line the cursor was on before the insert 00594 oldCursor.parag()->lineStartOfChar( oldCursor.index(), 0, &origLine ); 00595 00596 cursor->insert( txt, checkNewLine ); // insert the text 00597 setLastFormattedParag( checkNewLine ? oldCursor.parag() : cursor->parag() ); 00598 00599 if ( !customItemsMap.isEmpty() ) { 00600 customItemsMap.insertItems( oldCursor, txt.length() ); 00601 undoRedoInfo.customItemsMap = customItemsMap; 00602 tinyRepaint = false; 00603 } 00604 00605 textdoc->setSelectionStart( KoTextDocument::Temp, &oldCursor ); 00606 textdoc->setSelectionEnd( KoTextDocument::Temp, cursor ); 00607 //kdDebug(32500) << "KoTextObject::insert setting format " << currentFormat << endl; 00608 textdoc->setFormat( KoTextDocument::Temp, currentFormat, KoTextFormat::Format ); 00609 textdoc->removeSelection( KoTextDocument::Temp ); 00610 00611 // Speed optimization: if we only type a char, and it doesn't 00612 // invalidate the next parag, only format the current one 00613 // ### This idea is wrong. E.g. when the last parag grows and must create a new page. 00614 #if 0 00615 KoTextParag *parag = cursor->parag(); 00616 if ( !checkNewLine && m_lastFormatted == parag && ( !parag->next() || parag->next()->isValid() ) ) 00617 { 00618 parag->format(); 00619 m_lastFormatted = m_lastFormatted->next(); 00620 } 00621 #endif 00622 // Call formatMore until necessary. This will create new pages if needed. 00623 // Doing this here means callers don't have to do it, and cursor can be positionned correctly. 00624 ensureFormatted( cursor->parag() ); 00625 00626 // Speed optimization: if we only type a char, only repaint from current line 00627 // (In fact the one before. When typing a space, a word could move up to the 00628 // line before, we need to repaint it too...) 00629 if ( !checkNewLine && tinyRepaint && !wasChanged ) 00630 { 00631 // insert() called format() which called setChanged(). 00632 // We're reverting that, and calling setLineChanged() only. 00633 Q_ASSERT( cursor->parag() == oldCursor.parag() ); // no newline! 00634 KoTextParag* parag = cursor->parag(); 00635 // If the new char led to a new line, 00636 // the wordwrap could have changed on the line above 00637 // This is why we use origLine and not calling lineStartOfChar here. 00638 parag->setChanged( false ); 00639 parag->setLineChanged( origLine - 1 ); // if origLine=0, it'll pass -1, which is 'all' 00640 } 00641 00642 if ( repaint ) { 00643 emit repaintChanged( this ); 00644 emit ensureCursorVisible(); 00645 emit showCursor(); 00646 // we typed the first char of a paragraph in AlignAuto mode -> show correct alignment in UI 00647 if ( oldCursor.index() == 0 && oldCursor.parag()->alignment() == Qt::AlignAuto ) 00648 emit updateUI( true ); 00649 00650 } 00651 undoRedoInfo.text += txt; 00652 for ( int i = 0; i < (int)txt.length(); ++i ) { 00653 if ( txt[ oldLen + i ] != '\n' ) 00654 copyCharFormatting( c2.parag(), c2.index(), oldLen + i, false ); 00655 c2.gotoNextLetter(); 00656 } 00657 00658 if ( !removeSelected ) { 00659 // ## not sure why we do this. I'd prefer leaving the selection unchanged... 00660 // but then it'd need adjustements in the offsets etc. 00661 if ( textdoc->removeSelection( selectionId ) && repaint ) 00662 selectionChangedNotify(); // does the repaint 00663 } 00664 if ( !customItemsMap.isEmpty() ) 00665 clearUndoRedoInfo(); 00666 00667 // Notifications 00668 emit paragraphModified( oldCursor.parag(), AddChar, cursor->index(), txt.length() ); 00669 // TODO 00670 // if (checkNewLine) 00671 // emit paragraphCreated for every paragraph from oldCursor->parag()->next() until cursor->parag() 00672 } 00673 00674 void KoTextObject::pasteText( KoTextCursor * cursor, const QString & text, KoTextFormat * currentFormat, bool removeSelected ) 00675 { 00676 if ( protectContent() ) 00677 return; 00678 kdDebug(32500) << "KoTextObject::pasteText cursor parag=" << cursor->parag()->paragId() << endl; 00679 QString t = text; 00680 // Need to convert CRLF to NL 00681 QRegExp crlf( QString::fromLatin1("\r\n") ); 00682 t.replace( crlf, QChar('\n') ); 00683 // Convert non-printable chars 00684 for ( int i=0; (uint) i<t.length(); i++ ) { 00685 if ( t[ i ] < ' ' && t[ i ] != '\n' && t[ i ] != '\t' ) 00686 t[ i ] = ' '; 00687 } 00688 if ( !t.isEmpty() ) 00689 { 00690 insert( cursor, currentFormat, t, true /*checkNewLine*/, removeSelected, i18n("Paste Text") ); 00691 formatMore( 2 ); 00692 emit repaintChanged( this ); 00693 } 00694 } 00695 00696 00697 void KoTextObject::applyStyle( KoTextCursor * cursor, const KoStyle * newStyle, 00698 int selectionId, 00699 int paragLayoutFlags, int formatFlags, 00700 bool createUndoRedo, bool interactive ) 00701 { 00702 KCommand *cmd = applyStyleCommand( cursor, newStyle, selectionId, 00703 paragLayoutFlags, formatFlags, 00704 createUndoRedo, interactive ); 00705 if ( createUndoRedo && cmd ) 00706 emit newCommand( cmd ); 00707 else 00708 Q_ASSERT( !cmd ); // mem leak, if applyStyleCommand created a command despite createUndoRedo==false! 00709 } 00710 00711 KCommand *KoTextObject::applyStyleCommand( KoTextCursor * cursor, const KoStyle * newStyle, 00712 int selectionId, 00713 int paragLayoutFlags, int formatFlags, 00714 bool createUndoRedo, bool interactive ) 00715 { 00716 if ( protectContent()) 00717 return 0L; 00718 if ( interactive ) 00719 emit hideCursor(); 00720 if ( !textdoc->hasSelection( selectionId, true ) && !cursor) 00721 return 0L; 00727 KMacroCommand * macroCmd = createUndoRedo ? new KMacroCommand( i18n("Apply Style %1"). 00728 arg(newStyle->translatedName() ) ) : 0; 00729 00730 // 1 00731 //kdDebug(32500) << "KoTextObject::applyStyle setParagLayout" << endl; 00732 storeParagUndoRedoInfo( cursor, selectionId ); 00733 undoRedoInfo.type = UndoRedoInfo::Invalid; // tricky, we don't want clear() to create a command 00734 if ( paragLayoutFlags != 0 ) 00735 { 00736 if ( !textdoc->hasSelection( selectionId, true ) ) { 00737 cursor->parag()->setParagLayout( newStyle->paragLayout(), paragLayoutFlags ); 00738 } else { 00739 KoTextParag *start = textdoc->selectionStart( selectionId ); 00740 KoTextParag *end = textdoc->selectionEnd( selectionId ); 00741 for ( ; start && start != end->next() ; start = start->next() ) 00742 start->setParagLayout( newStyle->paragLayout(), paragLayoutFlags ); 00743 } 00744 00745 if ( createUndoRedo ) 00746 { 00747 //kdDebug(32500) << "KoTextObject::applyStyle KoTextParagCommand" << endl; 00748 KoTextDocCommand * cmd = new KoTextParagCommand( textdoc, undoRedoInfo.id, undoRedoInfo.eid, 00749 undoRedoInfo.oldParagLayouts, 00750 newStyle->paragLayout(), paragLayoutFlags ); 00751 textdoc->addCommand( cmd ); 00752 macroCmd->addCommand( new KoTextCommand( this, /*cmd, */"related to KoTextParagCommand" ) ); 00753 } 00754 } 00755 00756 // 2 00757 //kdDebug(32500) << "KoTextObject::applyStyle gathering text and formatting" << endl; 00758 KoTextParag * firstParag; 00759 KoTextParag * lastParag; 00760 if ( !textdoc->hasSelection( selectionId, true ) ) { 00761 // No selection -> apply style formatting to the whole paragraph 00762 firstParag = cursor->parag(); 00763 lastParag = cursor->parag(); 00764 } 00765 else 00766 { 00767 firstParag = textdoc->selectionStart( selectionId ); 00768 lastParag = textdoc->selectionEnd( selectionId ); 00769 } 00770 00771 if ( formatFlags != 0 ) 00772 { 00773 KoTextFormat * newFormat = textdoc->formatCollection()->format( &newStyle->format() ); 00774 00775 if ( createUndoRedo ) 00776 { 00777 QValueList<KoTextFormat *> lstFormats; 00778 //QString str; 00779 for ( KoTextParag * parag = firstParag ; parag && parag != lastParag->next() ; parag = parag->next() ) 00780 { 00781 //str += parag->string()->toString() + '\n'; 00782 lstFormats.append( parag->paragFormat() ); 00783 } 00784 KoTextCursor c1( textdoc ); 00785 c1.setParag( firstParag ); 00786 c1.setIndex( 0 ); 00787 KoTextCursor c2( textdoc ); 00788 c2.setParag( lastParag ); 00789 c2.setIndex( lastParag->string()->length() ); 00790 undoRedoInfo.clear(); 00791 undoRedoInfo.type = UndoRedoInfo::Invalid; // same trick 00792 readFormats( c1, c2 ); // gather char-format info but not paraglayouts nor customitems 00793 00794 KoTextDocCommand * cmd = new KoTextFormatCommand( textdoc, firstParag->paragId(), 0, 00795 lastParag->paragId(), c2.index(), 00796 undoRedoInfo.text.rawData(), newFormat, 00797 formatFlags ); 00798 textdoc->addCommand( cmd ); 00799 macroCmd->addCommand( new KoTextCommand( this, /*cmd, */"related to KoTextFormatCommand" ) ); 00800 00801 // sub-command for '3' (paragFormat) 00802 cmd = new KoParagFormatCommand( textdoc, firstParag->paragId(), lastParag->paragId(), 00803 lstFormats, newFormat ); 00804 textdoc->addCommand( cmd ); 00805 macroCmd->addCommand( new KoTextCommand( this, /*cmd, */"related to KoParagFormatCommand" ) ); 00806 } 00807 00808 // apply '2' and '3' (format) 00809 for ( KoTextParag * parag = firstParag ; parag && parag != lastParag->next() ; parag = parag->next() ) 00810 { 00811 //kdDebug(32500) << "KoTextObject::applyStyle parag:" << parag->paragId() 00812 // << ", from 0 to " << parag->string()->length() << ", format=" << newFormat << endl; 00813 parag->setFormat( 0, parag->string()->length(), newFormat, true, formatFlags ); 00814 parag->setFormat( newFormat ); 00815 } 00816 //currentFormat = textdoc->formatCollection()->format( newFormat ); 00817 //kdDebug(32500) << "KoTextObject::applyStyle currentFormat=" << currentFormat << " " << currentFormat->key() << endl; 00818 } 00819 00820 //resize all variables after applying the style 00821 QPtrListIterator<KoTextCustomItem> cit( textdoc->allCustomItems() ); 00822 for ( ; cit.current() ; ++cit ) 00823 cit.current()->resize(); 00824 00825 00826 if ( interactive ) 00827 { 00828 setLastFormattedParag( firstParag ); 00829 formatMore( 2 ); 00830 emit repaintChanged( this ); 00831 emit updateUI( true ); 00832 emit showCursor(); 00833 } 00834 00835 undoRedoInfo.clear(); 00836 00837 return macroCmd; 00838 } 00839 00840 void KoTextObject::applyStyleChange( StyleChangeDefMap changed ) 00841 { 00842 /*kdDebug(32500) << "KoTextObject::applyStyleChange " << changedStyle->name() 00843 << " paragLayoutChanged=" << paragLayoutChanged 00844 << " formatChanged=" << formatChanged 00845 << endl;*/ 00846 00847 KoTextParag *p = textdoc->firstParag(); 00848 while ( p ) { 00849 StyleChangeDefMap::Iterator it = changed.find( p->style() ); 00850 if ( it != changed.end() ) 00851 { 00852 if ( (*it).paragLayoutChanged == -1 || (*it).formatChanged == -1 ) // Style has been deleted 00853 { 00854 p->setStyle( m_defaultStyle ); // keeps current formatting 00855 // TODO, make this undoable somehow 00856 } 00857 else 00858 { 00859 // Apply this style again, to get the changes 00860 KoTextCursor cursor( textdoc ); 00861 cursor.setParag( p ); 00862 cursor.setIndex( 0 ); 00863 //kdDebug(32500) << "KoTextObject::applyStyleChange applying to paragraph " << p << " " << p->paragId() << endl; 00864 #if 0 00865 KoStyle styleApplied=*style; 00866 if ( (m_doc->applyStyleChangeMask() & KWDocument::U_BORDER) == 0) 00867 { 00868 styleApplied.paragLayout().leftBorder=p->leftBorder(); 00869 styleApplied.paragLayout().rightBorder=p->rightBorder(); 00870 styleApplied.paragLayout().topBorder=p->topBorder(); 00871 styleApplied.paragLayout().bottomBorder=p->bottomBorder(); 00872 } 00873 if ( (m_doc->applyStyleChangeMask() & KWDocument::U_ALIGN )==0) 00874 { 00875 styleApplied.setAlign(p->alignment()); 00876 } 00877 if ( (m_doc->applyStyleChangeMask() & KWDocument::U_NUMBERING)==0 ) 00878 { 00879 styleApplied.paragLayout().counter=*(p->counter()); 00880 } 00881 if ( (m_doc->applyStyleChangeMask() & KWDocument::U_COLOR)==0 ) 00882 { 00883 styleApplied.format().setColor(p->paragFormat()->color()); 00884 } 00885 if ( (m_doc->applyStyleChangeMask() & KWDocument::U_TABS)==0 ) 00886 { 00887 styleApplied.paragLayout().setTabList(p->tabList()); 00888 } 00889 if ( (m_doc->applyStyleChangeMask() & KWDocument::U_INDENT)==0 ) 00890 { 00891 styleApplied.paragLayout().lineSpacing=p->kwLineSpacing(); 00892 styleApplied.paragLayout().margins[QStyleSheetItem::MarginLeft]=p->margin(QStyleSheetItem::MarginLeft); 00893 styleApplied.paragLayout().margins[QStyleSheetItem::MarginRight]=p->margin(QStyleSheetItem::MarginRight); 00894 styleApplied.paragLayout().margins[QStyleSheetItem::MarginFirstLine]=p->margin(QStyleSheetItem::MarginFirstLine); 00895 styleApplied.paragLayout().margins[QStyleSheetItem::MarginBottom]=p->margin(QStyleSheetItem::MarginBottom); 00896 styleApplied.paragLayout().margins[QStyleSheetItem::MarginTop]=p->margin(QStyleSheetItem::MarginTop); 00897 } 00898 #endif 00899 applyStyle( &cursor, it.key(), 00900 -1, // A selection we can't possibly have 00901 (*it).paragLayoutChanged, (*it).formatChanged, 00902 false, false ); // don't create undo/redo, not interactive 00903 } 00904 } 00905 p = p->next(); 00906 } 00907 setLastFormattedParag( textdoc->firstParag() ); 00908 formatMore( 2 ); 00909 emit repaintChanged( this ); 00910 emit updateUI( true ); 00911 } 00912 00914 KCommand *KoTextObject::setFormatCommand( const KoTextFormat *format, int flags, bool zoomFont ) 00915 { 00916 textdoc->selectAll( KoTextDocument::Temp ); 00917 KCommand *cmd = setFormatCommand( 0L, 0L, format, flags, zoomFont, KoTextDocument::Temp ); 00918 textdoc->removeSelection( KoTextDocument::Temp ); 00919 return cmd; 00920 } 00921 00922 KCommand * KoTextObject::setFormatCommand( KoTextCursor * cursor, KoTextFormat ** pCurrentFormat, const KoTextFormat *format, int flags, bool /*zoomFont*/, int selectionId ) 00923 { 00924 KCommand *ret = 0; 00925 if ( protectContent() ) 00926 return ret; 00927 00928 KoTextFormat* newFormat = 0; 00929 // Get new format from collection if 00930 // - caller has notion of a "current format" and new format is different 00931 // - caller has no notion of "current format", e.g. whole textobjects 00932 bool isNewFormat = ( pCurrentFormat && *pCurrentFormat && (*pCurrentFormat)->key() != format->key() ); 00933 if ( isNewFormat || !pCurrentFormat ) 00934 { 00935 #if 0 00936 int origFontSize = 0; 00937 if ( zoomFont ) // The format has a user-specified font (e.g. setting a style, or a new font size) 00938 { 00939 origFontSize = format->pointSize(); 00940 format->setPointSize( zoomedFontSize( origFontSize ) ); 00941 //kdDebug(32500) << "KoTextObject::setFormatCommand format " << format->key() << " zoomed from " << origFontSize << " to " << format->font().pointSizeFloat() << endl; 00942 } 00943 #endif 00944 // Remove ref to current format, if caller wanted that 00945 if ( pCurrentFormat ) 00946 (*pCurrentFormat)->removeRef(); 00947 // Find format in collection 00948 newFormat = textdoc->formatCollection()->format( format ); 00949 if ( newFormat->isMisspelled() ) { 00950 KoTextFormat fNoMisspelled( *newFormat ); 00951 newFormat->removeRef(); 00952 fNoMisspelled.setMisspelled( false ); 00953 newFormat = textdoc->formatCollection()->format( &fNoMisspelled ); 00954 } 00955 if ( pCurrentFormat ) 00956 (*pCurrentFormat) = newFormat; 00957 } 00958 00959 if ( textdoc->hasSelection( selectionId, true ) ) { 00960 emit hideCursor(); 00961 KoTextCursor c1 = textdoc->selectionStartCursor( selectionId ); 00962 KoTextCursor c2 = textdoc->selectionEndCursor( selectionId ); 00963 undoRedoInfo.clear(); 00964 int id = c1.parag()->paragId(); 00965 int index = c1.index(); 00966 int eid = c2.parag()->paragId(); 00967 int eindex = c2.index(); 00968 readFormats( c1, c2 ); // read previous formatting info 00969 //kdDebug(32500) << "KoTextObject::setFormatCommand undoredo info done" << endl; 00970 textdoc->setFormat( selectionId, format, flags ); 00971 if ( !undoRedoInfo.customItemsMap.isEmpty() ) 00972 { 00973 // Some custom items (e.g. variables) depend on the format 00974 CustomItemsMap::Iterator it = undoRedoInfo.customItemsMap.begin(); 00975 for ( ; it != undoRedoInfo.customItemsMap.end(); ++it ) 00976 it.data()->resize(); 00977 } 00978 KoTextFormatCommand *cmd = new KoTextFormatCommand( 00979 textdoc, id, index, eid, eindex, undoRedoInfo.text.rawData(), 00980 format, flags ); 00981 textdoc->addCommand( cmd ); 00982 ret = new KoTextCommand( this, /*cmd, */i18n("Format Text") ); 00983 undoRedoInfo.clear(); 00984 setLastFormattedParag( c1.parag() ); 00985 formatMore( 2 ); 00986 emit repaintChanged( this ); 00987 emit showCursor(); 00988 } 00989 if ( isNewFormat ) { 00990 emit showCurrentFormat(); 00991 //kdDebug(32500) << "KoTextObject::setFormatCommand index=" << cursor->index() << " length-1=" << cursor->parag()->length() - 1 << endl; 00992 if ( cursor && cursor->index() == cursor->parag()->length() - 1 ) { 00993 newFormat->addRef(); 00994 cursor->parag()->string()->setFormat( cursor->index(), newFormat, TRUE ); 00995 if ( cursor->parag()->length() == 1 ) { 00996 newFormat->addRef(); 00997 cursor->parag()->setFormat( newFormat ); 00998 cursor->parag()->invalidate(0); 00999 cursor->parag()->format(); 01000 emit repaintChanged( this ); 01001 } 01002 } 01003 } 01004 return ret; 01005 } 01006 01007 void KoTextObject::setFormat( KoTextCursor * cursor, KoTextFormat ** currentFormat, KoTextFormat *format, int flags, bool zoomFont ) 01008 { 01009 if ( protectContent() ) 01010 return; 01011 KCommand *cmd = setFormatCommand( cursor, currentFormat, format, flags, zoomFont ); 01012 if (cmd) 01013 emit newCommand( cmd ); 01014 } 01015 01016 void KoTextObject::emitNewCommand(KCommand *cmd) 01017 { 01018 if(cmd) 01019 emit newCommand( cmd ); 01020 } 01021 01022 KCommand *KoTextObject::setCounterCommand( KoTextCursor * cursor, const KoParagCounter & counter, int selectionId ) 01023 { 01024 if ( protectContent() ) 01025 return 0L; 01026 const KoParagCounter * curCounter = 0L; 01027 if(cursor) 01028 curCounter=cursor->parag()->counter(); 01029 if ( !textdoc->hasSelection( selectionId, true ) && 01030 curCounter && counter == *curCounter ) 01031 return 0L; 01032 emit hideCursor(); 01033 storeParagUndoRedoInfo( cursor, selectionId ); 01034 if ( !textdoc->hasSelection( selectionId, true ) && cursor) { 01035 cursor->parag()->setCounter( counter ); 01036 setLastFormattedParag( cursor->parag() ); 01037 } else { 01038 KoTextParag *start = textdoc->selectionStart( selectionId ); 01039 KoTextParag *end = textdoc->selectionEnd( selectionId ); 01040 #if 0 01041 // Special hack for BR25742, don't apply bullet to last empty parag of the selection 01042 if ( start != end && end->length() <= 1 ) 01043 { 01044 end = end->prev(); 01045 undoRedoInfo.eid = end->paragId(); 01046 } 01047 #endif 01048 setLastFormattedParag( start ); 01049 for ( ; start && start != end->next() ; start = start->next() ) 01050 { 01051 if ( start->length() > 1 ) // don't apply to empty paragraphs (#25742, #34062) 01052 start->setCounter( counter ); 01053 } 01054 } 01055 formatMore( 2 ); 01056 emit repaintChanged( this ); 01057 if ( !undoRedoInfo.newParagLayout.counter ) 01058 undoRedoInfo.newParagLayout.counter = new KoParagCounter; 01059 *undoRedoInfo.newParagLayout.counter = counter; 01060 KoTextParagCommand *cmd = new KoTextParagCommand( 01061 textdoc, undoRedoInfo.id, undoRedoInfo.eid, 01062 undoRedoInfo.oldParagLayouts, undoRedoInfo.newParagLayout, 01063 KoParagLayout::BulletNumber ); 01064 textdoc->addCommand( cmd ); 01065 01066 undoRedoInfo.clear(); // type is still Invalid -> no command created 01067 emit showCursor(); 01068 emit updateUI( true ); 01069 return new KoTextCommand( this, /*cmd, */i18n("Change List Type") ); 01070 } 01071 01072 KCommand * KoTextObject::setAlignCommand( KoTextCursor * cursor, int align, int selectionId ) 01073 { 01074 if ( protectContent() ) 01075 return 0L; 01076 if ( !textdoc->hasSelection( selectionId, true ) && cursor && 01077 (int)cursor->parag()->alignment() == align ) 01078 return 0L; // No change needed. 01079 01080 emit hideCursor(); 01081 storeParagUndoRedoInfo( cursor ,selectionId ); 01082 if ( !textdoc->hasSelection( selectionId, true ) &&cursor ) { 01083 cursor->parag()->setAlign(align); 01084 setLastFormattedParag( cursor->parag() ); 01085 } 01086 else 01087 { 01088 KoTextParag *start = textdoc->selectionStart( selectionId ); 01089 KoTextParag *end = textdoc->selectionEnd( selectionId ); 01090 setLastFormattedParag( start ); 01091 for ( ; start && start != end->next() ; start = start->next() ) 01092 start->setAlign(align); 01093 } 01094 formatMore( 2 ); 01095 emit repaintChanged( this ); 01096 undoRedoInfo.newParagLayout.alignment = align; 01097 KoTextParagCommand *cmd = new KoTextParagCommand( 01098 textdoc, undoRedoInfo.id, undoRedoInfo.eid, 01099 undoRedoInfo.oldParagLayouts, undoRedoInfo.newParagLayout, 01100 KoParagLayout::Alignment ); 01101 textdoc->addCommand( cmd ); 01102 undoRedoInfo.clear(); // type is still Invalid -> no command created 01103 emit showCursor(); 01104 emit updateUI( true ); 01105 return new KoTextCommand( this, /*cmd, */i18n("Change Alignment") ); 01106 } 01107 01108 KCommand * KoTextObject::setMarginCommand( KoTextCursor * cursor, QStyleSheetItem::Margin m, double margin , int selectionId ) { 01109 if ( protectContent() ) 01110 return 0L; 01111 01112 //kdDebug(32500) << "KoTextObject::setMargin " << m << " to value " << margin << endl; 01113 //kdDebug(32500) << "Current margin is " << cursor->parag()->margin(m) << endl; 01114 if ( !textdoc->hasSelection( selectionId, true ) && cursor && 01115 cursor->parag()->margin(m) == margin ) 01116 return 0L; // No change needed. 01117 01118 emit hideCursor(); 01119 storeParagUndoRedoInfo( cursor, selectionId ); 01120 if ( !textdoc->hasSelection( selectionId, true )&&cursor ) { 01121 cursor->parag()->setMargin(m, margin); 01122 setLastFormattedParag( cursor->parag() ); 01123 } 01124 else 01125 { 01126 KoTextParag *start = textdoc->selectionStart( selectionId ); 01127 KoTextParag *end = textdoc->selectionEnd( selectionId ); 01128 setLastFormattedParag( start ); 01129 for ( ; start && start != end->next() ; start = start->next() ) 01130 start->setMargin(m, margin); 01131 } 01132 formatMore( 2 ); 01133 emit repaintChanged( this ); 01134 undoRedoInfo.newParagLayout.margins[m] = margin; 01135 KoTextParagCommand *cmd = new KoTextParagCommand( 01136 textdoc, undoRedoInfo.id, undoRedoInfo.eid, 01137 undoRedoInfo.oldParagLayouts, undoRedoInfo.newParagLayout, 01138 KoParagLayout::Margins, m ); 01139 textdoc->addCommand( cmd ); 01140 QString name; 01141 if ( m == QStyleSheetItem::MarginFirstLine ) 01142 name = i18n("Change First Line Indent"); 01143 else if ( m == QStyleSheetItem::MarginLeft || m == QStyleSheetItem::MarginRight ) 01144 name = i18n("Change Indent"); 01145 else 01146 name = i18n("Change Paragraph Spacing"); 01147 undoRedoInfo.clear(); 01148 emit showCursor(); 01149 emit updateUI( true ); 01150 return new KoTextCommand( this, /*cmd, */name ); 01151 } 01152 01153 KCommand * KoTextObject::setLineSpacingCommand( KoTextCursor * cursor, double spacing, KoParagLayout::SpacingType _type, int selectionId ) 01154 { 01155 if ( protectContent() ) 01156 return 0L; 01157 //kdDebug(32500) << "KoTextObject::setLineSpacing to value " << spacing << endl; 01158 //kdDebug(32500) << "Current spacing is " << cursor->parag()->kwLineSpacing() << endl; 01159 //kdDebug(32500) << "Comparison says " << ( cursor->parag()->kwLineSpacing() == spacing ) << endl; 01160 //kdDebug(32500) << "hasSelection " << textdoc->hasSelection( selectionId ) << endl; 01161 if ( !textdoc->hasSelection( selectionId, true ) && cursor && 01162 cursor->parag()->kwLineSpacing() == spacing 01163 && cursor->parag()->kwLineSpacingType() == _type) 01164 return 0L; // No change needed. 01165 01166 emit hideCursor(); 01167 storeParagUndoRedoInfo( cursor, selectionId ); 01168 if ( !textdoc->hasSelection( selectionId, true ) && cursor ) { 01169 cursor->parag()->setLineSpacing(spacing); 01170 cursor->parag()->setLineSpacingType( _type); 01171 setLastFormattedParag( cursor->parag() ); 01172 } 01173 else 01174 { 01175 KoTextParag *start = textdoc->selectionStart( selectionId ); 01176 KoTextParag *end = textdoc->selectionEnd( selectionId ); 01177 setLastFormattedParag( start ); 01178 for ( ; start && start != end->next() ; start = start->next() ) 01179 { 01180 start->setLineSpacing(spacing); 01181 start->setLineSpacingType( _type); 01182 } 01183 } 01184 formatMore( 2 ); 01185 emit repaintChanged( this ); 01186 undoRedoInfo.newParagLayout.setLineSpacingValue( spacing ); 01187 undoRedoInfo.newParagLayout.lineSpacingType = _type; 01188 KoTextParagCommand *cmd = new KoTextParagCommand( 01189 textdoc, undoRedoInfo.id, undoRedoInfo.eid, 01190 undoRedoInfo.oldParagLayouts, undoRedoInfo.newParagLayout, 01191 KoParagLayout::LineSpacing ); 01192 textdoc->addCommand( cmd ); 01193 01194 undoRedoInfo.clear(); 01195 emit showCursor(); 01196 return new KoTextCommand( this, /*cmd, */i18n("Change Line Spacing") ); 01197 } 01198 01199 01200 KCommand * KoTextObject::setBordersCommand( KoTextCursor * cursor, const KoBorder& leftBorder, const KoBorder& rightBorder, const KoBorder& topBorder, const KoBorder& bottomBorder , int selectionId ) 01201 { 01202 if ( protectContent() ) 01203 return 0L; 01204 if ( !textdoc->hasSelection( selectionId, true ) && cursor && 01205 cursor->parag()->leftBorder() ==leftBorder && 01206 cursor->parag()->rightBorder() ==rightBorder && 01207 cursor->parag()->topBorder() ==topBorder && 01208 cursor->parag()->bottomBorder() ==bottomBorder ) 01209 return 0L; // No change needed. 01210 01211 emit hideCursor(); 01212 bool borderOutline = false; 01213 storeParagUndoRedoInfo( cursor, selectionId ); 01214 if ( !textdoc->hasSelection( selectionId, true ) ) { 01215 cursor->parag()->setLeftBorder(leftBorder); 01216 cursor->parag()->setRightBorder(rightBorder); 01217 cursor->parag()->setBottomBorder(bottomBorder); 01218 cursor->parag()->setTopBorder(topBorder); 01219 setLastFormattedParag( cursor->parag() ); 01220 } 01221 else 01222 { 01223 KoTextParag *start = textdoc->selectionStart( selectionId ); 01224 KoTextParag *end = textdoc->selectionEnd( selectionId ); 01225 setLastFormattedParag( start ); 01226 KoBorder tmpBorder; 01227 tmpBorder.setPenWidth(0); 01228 for ( ; start && start != end->next() ; start = start->next() ) 01229 { 01230 start->setLeftBorder(leftBorder); 01231 start->setRightBorder(rightBorder); 01232 //remove border 01233 start->setTopBorder(tmpBorder); 01234 start->setBottomBorder(tmpBorder); 01235 } 01236 end->setBottomBorder(bottomBorder); 01237 textdoc->selectionStart( selectionId )->setTopBorder(topBorder); 01238 borderOutline = true; 01239 } 01240 formatMore( 2 ); 01241 emit repaintChanged( this ); 01242 undoRedoInfo.newParagLayout.leftBorder=leftBorder; 01243 undoRedoInfo.newParagLayout.rightBorder=rightBorder; 01244 undoRedoInfo.newParagLayout.topBorder=topBorder; 01245 undoRedoInfo.newParagLayout.bottomBorder=bottomBorder; 01246 01247 KoTextParagCommand *cmd = new KoTextParagCommand( 01248 textdoc, undoRedoInfo.id, undoRedoInfo.eid, 01249 undoRedoInfo.oldParagLayouts, undoRedoInfo.newParagLayout, 01250 KoParagLayout::Borders, (QStyleSheetItem::Margin)-1, borderOutline); 01251 textdoc->addCommand( cmd ); 01252 01253 undoRedoInfo.clear(); 01254 emit showCursor(); 01255 emit updateUI( true ); 01256 return new KoTextCommand( this, /*cmd, */i18n("Change Borders") ); 01257 } 01258 01259 01260 KCommand * KoTextObject::setTabListCommand( KoTextCursor * cursor, const KoTabulatorList &tabList, int selectionId ) 01261 { 01262 if ( protectContent() ) 01263 return 0L; 01264 if ( !textdoc->hasSelection( selectionId, true ) && cursor && 01265 cursor->parag()->tabList() == tabList ) 01266 return 0L; // No change needed. 01267 01268 emit hideCursor(); 01269 storeParagUndoRedoInfo( cursor, selectionId ); 01270 01271 if ( !textdoc->hasSelection( selectionId, true ) && cursor ) { 01272 cursor->parag()->setTabList( tabList ); 01273 setLastFormattedParag( cursor->parag() ); 01274 } 01275 else 01276 { 01277 KoTextParag *start = textdoc->selectionStart( selectionId ); 01278 KoTextParag *end = textdoc->selectionEnd( selectionId ); 01279 setLastFormattedParag( start ); 01280 for ( ; start && start != end->next() ; start = start->next() ) 01281 start->setTabList( tabList ); 01282 } 01283 01284 formatMore( 2 ); 01285 emit repaintChanged( this ); 01286 undoRedoInfo.newParagLayout.setTabList( tabList ); 01287 KoTextParagCommand *cmd = new KoTextParagCommand( 01288 textdoc, undoRedoInfo.id, undoRedoInfo.eid, 01289 undoRedoInfo.oldParagLayouts, undoRedoInfo.newParagLayout, 01290 KoParagLayout::Tabulator); 01291 textdoc->addCommand( cmd ); 01292 undoRedoInfo.clear(); 01293 emit showCursor(); 01294 emit updateUI( true ); 01295 return new KoTextCommand( this, /*cmd, */i18n("Change Tabulator") ); 01296 } 01297 01298 KCommand * KoTextObject::setParagDirectionCommand( KoTextCursor * cursor, QChar::Direction d, int selectionId ) 01299 { 01300 if ( protectContent() ) 01301 return 0L; 01302 if ( !textdoc->hasSelection( selectionId, true ) && cursor && 01303 cursor->parag()->direction() == d ) 01304 return 0L; // No change needed. 01305 01306 emit hideCursor(); 01307 storeParagUndoRedoInfo( cursor, selectionId ); 01308 01309 if ( !textdoc->hasSelection( selectionId, true ) && cursor ) { 01310 cursor->parag()->setDirection( d ); 01311 setLastFormattedParag( cursor->parag() ); 01312 } 01313 else 01314 { 01315 KoTextParag *start = textdoc->selectionStart( selectionId ); 01316 KoTextParag *end = textdoc->selectionEnd( selectionId ); 01317 setLastFormattedParag( start ); 01318 for ( ; start && start != end->next() ; start = start->next() ) 01319 start->setDirection( d ); 01320 } 01321 01322 formatMore( 2 ); 01323 emit repaintChanged( this ); 01325 #if 0 01326 undoRedoInfo.newParagLayout.direction = d; 01327 KoTextParagCommand *cmd = new KoTextParagCommand( 01328 textdoc, undoRedoInfo.id, undoRedoInfo.eid, 01329 undoRedoInfo.oldParagLayouts, undoRedoInfo.newParagLayout, 01330 KoParagLayout::Shadow); 01331 textdoc->addCommand( cmd ); 01332 #endif 01333 undoRedoInfo.clear(); 01334 emit showCursor(); 01335 emit updateUI( true ); 01336 #if 0 01337 return new KoTextCommand( this, /*cmd, */i18n("Change Shadow") ); 01338 #else 01339 return 0L; 01340 #endif 01341 } 01342 01343 void KoTextObject::removeSelectedText( KoTextCursor * cursor, int selectionId, const QString & cmdName, bool createUndoRedo ) 01344 { 01345 if ( protectContent() ) 01346 return ; 01347 emit hideCursor(); 01348 if( createUndoRedo) 01349 { 01350 checkUndoRedoInfo( cursor, UndoRedoInfo::RemoveSelected ); 01351 if ( !undoRedoInfo.valid() ) { 01352 textdoc->selectionStart( selectionId, undoRedoInfo.id, undoRedoInfo.index ); 01353 undoRedoInfo.text = QString::null; 01354 newPlaceHolderCommand( cmdName.isNull() ? i18n("Remove Selected Text") : cmdName ); 01355 } 01356 } 01357 KoTextCursor c1 = textdoc->selectionStartCursor( selectionId ); 01358 KoTextCursor c2 = textdoc->selectionEndCursor( selectionId ); 01359 readFormats( c1, c2, true, true ); 01360 //kdDebug(32500) << "KoTextObject::removeSelectedText text=" << undoRedoInfo.text.toString() << endl; 01361 01362 textdoc->removeSelectedText( selectionId, cursor ); 01363 01364 setLastFormattedParag( cursor->parag() ); 01365 formatMore( 2 ); 01366 emit repaintChanged( this ); 01367 emit ensureCursorVisible(); 01368 emit updateUI( true ); 01369 emit showCursor(); 01370 if(selectionId==KoTextDocument::Standard) 01371 selectionChangedNotify(); 01372 if ( createUndoRedo) 01373 undoRedoInfo.clear(); 01374 } 01375 01376 KCommand * KoTextObject::removeSelectedTextCommand( KoTextCursor * cursor, int selectionId, bool repaint ) 01377 { 01378 if ( protectContent() ) 01379 return 0L; 01380 if ( !textdoc->hasSelection( selectionId, true ) ) 01381 return 0L; 01382 01383 undoRedoInfo.clear(); 01384 textdoc->selectionStart( selectionId, undoRedoInfo.id, undoRedoInfo.index ); 01385 Q_ASSERT( undoRedoInfo.id >= 0 ); 01386 01387 KoTextCursor c1 = textdoc->selectionStartCursor( selectionId ); 01388 KoTextCursor c2 = textdoc->selectionEndCursor( selectionId ); 01389 readFormats( c1, c2, true, true ); 01390 01391 textdoc->removeSelectedText( selectionId, cursor ); 01392 01393 KMacroCommand *macroCmd = new KMacroCommand( i18n("Remove Selected Text") ); 01394 01395 KoTextDocCommand *cmd = deleteTextCommand( textdoc, undoRedoInfo.id, undoRedoInfo.index, 01396 undoRedoInfo.text.rawData(), 01397 undoRedoInfo.customItemsMap, 01398 undoRedoInfo.oldParagLayouts ); 01399 textdoc->addCommand(cmd); 01400 macroCmd->addCommand(new KoTextCommand( this, /*cmd, */QString::null )); 01401 01402 if(!undoRedoInfo.customItemsMap.isEmpty()) 01403 undoRedoInfo.customItemsMap.deleteAll( macroCmd ); 01404 01405 undoRedoInfo.type = UndoRedoInfo::Invalid; // we don't want clear() to create a command 01406 undoRedoInfo.clear(); 01407 if ( repaint ) 01408 selectionChangedNotify(); 01409 return macroCmd; 01410 } 01411 01412 KCommand* KoTextObject::replaceSelectionCommand( KoTextCursor * cursor, const QString & replacement, 01413 int selectionId, const QString & cmdName, bool repaint ) 01414 { 01415 if ( protectContent() ) 01416 return 0L; 01417 if ( repaint ) 01418 emit hideCursor(); 01419 KMacroCommand * macroCmd = new KMacroCommand( cmdName ); 01420 01421 // Remember formatting 01422 KoTextCursor c1 = textdoc->selectionStartCursor( selectionId ); 01423 KoTextFormat * format = c1.parag()->at( c1.index() )->format(); 01424 format->addRef(); 01425 01426 // Remove selected text, if any 01427 KCommand* removeSelCmd = removeSelectedTextCommand( cursor, selectionId, repaint ); 01428 if ( removeSelCmd ) 01429 macroCmd->addCommand( removeSelCmd ); 01430 01431 // Insert replacement 01432 insert( cursor, format, 01433 replacement, true, false, QString::null /* no place holder command */, 01434 CustomItemsMap(), selectionId, repaint ); 01435 01436 KoTextDocCommand * cmd = new KoTextInsertCommand( textdoc, undoRedoInfo.id, undoRedoInfo.index, 01437 undoRedoInfo.text.rawData(), 01438 CustomItemsMap(), undoRedoInfo.oldParagLayouts ); 01439 textdoc->addCommand( cmd ); 01440 macroCmd->addCommand( new KoTextCommand( this, /*cmd, */QString::null ) ); 01441 01442 undoRedoInfo.type = UndoRedoInfo::Invalid; // we don't want clear() to create a command 01443 undoRedoInfo.clear(); 01444 01445 format->removeRef(); 01446 01447 setLastFormattedParag( c1.parag() ); 01448 if ( repaint ) // false during search/replace 01449 { 01450 formatMore( 2 ); 01451 emit repaintChanged( this ); 01452 emit ensureCursorVisible(); 01453 emit updateUI( true ); 01454 emit showCursor(); 01455 if(selectionId==KoTextDocument::Standard) 01456 selectionChangedNotify(); 01457 } 01458 return macroCmd; 01459 } 01460 01461 KCommand * KoTextObject::insertParagraphCommand( KoTextCursor *cursor ) 01462 { 01463 if ( protectContent() ) 01464 return 0L; 01465 return replaceSelectionCommand( cursor, "\n", KoTextDocument::Standard, QString::null ); 01466 } 01467 01468 void KoTextObject::highlightPortion( KoTextParag * parag, int index, int length, bool repaint ) 01469 { 01470 if ( !m_highlightSelectionAdded ) 01471 { 01472 textdoc->addSelection( HighlightSelection ); 01473 textdoc->setSelectionColor( HighlightSelection, 01474 QApplication::palette().color( QPalette::Active, QColorGroup::Dark ) ); 01475 textdoc->setInvertSelectionText( HighlightSelection, true ); 01476 m_highlightSelectionAdded = true; 01477 } 01478 01479 removeHighlight(repaint); // remove previous highlighted selection 01480 KoTextCursor cursor( textdoc ); 01481 cursor.setParag( parag ); 01482 cursor.setIndex( index ); 01483 textdoc->setSelectionStart( HighlightSelection, &cursor ); 01484 cursor.setIndex( index + length ); 01485 textdoc->setSelectionEnd( HighlightSelection, &cursor ); 01486 if ( repaint ) { 01487 parag->setChanged( true ); 01488 emit repaintChanged( this ); 01489 } 01490 } 01491 01492 void KoTextObject::removeHighlight(bool repaint) 01493 { 01494 if ( textdoc->hasSelection( HighlightSelection, true ) ) 01495 { 01496 KoTextParag * oldParag = textdoc->selectionStart( HighlightSelection ); 01497 oldParag->setChanged( true ); 01498 textdoc->removeSelection( HighlightSelection ); 01499 } 01500 if ( repaint ) 01501 emit repaintChanged( this ); 01502 } 01503 01504 void KoTextObject::selectAll( bool select ) 01505 { 01506 if ( !select ) 01507 textdoc->removeSelection( KoTextDocument::Standard ); 01508 else 01509 textdoc->selectAll( KoTextDocument::Standard ); 01510 selectionChangedNotify(); 01511 } 01512 01513 void KoTextObject::selectionChangedNotify( bool enableActions /* = true */) 01514 { 01515 emit repaintChanged( this ); 01516 if ( enableActions ) 01517 emit selectionChanged( hasSelection() ); 01518 } 01519 01520 void KoTextObject::setViewArea( QWidget* w, int maxY ) 01521 { 01522 m_mapViewAreas.replace( w, maxY ); 01523 } 01524 01525 void KoTextObject::setLastFormattedParag( KoTextParag *parag ) 01526 { 01527 if ( !m_lastFormatted || !parag || m_lastFormatted->paragId() >= parag->paragId() ) { 01528 m_lastFormatted = parag; 01529 } 01530 } 01531 01532 void KoTextObject::ensureFormatted( KoTextParag * parag, bool emitAfterFormatting /* = true */ ) 01533 { 01534 if ( !textdoc->lastParag() ) 01535 return; // safety test 01536 //kdDebug(32500) << name() << " ensureFormatted " << parag->paragId() << endl; 01537 if ( !parag->isValid() && m_lastFormatted == 0 ) 01538 m_lastFormatted = parag; // bootstrap 01539 01540 while ( !parag->isValid() ) 01541 { 01542 if ( !m_lastFormatted ) { 01543 kdWarning() << "ensureFormatted for parag " << parag << " " << parag->paragId() << " still not formatted, but m_lastFormatted==0" << endl; 01544 return; 01545 } 01546 // The paragid diff is "a good guess". The >=1 is a safety measure ;) 01547 bool ret = formatMore( QMAX( 1, parag->paragId() - m_lastFormatted->paragId() ), emitAfterFormatting ); 01548 if ( !ret ) { // aborted 01549 //kdDebug(32500) << "ensureFormatted aborted!" << endl; 01550 break; 01551 } 01552 } 01553 //kdDebug(32500) << name() << " ensureFormatted " << parag->paragId() << " done" << endl; 01554 } 01555 01556 bool KoTextObject::formatMore( int count /* = 10 */, bool emitAfterFormatting /* = true */ ) 01557 { 01558 if ( ( !m_lastFormatted && d->afterFormattingEmitted ) 01559 || !m_visible || m_availableHeight == -1 ) 01560 return false; 01561 01562 if ( !textdoc->lastParag() ) 01563 return false; // safety test 01564 01565 if ( d->abortFormatting ) { 01566 d->abortFormatting = false; 01567 return false; 01568 } 01569 01570 if ( count == 0 ) 01571 { 01572 formatTimer->start( interval, TRUE ); 01573 return true; 01574 } 01575 01576 int bottom = 0; 01577 if ( m_lastFormatted ) 01578 { 01579 d->afterFormattingEmitted = false; 01580 01581 int viewsBottom = 0; 01582 QMapIterator<QWidget *, int> mapIt = m_mapViewAreas.begin(); 01583 for ( ; mapIt != m_mapViewAreas.end() ; ++mapIt ) 01584 viewsBottom = QMAX( viewsBottom, mapIt.data() ); 01585 01586 #ifdef DEBUG_FORMAT_MORE 01587 kdDebug(32500) << "formatMore " << name() 01588 << " lastFormatted id=" << m_lastFormatted->paragId() 01589 << " lastFormatted's top=" << m_lastFormatted->rect().top() 01590 << " lastFormatted's height=" << m_lastFormatted->rect().height() 01591 << " count=" << count << " viewsBottom=" << viewsBottom 01592 << " availableHeight=" << m_availableHeight << endl; 01593 #endif 01594 if ( m_lastFormatted->prev() == 0 ) 01595 { 01596 emit formattingFirstParag(); 01597 #ifdef TIMING_FORMAT 01598 kdDebug(32500) << "formatMore " << name() << ". First parag -> starting timer" << endl; 01599 m_time.start(); 01600 #endif 01601 } 01602 01603 // Stop if we have formatted everything or if we need more space 01604 // Otherwise, stop formatting after "to" paragraphs, 01605 // but make sure we format everything the views need 01606 int i; 01607 for ( i = 0; 01608 m_lastFormatted && bottom + m_lastFormatted->rect().height() <= m_availableHeight && 01609 ( i < count || bottom <= viewsBottom ) ; ++i ) 01610 { 01611 KoTextParag* parag = m_lastFormatted; 01612 #ifdef DEBUG_FORMAT_MORE 01613 kdDebug(32500) << "formatMore formatting id=" << parag->paragId() << endl; 01614 #endif 01615 parag->format(); 01616 bottom = parag->rect().top() + parag->rect().height(); 01617 #if 0 //def DEBUG_FORMAT_MORE 01618 kdDebug(32500) << "formatMore(inside) top=" << parag->rect().top() 01619 << " height=" << parag->rect().height() 01620 << " bottom=" << bottom << " m_lastFormatted(next parag) = " << m_lastFormatted->next() << endl; 01621 #endif 01622 01623 // Check for Head 1 (i.e. section) titles, and emit them - for the Section variable 01624 if ( parag->counter() && parag->counter()->numbering() == KoParagCounter::NUM_CHAPTER 01625 && parag->counter()->depth() == 0 ) 01626 emit chapterParagraphFormatted( parag ); 01627 01628 if ( d->abortFormatting ) { 01629 #ifdef DEBUG_FORMAT_MORE 01630 kdDebug(32500) << "formatMore formatting aborted. " << endl; 01631 #endif 01632 d->abortFormatting = false; 01633 return false; 01634 } 01635 01636 if ( parag != m_lastFormatted ) 01637 kdWarning() << "Some code changed m_lastFormatted during formatting! Was " << parag->paragId() << ", is now " << m_lastFormatted->paragId() << endl; 01638 #if 0 // This happens now that formatting can 'abort' (e.g. due to page not yet created) 01639 else if (!parag->isValid()) 01640 kdWarning() << "PARAGRAPH " << parag->paragId() << " STILL INVALID AFTER FORMATTING" << endl; 01641 #endif 01642 m_lastFormatted = parag->next(); 01643 } 01644 } 01645 else // formatting was done previously, but not emit afterFormatting 01646 { 01647 QRect rect = textdoc->lastParag()->rect(); 01648 bottom = rect.top() + rect.height(); 01649 } 01650 #ifdef DEBUG_FORMAT_MORE 01651 QString id; 01652 if ( m_lastFormatted ) id = QString(" (%1)").arg(m_lastFormatted->paragId()); 01653 kdDebug(32500) << "formatMore finished formatting. " 01654 << " bottom=" << bottom 01655 << " m_lastFormatted=" << m_lastFormatted << id 01656 << endl; 01657 #endif 01658 01659 if ( emitAfterFormatting ) 01660 { 01661 d->afterFormattingEmitted = true; 01662 bool abort = false; 01663 // Check if we need more space - for proper default value of 'abort' 01664 if ( ( bottom > m_availableHeight ) || // this parag is already off page 01665 ( m_lastFormatted && bottom + m_lastFormatted->rect().height() > m_availableHeight ) ) // or next parag will be off page 01666 abort = true; 01667 emit afterFormatting( bottom, m_lastFormatted, &abort ); 01668 if ( abort ) 01669 return false; 01670 else if ( m_lastFormatted ) // we got more space, keep formatting then 01671 return formatMore( 2 ); 01672 } 01673 01674 // Now let's see when we'll need to get back here. 01675 if ( m_lastFormatted ) 01676 { 01677 formatTimer->start( interval, TRUE ); 01678 #ifdef DEBUG_FORMAT_MORE 01679 kdDebug(32500) << name() << " formatMore: will have to format more. formatTimer->start with interval=" << interval << endl; 01680 #endif 01681 } 01682 else 01683 { 01684 interval = QMAX( 0, interval ); 01685 #ifdef DEBUG_FORMAT_MORE 01686 kdDebug(32500) << name() << " formatMore: all formatted interval=" << interval << endl; 01687 #endif 01688 #ifdef TIMING_FORMAT 01689 //if ( frameSetInfo() == FI_BODY ) 01690 kdDebug(32500) << "formatMore: " << name() << " all formatted. Took " 01691 << (double)(m_time.elapsed()) / 1000 << " seconds." << endl; 01692 #endif 01693 } 01694 return true; 01695 } 01696 01697 void KoTextObject::abortFormatting() 01698 { 01699 d->abortFormatting = true; 01700 } 01701 01702 void KoTextObject::doChangeInterval() 01703 { 01704 //kdDebug(32500) << "KoTextObject::doChangeInterval back to interval=0" << endl; 01705 interval = 0; 01706 } 01707 01708 void KoTextObject::typingStarted() 01709 { 01710 //kdDebug(32500) << "KoTextObject::typingStarted" << endl; 01711 changeIntervalTimer->stop(); 01712 interval = 10; 01713 } 01714 01715 void KoTextObject::typingDone() 01716 { 01717 changeIntervalTimer->start( 100, TRUE ); 01718 } 01719 01720 01721 KCommand *KoTextObject::changeCaseOfTextParag(int cursorPosStart, int cursorPosEnd,KoChangeCaseDia::TypeOfCase _type,KoTextCursor *cursor, KoTextParag *parag) 01722 { 01723 if ( protectContent() ) 01724 return 0L; 01725 01726 KMacroCommand * macroCmd = new KMacroCommand( i18n("Change Case") ); 01727 KoTextFormat *curFormat = parag->paragraphFormat(); 01728 QString text = parag->string()->toString().mid(cursorPosStart , cursorPosEnd - cursorPosStart ); 01729 QString repl; 01730 int posStart=cursorPosStart; 01731 int posEnd=cursorPosStart; 01732 KoTextCursor c1( textdoc ); 01733 KoTextCursor c2( textdoc ); 01734 for ( int i = cursorPosStart; i < cursorPosEnd; ++i ) 01735 { 01736 KoTextStringChar & ch = *(parag->at(i)); 01737 KoTextFormat * newFormat = ch.format(); 01738 if( ch.isCustom()) 01739 { 01740 posEnd=i; 01741 c1.setParag(parag ); 01742 c1.setIndex( posStart ); 01743 c2.setParag( parag ); 01744 c2.setIndex( posEnd ); 01745 01746 repl=text.mid(posStart-cursorPosStart,posEnd-posStart); 01747 textdoc->setSelectionStart( KoTextDocument::Temp, &c1 ); 01748 textdoc->setSelectionEnd( KoTextDocument::Temp, &c2 ); 01749 macroCmd->addCommand(replaceSelectionCommand( 01750 cursor, textChangedCase(repl,_type), 01751 KoTextDocument::Temp, "" )); 01752 do 01753 { 01754 ++i; 01755 } 01756 while( parag->at(i)->isCustom() && i != cursorPosEnd); 01757 posStart=i; 01758 posEnd=i; 01759 } 01760 else 01761 { 01762 if ( newFormat != curFormat ) 01763 { 01764 posEnd=i; 01765 c1.setParag(parag ); 01766 c1.setIndex( posStart ); 01767 c2.setParag( parag ); 01768 c2.setIndex( posEnd ); 01769 01770 repl=text.mid(posStart-cursorPosStart,posEnd-posStart); 01771 textdoc->setSelectionStart( KoTextDocument::Temp, &c1 ); 01772 textdoc->setSelectionEnd( KoTextDocument::Temp, &c2 ); 01773 macroCmd->addCommand(replaceSelectionCommand( 01774 cursor, textChangedCase(repl,_type), 01775 KoTextDocument::Temp, "" )); 01776 posStart=i; 01777 posEnd=i; 01778 curFormat = newFormat; 01779 } 01780 } 01781 } 01782 //change last word 01783 c1.setParag(parag ); 01784 c1.setIndex( posStart ); 01785 c2.setParag(parag ); 01786 c2.setIndex( cursorPosEnd ); 01787 01788 textdoc->setSelectionStart( KoTextDocument::Temp, &c1 ); 01789 textdoc->setSelectionEnd( KoTextDocument::Temp, &c2 ); 01790 repl=text.mid(posStart-cursorPosStart,cursorPosEnd-posStart); 01791 macroCmd->addCommand(replaceSelectionCommand( 01792 cursor, textChangedCase(repl,_type), 01793 KoTextDocument::Temp, "" )); 01794 return macroCmd; 01795 01796 } 01797 01798 KCommand *KoTextObject::changeCaseOfText(KoTextCursor *cursor,KoChangeCaseDia::TypeOfCase _type) 01799 { 01800 if ( protectContent() ) 01801 return 0L; 01802 KMacroCommand * macroCmd = new KMacroCommand( i18n("Change Case") ); 01803 01804 KoTextCursor start = textdoc->selectionStartCursor( KoTextDocument::Standard ); 01805 KoTextCursor end = textdoc->selectionEndCursor( KoTextDocument::Standard ); 01806 01807 if ( start.parag() == end.parag() ) 01808 { 01809 macroCmd->addCommand(changeCaseOfTextParag(start.index(),end.index() , _type,cursor, start.parag() )); 01810 } 01811 else 01812 { 01813 macroCmd->addCommand(changeCaseOfTextParag(start.index(), start.parag()->length() - 1 - start.index(), _type,cursor, start.parag() )); 01814 KoTextParag *p = start.parag()->next(); 01815 while ( p && p != end.parag() ) 01816 { 01817 macroCmd->addCommand(changeCaseOfTextParag(0,p->length()-1 , _type,cursor, p )); 01818 p = p->next(); 01819 } 01820 macroCmd->addCommand(changeCaseOfTextParag(0,end.index() , _type,cursor, end.parag() )); 01821 } 01822 return macroCmd; 01823 } 01824 01825 QString KoTextObject::textChangedCase(const QString& _text,KoChangeCaseDia::TypeOfCase _type) 01826 { 01827 QString text(_text); 01828 switch(_type) 01829 { 01830 case KoChangeCaseDia::UpperCase: 01831 text=text.upper(); 01832 break; 01833 case KoChangeCaseDia::LowerCase: 01834 text=text.lower(); 01835 break; 01836 case KoChangeCaseDia::TitleCase: 01837 for(uint i=0;i<text.length();i++) 01838 { 01839 if(text.at(i)!=' ') 01840 { 01841 QChar prev = text.at(QMAX(i-1,0)); 01842 if(i==0 || prev == ' ' || prev == '\n' || prev == '\t') 01843 text=text.replace(i, 1, text.at(i).upper() ); 01844 else 01845 text=text.replace(i, 1, text.at(i).lower() ); 01846 } 01847 } 01848 break; 01849 case KoChangeCaseDia::ToggleCase: 01850 for(uint i=0;i<text.length();i++) 01851 { 01852 QString repl=QString(text.at(i)); 01853 if(text.at(i)!=text.at(i).upper()) 01854 repl=repl.upper(); 01855 else if(text.at(i).lower()!=text.at(i)) 01856 repl=repl.lower(); 01857 text=text.replace(i, 1, repl ); 01858 } 01859 break; 01860 case KoChangeCaseDia::SentenceCase: 01861 for(uint i=0;i<text.length();i++) 01862 { 01863 if(text.at(i)!=' ') 01864 { 01865 QChar prev = text.at(QMAX(i-1,0)); 01866 if(i==0 || prev == '\n' ||prev.isPunct()) 01867 text=text.replace(i, 1, text.at(i).upper() ); 01868 } 01869 } 01870 break; 01871 default: 01872 kdDebug(32500)<<"Error in changeCaseOfText !\n"; 01873 break; 01874 01875 } 01876 return text; 01877 } 01878 01879 // Warning, this doesn't ref the format! 01880 KoTextFormat * KoTextObject::currentFormat() const 01881 { 01882 // We use the formatting of the very first character 01883 // Should we use a style instead, maybe ? 01884 KoTextStringChar *ch = textdoc->firstParag()->at( 0 ); 01885 return ch->format(); 01886 } 01887 01888 const KoParagLayout * KoTextObject::currentParagLayoutFormat() const 01889 { 01890 KoTextParag * parag = textdoc->firstParag(); 01891 return &(parag->paragLayout()); 01892 } 01893 01894 bool KoTextObject::rtl() const 01895 { 01896 return textdoc->firstParag()->string()->isRightToLeft(); 01897 } 01898 01899 KCommand *KoTextObject::setParagLayoutFormatCommand( KoParagLayout *newLayout,int flags,int marginIndex) 01900 { 01901 if ( protectContent() ) 01902 return 0L; 01903 textdoc->selectAll( KoTextDocument::Temp ); 01904 KoTextCursor *cursor = new KoTextCursor( textdoc ); 01905 KCommand* cmd = setParagLayoutFormatCommand( cursor, KoTextDocument::Temp, newLayout, flags, marginIndex ); 01906 textdoc->removeSelection( KoTextDocument::Temp ); 01907 delete cursor; 01908 return cmd; 01909 } 01910 01911 KCommand *KoTextObject::setParagLayoutFormatCommand( KoTextCursor* cursor, int selectionId, KoParagLayout *newLayout, int flags, int marginIndex) 01912 { 01913 if ( protectContent() ) 01914 return 0L; 01915 KCommand *cmd =0L; 01916 KoParagCounter c; 01917 if(newLayout->counter) 01918 c=*newLayout->counter; 01919 switch(flags) 01920 { 01921 case KoParagLayout::Alignment: 01922 cmd = setAlignCommand( cursor, newLayout->alignment, selectionId ); 01923 break; 01924 case KoParagLayout::Margins: 01925 cmd = setMarginCommand( cursor, (QStyleSheetItem::Margin)marginIndex, newLayout->margins[marginIndex], selectionId ); 01926 break; 01927 case KoParagLayout::Tabulator: 01928 cmd = setTabListCommand( cursor, newLayout->tabList(), selectionId ); 01929 break; 01930 case KoParagLayout::BulletNumber: 01931 cmd = setCounterCommand( cursor, c, selectionId ); 01932 break; 01933 default: 01934 break; 01935 } 01936 return cmd; 01937 } 01938 01939 void KoTextObject::setFormat( KoTextFormat * newFormat, int flags, bool zoomFont ) 01940 { 01941 if ( protectContent() ) 01942 return ; 01943 // This version of setFormat works on the whole textobject - we use the Temp selection for that 01944 textdoc->selectAll( KoTextDocument::Temp ); 01945 KCommand *cmd = setFormatCommand( 0L, 0L, newFormat, 01946 flags, zoomFont, KoTextDocument::Temp ); 01947 textdoc->removeSelection( KoTextDocument::Temp ); 01948 if (cmd) 01949 emit newCommand( cmd ); 01950 01951 KoTextFormat format = *currentFormat(); 01952 //format.setPointSize( docFontSize( currentFormat() ) ); // "unzoom" the font size 01953 emit showFormatObject(format); 01954 } 01955 01956 KCommand *KoTextObject::setChangeCaseOfTextCommand(KoChangeCaseDia::TypeOfCase _type) 01957 { 01958 if ( protectContent() ) 01959 return 0L; 01960 textdoc->selectAll( KoTextDocument::Standard ); 01961 KoTextCursor *cursor = new KoTextCursor( textdoc ); 01962 KCommand* cmd = changeCaseOfText(cursor, _type); 01963 textdoc->removeSelection( KoTextDocument::Standard ); 01964 delete cursor; 01965 return cmd; 01966 } 01967 01968 void KoTextObject::setNeedSpellCheck(bool b) 01969 { 01970 m_needsSpellCheck = b; 01971 for (KoTextParag * parag = textdoc->firstParag(); parag ; parag = parag->next()) 01972 parag->string()->setNeedsSpellCheck( b ); 01973 } 01974 01975 #ifndef NDEBUG 01976 void KoTextObject::printRTDebug(int info) 01977 { 01978 for (KoTextParag * parag = textdoc->firstParag(); parag ; parag = parag->next()) 01979 { 01980 parag->printRTDebug( info ); 01981 } 01982 if ( info == 1 ) 01983 textdoc->formatCollection()->debug(); 01984 } 01985 #endif 01986 01988 01989 KCommand *KoTextFormatInterface::setBoldCommand(bool on) 01990 { 01991 KoTextFormat format( *currentFormat() ); 01992 format.setBold( on ); 01993 return setFormatCommand( &format, KoTextFormat::Bold ); 01994 } 01995 01996 KCommand *KoTextFormatInterface::setItalicCommand( bool on) 01997 { 01998 KoTextFormat format( *currentFormat() ); 01999 format.setItalic( on ); 02000 return setFormatCommand( &format, KoTextFormat::Italic ); 02001 } 02002 02003 KCommand *KoTextFormatInterface::setUnderlineCommand( bool on ) 02004 { 02005 KoTextFormat format( *currentFormat() ); 02006 format.setUnderlineType( on ? KoTextFormat::U_SIMPLE : KoTextFormat::U_NONE); 02007 return setFormatCommand( &format, KoTextFormat::ExtendUnderLine ); 02008 } 02009 02010 KCommand *KoTextFormatInterface::setUnderlineColorCommand( const QColor &color ) 02011 { 02012 KoTextFormat format( *currentFormat() ); 02013 format.setTextUnderlineColor( color); 02014 return setFormatCommand( &format, KoTextFormat::ExtendUnderLine ); 02015 } 02016 02017 KCommand *KoTextFormatInterface::setDoubleUnderlineCommand( bool on ) 02018 { 02019 KoTextFormat format( *currentFormat() ); 02020 format.setUnderlineType( on ? KoTextFormat::U_DOUBLE : KoTextFormat::U_NONE); 02021 return setFormatCommand( &format, KoTextFormat::ExtendUnderLine ); 02022 } 02023 02024 KCommand *KoTextFormatInterface::setStrikeOutCommand( bool on ) 02025 { 02026 KoTextFormat format( *currentFormat() ); 02027 format.setStrikeOutType( on ? KoTextFormat::S_SIMPLE : KoTextFormat::S_NONE); 02028 return setFormatCommand( &format, KoTextFormat::StrikeOut ); 02029 } 02030 02031 KCommand *KoTextFormatInterface::setTextBackgroundColorCommand(const QColor & col) 02032 { 02033 KoTextFormat format( *currentFormat() ); 02034 format.setTextBackgroundColor( col ); 02035 return setFormatCommand( &format, KoTextFormat::TextBackgroundColor ); 02036 } 02037 02038 KCommand *KoTextFormatInterface::setPointSizeCommand( int s ) 02039 { 02040 KoTextFormat format( *currentFormat() ); 02041 format.setPointSize( s ); 02042 return setFormatCommand( &format, KoTextFormat::Size, true /* zoom the font size */ ); 02043 } 02044 02045 KCommand *KoTextFormatInterface::setFamilyCommand(const QString &font) 02046 { 02047 KoTextFormat format( *currentFormat() ); 02048 format.setFamily( font ); 02049 return setFormatCommand( &format, KoTextFormat::Family ); 02050 } 02051 02052 QColor KoTextFormatInterface::textBackgroundColor() const 02053 { 02054 return currentFormat()->textBackgroundColor(); 02055 } 02056 02057 QColor KoTextFormatInterface::textUnderlineColor()const 02058 { 02059 return currentFormat()->textUnderlineColor(); 02060 } 02061 02062 QColor KoTextFormatInterface::textColor() const 02063 { 02064 return currentFormat()->color(); 02065 } 02066 02067 02068 bool KoTextFormatInterface::textUnderline()const 02069 { 02070 return currentFormat()->underline(); 02071 } 02072 02073 bool KoTextFormatInterface::textDoubleUnderline()const 02074 { 02075 return currentFormat()->doubleUnderline(); 02076 } 02077 02078 bool KoTextFormatInterface::textBold()const 02079 { 02080 return currentFormat()->font().bold(); 02081 } 02082 02083 bool KoTextFormatInterface::textStrikeOut()const 02084 { 02085 return currentFormat()->font().strikeOut(); 02086 } 02087 02088 bool KoTextFormatInterface::textItalic() const 02089 { 02090 return currentFormat()->font().italic(); 02091 } 02092 02093 bool KoTextFormatInterface::textSubScript() const 02094 { 02095 return (currentFormat()->vAlign()==KoTextFormat::AlignSubScript); 02096 } 02097 02098 bool KoTextFormatInterface::textSuperScript() const 02099 { 02100 return (currentFormat()->vAlign()==KoTextFormat::AlignSuperScript); 02101 } 02102 02103 double KoTextFormatInterface::shadowDistanceX() const 02104 { 02105 return currentFormat()->shadowDistanceX(); 02106 } 02107 02108 double KoTextFormatInterface::shadowDistanceY() const 02109 { 02110 return currentFormat()->shadowDistanceY(); 02111 } 02112 02113 QColor KoTextFormatInterface::shadowColor() const 02114 { 02115 return currentFormat()->shadowColor(); 02116 } 02117 02118 KoTextFormat::AttributeStyle KoTextFormatInterface::fontAttribute() const 02119 { 02120 return currentFormat()->attributeFont(); 02121 } 02122 02123 double KoTextFormatInterface::relativeTextSize() const 02124 { 02125 return ( currentFormat()->relativeTextSize()); 02126 } 02127 02128 int KoTextFormatInterface::offsetFromBaseLine()const 02129 { 02130 return ( currentFormat()->offsetFromBaseLine()); 02131 } 02132 02133 bool KoTextFormatInterface::wordByWord()const 02134 { 02135 return ( currentFormat()->wordByWord()); 02136 } 02137 02138 bool KoTextFormatInterface::hyphenation()const 02139 { 02140 return ( currentFormat()->hyphenation()); 02141 } 02142 02143 KoTextFormat::UnderlineType KoTextFormatInterface::underlineType()const 02144 { 02145 return currentFormat()->underlineType(); 02146 } 02147 02148 KoTextFormat::StrikeOutType KoTextFormatInterface::strikeOutType()const 02149 { 02150 return currentFormat()->strikeOutType(); 02151 } 02152 02153 KoTextFormat::UnderlineStyle KoTextFormatInterface::underlineStyle()const 02154 { 02155 return currentFormat()->underlineStyle(); 02156 } 02157 02158 KoTextFormat::StrikeOutStyle KoTextFormatInterface::strikeOutStyle()const 02159 { 02160 return currentFormat()->strikeOutStyle(); 02161 } 02162 02163 QFont KoTextFormatInterface::textFont() const 02164 { 02165 QFont fn( currentFormat()->font() ); 02166 // "unzoom" the font size 02167 //fn.setPointSize( static_cast<int>( KoTextZoomHandler::layoutUnitPtToPt( fn.pointSize() ) ) ); 02168 return fn; 02169 } 02170 02171 QString KoTextFormatInterface::textFontFamily()const 02172 { 02173 return currentFormat()->font().family(); 02174 } 02175 02176 QString KoTextFormatInterface::language() const 02177 { 02178 return currentFormat()->language(); 02179 } 02180 02181 KCommand *KoTextFormatInterface::setTextColorCommand(const QColor &color) 02182 { 02183 KoTextFormat format( *currentFormat() ); 02184 format.setColor( color ); 02185 return setFormatCommand( &format, KoTextFormat::Color ); 02186 } 02187 02188 KCommand *KoTextFormatInterface::setTextSubScriptCommand(bool on) 02189 { 02190 KoTextFormat format( *currentFormat() ); 02191 if(!on) 02192 format.setVAlign(KoTextFormat::AlignNormal); 02193 else 02194 format.setVAlign(KoTextFormat::AlignSubScript); 02195 return setFormatCommand( &format, KoTextFormat::VAlign ); 02196 } 02197 02198 KCommand *KoTextFormatInterface::setTextSuperScriptCommand(bool on) 02199 { 02200 KoTextFormat format( *currentFormat() ); 02201 if(!on) 02202 format.setVAlign(KoTextFormat::AlignNormal); 02203 else 02204 format.setVAlign(KoTextFormat::AlignSuperScript); 02205 return setFormatCommand( &format, KoTextFormat::VAlign ); 02206 } 02207 02208 KCommand *KoTextFormatInterface::setDefaultFormatCommand() 02209 { 02210 KoTextFormatCollection * coll = currentFormat()->parent(); 02211 Q_ASSERT(coll); 02212 if(coll) 02213 { 02214 KoTextFormat * format = coll->defaultFormat(); 02215 return setFormatCommand( format, KoTextFormat::Format ); 02216 } 02217 return 0L; 02218 } 02219 02220 KCommand *KoTextFormatInterface::setAlignCommand(int align) 02221 { 02222 KoParagLayout format( *currentParagLayoutFormat() ); 02223 format.alignment=align; 02224 return setParagLayoutFormatCommand(&format,KoParagLayout::Alignment); 02225 } 02226 02227 KCommand *KoTextFormatInterface::setHyphenationCommand( bool _b ) 02228 { 02229 KoTextFormat format( *currentFormat() ); 02230 format.setHyphenation( _b ); 02231 return setFormatCommand( &format, KoTextFormat::Hyphenation); 02232 } 02233 02234 02235 KCommand *KoTextFormatInterface::setShadowTextCommand( double shadowDistanceX, double shadowDistanceY, const QColor& shadowColor ) 02236 { 02237 KoTextFormat format( *currentFormat() ); 02238 format.setShadow( shadowDistanceX, shadowDistanceY, shadowColor ); 02239 return setFormatCommand( &format, KoTextFormat::ShadowText ); 02240 } 02241 02242 KCommand *KoTextFormatInterface::setFontAttributeCommand( KoTextFormat::AttributeStyle _att) 02243 { 02244 KoTextFormat format( *currentFormat() ); 02245 format.setAttributeFont( _att ); 02246 return setFormatCommand( &format, KoTextFormat::Attribute ); 02247 } 02248 02249 KCommand *KoTextFormatInterface::setRelativeTextSizeCommand( double _size ) 02250 { 02251 KoTextFormat format( *currentFormat() ); 02252 format.setRelativeTextSize( _size ); 02253 return setFormatCommand( &format, KoTextFormat::VAlign ); 02254 } 02255 02256 KCommand *KoTextFormatInterface::setOffsetFromBaseLineCommand( int _offset ) 02257 { 02258 KoTextFormat format( *currentFormat() ); 02259 format.setOffsetFromBaseLine( _offset ); 02260 return setFormatCommand( &format, KoTextFormat::OffsetFromBaseLine ); 02261 } 02262 02263 KCommand *KoTextFormatInterface::setWordByWordCommand( bool _b ) 02264 { 02265 KoTextFormat format( *currentFormat() ); 02266 format.setWordByWord( _b ); 02267 return setFormatCommand( &format, KoTextFormat::WordByWord ); 02268 } 02269 02270 02271 #if 0 02272 void KoTextFormatInterface::setAlign(int align) 02273 { 02274 KCommand *cmd = setAlignCommand( align ); 02275 emitNewCommand( cmd ); 02276 } 02277 02278 void KoTextFormatInterface::setMargin(QStyleSheetItem::Margin m, double margin) 02279 { 02280 KCommand *cmd = setMarginCommand( m, margin ); 02281 emitNewCommand( cmd ); 02282 } 02283 02284 void KoTextFormatInterface::setTabList(const KoTabulatorList & tabList ) 02285 { 02286 KCommand *cmd = setTabListCommand( tabList ); 02287 emitNewCommand( cmd ); 02288 } 02289 02290 void KoTextFormatInterface::setCounter(const KoParagCounter & counter ) 02291 { 02292 KCommand *cmd = setCounterCommand( counter ); 02293 emitNewCommand( cmd ); 02294 } 02295 02296 void KoTextFormatInterface::setParagLayoutFormat( KoParagLayout *newLayout, int flags, int marginIndex) 02297 { 02298 KCommand *cmd = setParagLayoutFormatCommand(newLayout, flags, marginIndex); 02299 emitNewCommand( cmd ); 02300 } 02301 #endif 02302 02303 KCommand *KoTextFormatInterface::setMarginCommand(QStyleSheetItem::Margin m, double margin) 02304 { 02305 KoParagLayout format( *currentParagLayoutFormat() ); 02306 format.margins[m]=margin; 02307 return setParagLayoutFormatCommand(&format,KoParagLayout::Margins,(int)m); 02308 } 02309 02310 KCommand *KoTextFormatInterface::setTabListCommand(const KoTabulatorList & tabList ) 02311 { 02312 KoParagLayout format( *currentParagLayoutFormat() ); 02313 format.setTabList(tabList); 02314 return setParagLayoutFormatCommand(&format,KoParagLayout::Tabulator); 02315 } 02316 02317 KCommand *KoTextFormatInterface::setCounterCommand(const KoParagCounter & counter ) 02318 { 02319 KoParagLayout format( *currentParagLayoutFormat() ); 02320 if(!format.counter) 02321 format.counter = new KoParagCounter; 02322 *format.counter = counter; 02323 return setParagLayoutFormatCommand(&format,KoParagLayout::BulletNumber); 02324 } 02325 02326 KCommand *KoTextFormatInterface::setLanguageCommand(const QString &_lang) 02327 { 02328 KoTextFormat format( *currentFormat() ); 02329 format.setLanguage(_lang); 02330 return setFormatCommand( &format, KoTextFormat::Language ); 02331 } 02332 02333 KoTextDocCommand *KoTextFormatInterface::deleteTextCommand( KoTextDocument *textdoc, int id, int index, const QMemArray<KoTextStringChar> & str, const CustomItemsMap & customItemsMap, const QValueList<KoParagLayout> & oldParagLayouts ) 02334 { 02335 return textdoc->deleteTextCommand( textdoc, id, index, str, customItemsMap, oldParagLayouts ); 02336 } 02337 02338 #include "kotextobject.moc"
KDE Logo
This file is part of the documentation for lib Library Version 1.3.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Sep 28 04:04:02 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003