File indexing completed on 2024-05-12 16:34:01

0001 /* This file is part of the KDE project
0002    Copyright (C) 2001 Andrea Rizzi <rizzi@kde.org>
0003                       Ulrich Kuettler <ulrich.kuettler@mailbox.tu-dresden.de>
0004                  2006 Martin Pfeiffer <hubipete@gmx.net>
0005                  2009 Jeremias Epperlein <jeeree@web.de>
0006 
0007    This library is free software; you can redistribute it and/or
0008    modify it under the terms of the GNU Library General Public
0009    License as published by the Free Software Foundation; either
0010    version 2 of the License, or (at your option) any later version.
0011 
0012    This library is distributed in the hope that it will be useful,
0013    but WITHOUT ANY WARRANTY; without even the implied warranty of
0014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0015    Library General Public License for more details.
0016 
0017    You should have received a copy of the GNU Library General Public License
0018    along with this library; see the file COPYING.LIB.  If not, write to
0019    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0020    Boston, MA 02110-1301, USA.
0021 */
0022 
0023 #include "FormulaCommand.h"
0024 
0025 #include "FormulaCursor.h"
0026 #include "TokenElement.h"
0027 #include "BasicElement.h"
0028 #include "TableElement.h"
0029 #include "TableRowElement.h"
0030 #include "TableDataElement.h"
0031 #include "FormulaDebug.h"
0032 
0033 #include <klocalizedstring.h>
0034 
0035 FormulaCommand::FormulaCommand(KUndo2Command* parent)
0036               : KUndo2Command(parent)
0037 {
0038     m_done=false;
0039 }
0040 
0041 void FormulaCommand::changeCursor ( FormulaCursor& cursor, bool undo ) const
0042 {
0043     if (undo) {
0044         cursor.moveTo(m_undoCursorPosition);
0045     } else {
0046         cursor.moveTo(m_redoCursorPosition);
0047     }
0048     if (!cursor.isAccepted()) {
0049         cursor.move(MoveRight);
0050     }
0051 }
0052 
0053 void FormulaCommand::setUndoCursorPosition ( const FormulaCursor& position )
0054 {
0055     m_undoCursorPosition=position;
0056 }
0057 
0058 void FormulaCommand::setRedoCursorPosition ( const FormulaCursor& position )
0059 {
0060     m_redoCursorPosition=position;
0061 }
0062 
0063 FormulaCommandReplaceText::FormulaCommandReplaceText( TokenElement* owner, int position, int length, const QString& added , KUndo2Command* parent)
0064                   : FormulaCommand(parent)
0065 {
0066     m_ownerElement = owner;
0067     m_position = position;
0068     m_added = added;
0069     m_length = length;
0070     m_removedGlyphs=m_ownerElement->glyphList(position,length);
0071     m_removed=m_ownerElement->text().mid(position,length);
0072     setText( kundo2_i18n( "Add text to formula" ) );
0073     setUndoCursorPosition(FormulaCursor(m_ownerElement, m_position+m_removed.length()));
0074     setRedoCursorPosition(FormulaCursor(m_ownerElement, m_position+m_added.length()));
0075 }
0076 
0077 FormulaCommandReplaceText::~FormulaCommandReplaceText()
0078 {
0079 }
0080 
0081 void FormulaCommandReplaceText::redo()
0082 {
0083     m_done=true;
0084     if (m_length>0) {
0085         m_glyphpos=m_ownerElement->removeText(m_position,m_length);
0086     }
0087     m_ownerElement->insertText(m_position, m_added);
0088 }
0089 
0090 void FormulaCommandReplaceText::undo()
0091 {
0092     m_done=false;
0093     m_ownerElement->removeText(m_position,m_added.length());
0094     m_ownerElement->insertText(m_position, m_removed);
0095     m_ownerElement->insertGlyphs(m_glyphpos,m_removedGlyphs);
0096 }
0097 
0098 FormulaCommandReplaceElements::FormulaCommandReplaceElements ( RowElement* owner, int position, int length, QList< BasicElement* > elements, bool wrap,KUndo2Command* parent )
0099                             : FormulaCommand(parent)
0100 {
0101     m_ownerElement=owner;
0102     m_position=position;
0103     m_added=elements;
0104     m_length=length;
0105     m_wrap=wrap;
0106     m_removed=m_ownerElement->childElements().mid(m_position,m_length);
0107     m_placeholderPosition=0;
0108     
0109     //we have to remember to which descendant of m_added the elements got moved
0110     BasicElement* placeholder=0;
0111     foreach (BasicElement* tmp, m_added) {
0112         if ( (placeholder=tmp->emptyDescendant()) ) {
0113             break;
0114         }
0115     }
0116     if (placeholder) { //we are actually wrapping stuff
0117         //empty descandant only returns a element hows parent is an inferred mrow
0118         m_placeholderParent=static_cast<RowElement*>(placeholder->parentElement());
0119         m_placeholderPosition=m_placeholderParent->positionOfChild(placeholder);
0120         m_placeholderParent->removeChild(placeholder);
0121         delete placeholder;
0122         if (m_wrap) {
0123             setRedoCursorPosition(FormulaCursor(m_placeholderParent,m_placeholderPosition+m_removed.count()));
0124         } else {
0125             setRedoCursorPosition(FormulaCursor(m_placeholderParent,m_placeholderPosition));
0126         }
0127     } else {
0128         m_placeholderParent=0;
0129         setRedoCursorPosition(FormulaCursor(m_ownerElement,m_position+m_added.length()));
0130     }
0131     setUndoCursorPosition(FormulaCursor(m_ownerElement,m_position+m_removed.length()));
0132 }
0133 
0134 FormulaCommandReplaceElements::~FormulaCommandReplaceElements()
0135 {
0136     if (m_done) {
0137         if (!(m_wrap && m_placeholderParent)) {
0138             foreach (BasicElement* tmp, m_removed) {
0139                 delete tmp;
0140             }
0141         }
0142     } else {
0143         foreach (BasicElement* tmp, m_added) {
0144             delete tmp;
0145         }
0146     }
0147 }
0148 
0149 void FormulaCommandReplaceElements::redo()
0150 {
0151     m_done=true;
0152     for (int i=0; i<m_length; ++i) {
0153         m_ownerElement->removeChild(m_removed[i]);
0154     }
0155     if (m_wrap &&  m_placeholderParent!=0) {
0156         int counter=0;
0157         foreach (BasicElement *tmp, m_removed) {
0158             m_placeholderParent->insertChild(m_placeholderPosition+counter,tmp);
0159             counter++;
0160         }
0161     }
0162     for (int i=0; i<m_added.length(); ++i) {
0163         m_ownerElement->insertChild(m_position+i,m_added[i]);
0164     }
0165 }
0166 
0167 void FormulaCommandReplaceElements::undo()
0168 {
0169     m_done=false;
0170     for (int i=0; i<m_added.length(); ++i) {
0171         m_ownerElement->removeChild(m_added[i]);
0172     }
0173     if (m_wrap &&  m_placeholderParent!=0) {
0174         foreach (BasicElement *tmp, m_removed) {
0175             m_placeholderParent->removeChild(tmp);
0176         }
0177     }
0178     for (int i=0; i<m_length; ++i) {
0179         m_ownerElement->insertChild(m_position+i,m_removed[i]);
0180     }
0181 }
0182 
0183 FormulaCommandLoad::FormulaCommandLoad ( FormulaData* data, FormulaElement* newelement, KUndo2Command* parent )
0184                    : FormulaCommand ( parent)
0185 {
0186     m_data=data;
0187     m_newel=newelement;
0188     m_oldel=data->formulaElement();
0189     setUndoCursorPosition(FormulaCursor(m_oldel,0));
0190     setRedoCursorPosition(FormulaCursor(m_newel,0));
0191 }
0192 
0193 FormulaCommandLoad::~FormulaCommandLoad()
0194 {
0195     if (m_done) {
0196     } else {
0197     }
0198 }
0199 
0200 void FormulaCommandLoad::redo()
0201 {
0202     m_done=true;
0203     m_data->setFormulaElement(m_newel);
0204 }
0205 
0206 void FormulaCommandLoad::undo()
0207 {
0208     m_done=false;
0209     m_data->setFormulaElement(m_oldel);
0210 }
0211 
0212 FormulaCommandReplaceRow::FormulaCommandReplaceRow ( FormulaData* data, FormulaCursor oldposition, TableElement* table, int number, int oldlength, int newlength)
0213 {
0214     m_data=data;
0215     m_table=table;
0216     m_number=number;
0217     m_empty=0;
0218     int columnnumber=m_table->childElements()[0]->childElements().count();
0219     TableRowElement* tmpRow;
0220     for (int i=0; i<newlength;i++) {
0221         tmpRow = new TableRowElement();
0222         for (int j=0; j<columnnumber; j++) {
0223             tmpRow->insertChild(i,new TableDataElement());
0224         }
0225         m_newRows<<tmpRow;
0226     }
0227     m_oldRows=table->childElements().mid(number, oldlength);
0228     setText( kundo2_i18n( "Change rows" ) );
0229     if (newlength==0 && oldlength>=table->childElements().count()) {
0230         m_empty=new TableRowElement();
0231         m_empty->insertChild(0, new TableDataElement());
0232     }
0233     setUndoCursorPosition(oldposition);
0234 
0235     if (newlength>0) {
0236         setRedoCursorPosition(FormulaCursor(m_newRows[0]->childElements()[0],0));
0237     } else {
0238         if (m_empty) {
0239             setRedoCursorPosition(FormulaCursor(m_empty->childElements()[0],0));
0240         } else {
0241             int rowcount=m_table->childElements().count();
0242             if (number+oldlength < rowcount) {
0243                 //we can place the cursor after the removed elements
0244                 setRedoCursorPosition(FormulaCursor(table->childElements()[number+oldlength]->childElements()[0],0));
0245             } else {
0246                 //we have to place the cursor before the removed rows
0247                 setRedoCursorPosition(FormulaCursor(table->childElements()[number==0 ? 0: number-1]->childElements()[0],0));
0248             }
0249         }
0250     }
0251 }
0252 
0253 FormulaCommandReplaceRow::~FormulaCommandReplaceRow()
0254 {
0255     if (m_done) {
0256         qDeleteAll(m_oldRows);
0257     } else {
0258         if (m_empty) {
0259             delete m_empty;
0260         } else {
0261             qDeleteAll(m_newRows);
0262         }
0263     }
0264 }
0265 
0266 void FormulaCommandReplaceRow::redo()
0267 {
0268     for (int i=0; i<m_oldRows.count(); i++) {
0269         m_table->removeChild(m_oldRows[i]);
0270     }
0271     if (m_empty) {
0272         m_table->insertChild(0,m_empty);
0273     } else {
0274         for (int i=0; i<m_newRows.count(); i++) {
0275             m_table->insertChild(i+m_number,m_newRows[i]);
0276         }
0277     }
0278 }
0279 
0280 void FormulaCommandReplaceRow::undo()
0281 {
0282     if (m_empty) {
0283         m_table->removeChild(m_empty);
0284     } else {
0285         for (int i=0; i<m_newRows.count(); i++) {
0286             m_table->removeChild(m_newRows[i]);
0287         }
0288     }
0289     for (int i=0; i<m_oldRows.count(); i++) {
0290         m_table->insertChild(i+m_number,m_oldRows[i]);
0291     }
0292 }
0293 
0294 
0295 FormulaCommandReplaceColumn::FormulaCommandReplaceColumn ( FormulaData* data, FormulaCursor oldcursor, TableElement* table, int position, int oldlength, int newlength)
0296 {
0297     m_data=data;
0298     m_table=table;
0299     m_position=position;
0300     m_empty=0;
0301     int rownumber=m_table->childElements().count();
0302     QList<BasicElement*> tmp;
0303 
0304     if (newlength==0 && oldlength>=table->childElements().count()) {
0305         //we remove the whole table
0306         m_empty=new TableRowElement();
0307         m_empty->insertChild(0, new TableDataElement());
0308         m_oldRows=table->childElements();
0309     } else {
0310         for (int i=0; i<newlength;i++) {
0311             for (int j=0; j<rownumber;j++) {
0312                 tmp<<new TableDataElement();
0313             }
0314             m_newColumns<<tmp;
0315             tmp.clear();
0316         }
0317         for (int i=0; i<oldlength;i++) {
0318             for (int j=0; j<rownumber;j++) {
0319                 tmp<<table->childElements()[j]->childElements()[m_position+i];
0320             }
0321             m_oldColumns<<tmp;
0322             tmp.clear();
0323         }
0324     }
0325     setUndoCursorPosition(oldcursor);
0326 
0327     if (newlength>0) {
0328         setRedoCursorPosition(FormulaCursor(m_newColumns[0][0],0));
0329     } else {
0330         if (m_empty) {
0331             setRedoCursorPosition(FormulaCursor(m_empty->childElements()[0],0));
0332         } else {
0333             int columncount=m_table->childElements()[0]->childElements().count();
0334             if (position+oldlength < columncount) {
0335                 //we can place the cursor after the removed elements
0336                 setRedoCursorPosition(FormulaCursor(table->childElements()[0]->childElements()[position+oldlength],0));
0337             } else {
0338                 //we have to place the cursor before the removed rows
0339                 setRedoCursorPosition(FormulaCursor(table->childElements()[0]->childElements()[position==0 ? 0: position-1],0));
0340             }
0341         }
0342     }
0343 }
0344 
0345 FormulaCommandReplaceColumn::~FormulaCommandReplaceColumn()
0346 {
0347     if (m_done) {
0348         if (m_empty) {
0349             qDeleteAll(m_oldRows);
0350         } else {
0351             foreach (QList<BasicElement*> column, m_oldColumns) {
0352                 foreach( BasicElement* element, column) {
0353                     delete element;
0354                 }
0355             }
0356         }
0357     } else {
0358         if (m_empty) {
0359             delete m_empty;
0360         } else {
0361             foreach (QList<BasicElement*> column, m_newColumns) {
0362                 foreach( BasicElement* element, column) {
0363                     delete element;
0364                 }
0365             }
0366         }
0367     }
0368 }
0369 
0370 void FormulaCommandReplaceColumn::redo()
0371 {
0372     if (m_empty) {
0373         for (int i=0; i<m_oldRows.count();i++) {
0374             m_table->removeChild(m_oldRows[i]);
0375         }
0376         m_table->insertChild(0,m_empty);
0377     } else {
0378         for (int i=0; i<m_table->childElements().count(); i++) {
0379             TableRowElement* row=static_cast<TableRowElement*>(m_table->childElements()[i]);
0380             for (int j=0; j<m_oldColumns.count(); j++) {
0381                 row->removeChild(m_oldColumns[j][i]);
0382             }
0383             for (int j=0; j<m_newColumns.count(); j++) {
0384                 row->insertChild(m_position+j,m_newColumns[j][i]);
0385             }
0386         }
0387     }
0388 }
0389 
0390 void FormulaCommandReplaceColumn::undo()
0391 {
0392     if (m_empty) {
0393         m_table->removeChild(m_empty);
0394         for (int i=0; i<m_oldRows.count(); ++i) {
0395             m_table->insertChild(i,m_oldRows[i]);
0396         }
0397     } else {
0398         for (int i=0; i<m_table->childElements().count(); i++) {
0399             TableRowElement* row=static_cast<TableRowElement*>(m_table->childElements()[i]);
0400             for (int j=0; j<m_newColumns.count(); j++) {
0401                 row->removeChild(m_newColumns[j][i]);
0402             }
0403             for (int j=0; j<m_oldColumns.count(); j++) {
0404                 row->insertChild(m_position+j,m_oldColumns[j][i]);
0405             }
0406         }
0407     }
0408 }
0409 
0410 
0411 // FormulaCommandAttribute::FormulaCommandAttribute( FormulaCursor* cursor,
0412 //                                                   QHash<QString,QString> attributes )
0413 //                        : KUndo2Command()
0414 // {
0415 //     m_ownerElement = cursor.ownerElement();
0416 //     m_attributes = attributes;
0417 //     m_oldAttributes = m_ownerElement->attributes();
0418 //     QHashIterator<QString, QString> i( m_oldAttributes );
0419 //     while( i.hasNext() )
0420 //     {
0421 //         i.next();
0422 //  if( !m_attributes.contains( i.key() ) )
0423 //             m_attributes.insert( i.key(), i.value() );
0424 //     }
0425 // 
0426 //     setText( kundo2_i18n( "Attribute Changed" ) );
0427 // }
0428 // 
0429 // void FormulaCommandAttribute::redo()
0430 // {
0431 //     m_ownerElement->setAttributes( m_attributes );
0432 // }
0433 // 
0434 // void FormulaCommandAttribute::undo()
0435 // {
0436 //     m_ownerElement->setAttributes( m_oldAttributes );
0437 // }