lib

kformulacommand.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 2001 Andrea Rizzi <rizzi@kde.org>
00003                   Ulrich Kuettler <ulrich.kuettler@mailbox.tu-dresden.de>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018  * Boston, MA 02110-1301, USA.
00019 */
00020 
00021 #include <klocale.h>  //This is for undo descriptions
00022 
00023 #include <qvaluelist.h>
00024 
00025 #include "formulacursor.h"
00026 #include "formulaelement.h"
00027 #include "indexelement.h"
00028 #include "kformulacommand.h"
00029 #include "matrixelement.h"
00030 #include "sequenceelement.h"
00031 #include "textelement.h"
00032 #include "tokenelement.h"
00033 
00034 
00035 KFORMULA_NAMESPACE_BEGIN
00036 
00037 int PlainCommand::evilDestructionCount = 0;
00038 
00039 PlainCommand::PlainCommand( const QString& name )
00040     : KNamedCommand(name)
00041 {
00042     evilDestructionCount++;
00043 }
00044 
00045 PlainCommand::~PlainCommand()
00046 {
00047     evilDestructionCount--;
00048 }
00049 
00050 Command::Command(const QString &name, Container* document)
00051         : PlainCommand(name), cursordata(0), undocursor(0), doc(document)
00052 {
00053 }
00054 
00055 Command::~Command()
00056 {
00057     delete undocursor;
00058     delete cursordata;
00059 }
00060 
00061 FormulaCursor* Command::getExecuteCursor()
00062 {
00063     FormulaCursor* cursor = getActiveCursor();
00064     if (cursordata == 0) {
00065         setExecuteCursor(getActiveCursor());
00066     }
00067     else {
00068         cursor->setCursorData(cursordata);
00069     }
00070     return cursor;
00071 }
00072 
00073 void Command::setExecuteCursor(FormulaCursor* cursor)
00074 {
00075     // assert(cursordata == 0);
00076     cursordata = cursor->getCursorData();
00077 }
00078 
00079 FormulaCursor* Command::getUnexecuteCursor()
00080 {
00081     FormulaCursor* cursor = getActiveCursor();
00082     cursor->setCursorData(undocursor);
00083     destroyUndoCursor();
00084     return cursor;
00085 }
00086 
00087 void Command::setUnexecuteCursor(FormulaCursor* cursor)
00088 {
00089     // assert(undocursor == 0);
00090     undocursor = cursor->getCursorData();
00091 }
00092 
00093 
00094 // ******  Generic Add command
00095 
00096 KFCAdd::KFCAdd(const QString &name, Container *document)
00097         : Command(name, document)
00098 {
00099     addList.setAutoDelete( true );
00100 }
00101 
00102 
00103 void KFCAdd::execute()
00104 {
00105     FormulaCursor* cursor = getExecuteCursor();
00106     cursor->insert(addList, beforeCursor);
00107     setUnexecuteCursor(cursor);
00108     cursor->setSelection(false);
00109     testDirty();
00110 }
00111 
00112 
00113 void KFCAdd::unexecute()
00114 {
00115     FormulaCursor* cursor = getUnexecuteCursor();
00116     cursor->remove(addList, beforeCursor);
00117     //cursor->setSelection(false);
00118     cursor->normalize();
00119     testDirty();
00120 }
00121 
00122 
00123 // ******  Remove selection command
00124 
00125 KFCRemoveSelection::KFCRemoveSelection(Container *document,
00126                                        Direction direction)
00127         : Command(i18n("Remove Selected Text"), document),
00128           dir(direction)
00129 {
00130     removedList.setAutoDelete( true );
00131 }
00132 
00133 void KFCRemoveSelection::execute()
00134 {
00135     FormulaCursor* cursor = getExecuteCursor();
00136     cursor->remove(removedList, dir);
00137     setUnexecuteCursor(cursor);
00138     testDirty();
00139 }
00140 
00141 void KFCRemoveSelection::unexecute()
00142 {
00143     FormulaCursor* cursor = getUnexecuteCursor();
00144     cursor->insert(removedList);
00145     cursor->setSelection(false);
00146     testDirty();
00147 }
00148 
00149 
00150 
00151 KFCReplace::KFCReplace(const QString &name, Container* document)
00152         : KFCAdd(name, document), removeSelection(0)
00153 {
00154 }
00155 
00156 KFCReplace::~KFCReplace()
00157 {
00158     delete removeSelection;
00159 }
00160 
00161 void KFCReplace::execute()
00162 {
00163     if (getActiveCursor()->isSelection() && (removeSelection == 0)) {
00164         removeSelection = new KFCRemoveSelection(getDocument());
00165     }
00166     if (removeSelection != 0) {
00167         removeSelection->execute();
00168     }
00169     KFCAdd::execute();
00170 }
00171 
00172 void KFCReplace::unexecute()
00173 {
00174     KFCAdd::unexecute();
00175     if (removeSelection != 0) {
00176         removeSelection->unexecute();
00177     }
00178 }
00179 
00180 
00181 // ******  Token Add command
00182 
00183 KFCAddToken::KFCAddToken(const QString &name, Container *document)
00184         : Command(name, document)
00185 {
00186 }
00187 
00188 KFCAddToken::~KFCAddToken()
00189 {
00190     QPtrDictIterator< QPtrList< BasicElement > > it( contentList );
00191     QPtrList< BasicElement >* list;
00192     while ( ( list = it.current() ) != 0 ) {
00193         delete list;
00194         ++it;
00195     }
00196 }
00197 
00198 void KFCAddToken::execute()
00199 {
00200     kdDebug( DEBUGID ) << k_funcinfo << endl;
00201     FormulaCursor* cursor = getExecuteCursor();
00202     QPtrList<BasicElement> tokenListTmp = tokenList;
00203     cursor->insert( tokenList, beforeCursor );
00204     tokenList = tokenListTmp;
00205     QPtrListIterator< BasicElement > it( tokenList );
00206     BasicElement* element;
00207     BasicElement* current = cursor->getElement();
00208     while ( (element = it.current()) != 0 ) {
00209         element->goInside( cursor );
00210         cursor->insert( *contentList.find( element ), beforeCursor );
00211         ++it;
00212     }
00213     setUnexecuteCursor( cursor );
00214     cursor->setSelection(false);
00215     testDirty();
00216 }
00217 
00218 
00219 void KFCAddToken::unexecute()
00220 {
00221     kdDebug( DEBUGID ) << k_funcinfo << endl;
00222     FormulaCursor* cursor = getUnexecuteCursor();
00223     SequenceElement* parent = static_cast<SequenceElement*>(cursor->getElement()->getParent());
00224 
00225     for ( int i = 0; i < tokenList.count(); i++ ) {
00226         SequenceElement* current = static_cast<SequenceElement*>(cursor->getElement());
00227         QPtrList< BasicElement > list;
00228         for ( uint i = 0; i < current->countChildren(); ++i ) {
00229             cursor->remove( list, beforeCursor );
00230         }
00231         if ( parent ) {
00232             int pos = parent->childPos( current );
00233             cursor->setTo( parent, pos + 1);
00234             cursor->remove( list, beforeCursor );
00235             if ( pos > 0 ) {
00236                 BasicElement* element = parent->getChild( pos - 1 );
00237                 if (element)
00238                     element->moveEnd( cursor );
00239             }
00240         }
00241     }
00242     testDirty();
00243 }
00244 
00248 void KFCAddToken::addToken( BasicElement* element )
00249 { 
00250     tokenList.append( element ); 
00251     contentList.insert( element, new QPtrList< BasicElement > );
00252     contentList.find( element )->setAutoDelete( true );
00253 }
00254 
00255 KFCReplaceToken::KFCReplaceToken(const QString &name, Container* document)
00256     : KFCAddToken(name, document), removeSelection(0)
00257 {
00258 }
00259 
00260 KFCReplaceToken::~KFCReplaceToken()
00261 {
00262     delete removeSelection;
00263 }
00264 
00265 void KFCReplaceToken::execute()
00266 {
00267     kdDebug( DEBUGID ) << k_funcinfo << endl;
00268     if (getActiveCursor()->isSelection() && (removeSelection == 0)) {
00269         removeSelection = new KFCRemoveSelection(getDocument());
00270     }
00271     if (removeSelection != 0) {
00272         removeSelection->execute();
00273     }
00274     KFCAddToken::execute();
00275 }
00276 
00277 void KFCReplaceToken::unexecute()
00278 {
00279     kdDebug( DEBUGID ) << k_funcinfo << endl;
00280     KFCAddToken::unexecute();
00281     if (removeSelection != 0) {
00282         removeSelection->unexecute();
00283     }
00284 }
00285 
00286 
00287 KFCSplitToken::KFCSplitToken(const QString &name, Container* document)
00288     : KFCAddToken(name, document), removeSelection(0)
00289 {
00290     splitList.setAutoDelete( true );
00291 }
00292 
00293 KFCSplitToken::~KFCSplitToken()
00294 {
00295     delete splitCursor;
00296     delete removeSelection;
00297 }
00298 
00299 void KFCSplitToken::execute()
00300 {
00301     FormulaCursor* cursor = getExecuteCursor();
00302     if (getActiveCursor()->isSelection() && (removeSelection == 0)) {
00303         removeSelection = new KFCRemoveSelection(getDocument());
00304     }
00305     if (removeSelection != 0) {
00306         removeSelection->execute();
00307     }
00308     splitCursor = cursor->getCursorData();
00309     SequenceElement* parent = static_cast<SequenceElement*>( cursor->getElement() );
00310     if ( parent ) {
00311         cursor->setMark( parent->countChildren() );
00312         cursor->setSelection( true );
00313     }
00314     cursor->remove( splitList, afterCursor );
00315     TokenElement *token = new TokenElement();// TODO 
00316     addToken( token );
00317     QPtrListIterator< BasicElement > it ( splitList );
00318     BasicElement* element;
00319     while ( ( element = it.current() ) != 0 ) {
00320         addContent( token, element );
00321         ++it;
00322     }
00323     KFCAddToken::execute();
00324     cursor = getExecuteCursor();
00325     if ( parent ) {
00326         BasicElement* child = parent->getChild( cursor->getPos() );
00327         if ( child ) {
00328             child->moveEnd( cursor );
00329         }
00330     }
00331 }
00332 
00333 void KFCSplitToken::unexecute()
00334 {
00335     kdDebug( DEBUGID ) << k_funcinfo << endl;
00336     KFCAddToken::unexecute();
00337     FormulaCursor *cursor;
00338     cursor->setCursorData( splitCursor );
00339     cursor->insert( splitList, afterCursor );
00340     if (removeSelection != 0) {
00341         removeSelection->unexecute();
00342     }
00343     testDirty();
00344 }
00345 
00346 
00347 KFCRemove::KFCRemove(Container *document,
00348                      Direction direction)
00349         : Command(i18n("Remove Selected Text"), document),
00350           element(0), simpleRemoveCursor(0), dir(direction)
00351 {
00352     removedList.setAutoDelete( true );
00353 }
00354 
00355 KFCRemove::~KFCRemove()
00356 {
00357     delete simpleRemoveCursor;
00358     delete element;
00359 }
00360 
00361 void KFCRemove::execute()
00362 {
00363     FormulaCursor* cursor = getExecuteCursor();
00364     cursor->remove(removedList, dir);
00365     if (cursor->elementIsSenseless()) {
00366         simpleRemoveCursor = cursor->getCursorData();
00367         element = cursor->replaceByMainChildContent();
00368     }
00369     setUnexecuteCursor(cursor);
00370     cursor->normalize( dir );
00371     testDirty();
00372 }
00373 
00374 void KFCRemove::unexecute()
00375 {
00376     FormulaCursor* cursor = getUnexecuteCursor();
00377     if (element != 0) {
00378         cursor->replaceSelectionWith(element);
00379         element = 0;
00380 
00381         cursor->setCursorData(simpleRemoveCursor);
00382         delete simpleRemoveCursor;
00383         simpleRemoveCursor = 0;
00384     }
00385     cursor->insert(removedList, dir);
00386     cursor->setSelection(false);
00387     testDirty();
00388 }
00389 
00390 
00391 KFCRemoveEnclosing::KFCRemoveEnclosing(Container* document,
00392                                        Direction dir)
00393         : Command(i18n("Remove Enclosing Element"), document),
00394           element(0), direction(dir)
00395 {
00396 }
00397 
00398 KFCRemoveEnclosing::~KFCRemoveEnclosing()
00399 {
00400     delete element;
00401 }
00402 
00403 void KFCRemoveEnclosing::execute()
00404 {
00405     FormulaCursor* cursor = getExecuteCursor();
00406     element = cursor->removeEnclosingElement(direction);
00407     setUnexecuteCursor(cursor);
00408     //cursor->normalize();
00409     cursor->setSelection(false);
00410     testDirty();
00411 }
00412 
00413 void KFCRemoveEnclosing::unexecute()
00414 {
00415     FormulaCursor* cursor = getUnexecuteCursor();
00416     if ( element ) {
00417         cursor->replaceSelectionWith(element);
00418     }
00419     cursor->normalize();
00420     cursor->setSelection(false);
00421     element = 0;
00422     testDirty();
00423 }
00424 
00425 
00426 // ******  Add root, bracket etc command
00427 
00428 KFCAddReplacing::KFCAddReplacing(const QString &name, Container* document)
00429         : Command(name, document), element(0)
00430 {
00431 }
00432 
00433 KFCAddReplacing::~KFCAddReplacing()
00434 {
00435     delete element;
00436 }
00437 
00438 
00439 void KFCAddReplacing::execute()
00440 {
00441     FormulaCursor* cursor = getExecuteCursor();
00442     cursor->replaceSelectionWith(element);
00443     setUnexecuteCursor(cursor);
00444     cursor->goInsideElement(element);
00445     element = 0;
00446     testDirty();
00447 }
00448 
00449 
00450 void KFCAddReplacing::unexecute()
00451 {
00452     FormulaCursor* cursor = getUnexecuteCursor();
00453     element = cursor->replaceByMainChildContent();
00454     cursor->normalize();
00455     testDirty();
00456 }
00457 
00458 
00459 // ******  Add index command
00460 
00461 KFCAddGenericIndex::KFCAddGenericIndex(Container* document, ElementIndexPtr _index)
00462         : KFCAdd(i18n("Add Index"), document), index(_index)
00463 {
00464     addElement(new SequenceElement());
00465 }
00466 
00467 void KFCAddGenericIndex::execute()
00468 {
00469     index->setToIndex(getActiveCursor());
00470     KFCAdd::execute();
00471 }
00472 
00473 
00474 KFCAddIndex::KFCAddIndex(Container* document,
00475                          IndexElement* element, ElementIndexPtr index)
00476         : KFCAddReplacing(i18n("Add Index"), document),
00477           addIndex(document, index)
00478 {
00479     setElement(element);
00480 }
00481 
00482 KFCAddIndex::~KFCAddIndex()
00483 {
00484 }
00485 
00486 void KFCAddIndex::execute()
00487 {
00488     KFCAddReplacing::execute();
00489     addIndex.execute();
00490 }
00491 
00492 void KFCAddIndex::unexecute()
00493 {
00494     addIndex.unexecute();
00495     KFCAddReplacing::unexecute();
00496 }
00497 
00498 
00499 KFCChangeBaseSize::KFCChangeBaseSize( const QString& name, Container* document,
00500                                       FormulaElement* formula, int size )
00501     : PlainCommand( name ), m_document( document ), m_formula( formula ), m_size( size )
00502 {
00503     m_oldSize = formula->getBaseSize();
00504 }
00505 
00506 void KFCChangeBaseSize::execute()
00507 {
00508     m_formula->setBaseSize( m_size );
00509     m_document->recalc();
00510 }
00511 
00512 void KFCChangeBaseSize::unexecute()
00513 {
00514     m_formula->setBaseSize( m_oldSize );
00515     m_document->recalc();
00516 }
00517 
00518 
00519 FontCommand::FontCommand( const QString& name, Container* document )
00520     : Command( name, document )
00521 {
00522     list.setAutoDelete( false );
00523     elementList.setAutoDelete( false );
00524 }
00525 
00526 
00527 void FontCommand::collectChildren()
00528 {
00529     list.clear();
00530     uint count = elementList.count();
00531     for ( uint i=0; i<count; ++i ) {
00532         elementList.at( i )->dispatchFontCommand( this );
00533     }
00534 }
00535 
00536 
00537 void FontCommand::parseSequences( const QMap<SequenceElement*, int>& parents )
00538 {
00539     QValueList<SequenceElement*> sequences = parents.keys();
00540     for ( QValueList<SequenceElement*>::iterator i = sequences.begin();
00541           i != sequences.end();
00542           ++i ) {
00543         ( *i )->parse();
00544     }
00545 }
00546 
00547 
00548 CharStyleCommand::CharStyleCommand( CharStyle cs, const QString& name, Container* document )
00549     : FontCommand( name, document ), charStyle( cs )
00550 {
00551 }
00552 
00553 void CharStyleCommand::execute()
00554 {
00555     collectChildren();
00556     QMap<SequenceElement*, int> parentCollector;
00557 
00558     styleList.clear();
00559     uint count = childrenList().count();
00560     styleList.reserve( count );
00561     for ( uint i=0; i<count; ++i ) {
00562         TextElement* child = childrenList().at( i );
00563         styleList[i] = child->getCharStyle();
00564         child->setCharStyle( charStyle );
00565         parentCollector[static_cast<SequenceElement*>( child->getParent() )] = 1;
00566     }
00567     parseSequences( parentCollector );
00568     testDirty();
00569 }
00570 
00571 void CharStyleCommand::unexecute()
00572 {
00573     QMap<SequenceElement*, int> parentCollector;
00574     uint count = childrenList().count();
00575     //styleList.reserve( count );
00576     for ( uint i=0; i<count; ++i ) {
00577         TextElement* child = childrenList().at( i );
00578         child->setCharStyle( styleList[i] );
00579         parentCollector[static_cast<SequenceElement*>( child->getParent() )] = 1;
00580     }
00581     parseSequences( parentCollector );
00582     testDirty();
00583 }
00584 
00585 
00586 CharFamilyCommand::CharFamilyCommand( CharFamily cf, const QString& name, Container* document )
00587     : FontCommand( name, document ), charFamily( cf )
00588 {
00589 }
00590 
00591 void CharFamilyCommand::execute()
00592 {
00593     collectChildren();
00594 
00595     QMap<SequenceElement*, int> parentCollector;
00596 
00597     familyList.clear();
00598     uint count = childrenList().count();
00599     familyList.reserve( count );
00600     for ( uint i=0; i<count; ++i ) {
00601         TextElement* child = childrenList().at( i );
00602         familyList[i] = child->getCharFamily();
00603         child->setCharFamily( charFamily );
00604         parentCollector[static_cast<SequenceElement*>( child->getParent() )] = 1;
00605     }
00606     parseSequences( parentCollector );
00607     testDirty();
00608 }
00609 
00610 void CharFamilyCommand::unexecute()
00611 {
00612     QMap<SequenceElement*, int> parentCollector;
00613     uint count = childrenList().count();
00614     //familyList.reserve( count );
00615     for ( uint i=0; i<count; ++i ) {
00616         TextElement* child = childrenList().at( i );
00617         child->setCharFamily( familyList[i] );
00618         parentCollector[static_cast<SequenceElement*>( child->getParent() )] = 1;
00619     }
00620     parseSequences( parentCollector );
00621     testDirty();
00622 }
00623 
00624 
00625 KFORMULA_NAMESPACE_END
KDE Home | KDE Accessibility Home | Description of Access Keys