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