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

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 "FormulaEditor.h"
0024 
0025 #include "BasicElement.h"
0026 #include "RowElement.h"
0027 #include "FixedElement.h"
0028 #include "NumberElement.h"
0029 #include "TableElement.h"
0030 #include "TableDataElement.h"
0031 #include "TableRowElement.h"
0032 #include "ElementFactory.h"
0033 #include "OperatorElement.h"
0034 #include "IdentifierElement.h"
0035 #include "FormulaCommand.h"
0036 #include "FormulaDebug.h"
0037 
0038 #include <QPainter>
0039 #include <QPen>
0040 #include <algorithm>
0041 #include <QObject>
0042 
0043 #include <klocalizedstring.h>
0044 #include <kundo2command.h>
0045 #include <KoOdfLoadingContext.h>
0046 
0047 FormulaEditor::FormulaEditor( FormulaCursor cursor, FormulaData* data )
0048 {
0049     m_cursor=cursor;
0050     m_data=data;
0051 }
0052 
0053 FormulaEditor::FormulaEditor ( FormulaData* data )
0054 {
0055     m_cursor=FormulaCursor(data->formulaElement(),0);
0056     m_data=data;
0057 }
0058 
0059 
0060 
0061 void FormulaEditor::paint( QPainter& painter ) const
0062 {
0063     m_cursor.paint(painter);
0064 }
0065 
0066 FormulaCommand* FormulaEditor::insertText( const QString& text )
0067 {
0068     FormulaCommand *undo = 0;
0069     m_inputBuffer = text;
0070     if (m_cursor.insideToken()) {
0071         TokenElement* token=static_cast<TokenElement*>(m_cursor.currentElement());
0072         if (m_cursor.hasSelection()) {
0073             undo=new FormulaCommandReplaceText(token,m_cursor.selection().first,m_cursor.selection().second-m_cursor.selection().first,text);
0074         } else {
0075             undo=new FormulaCommandReplaceText(token,m_cursor.position(),0,text);
0076         }
0077     } else {
0078         TokenElement* token = static_cast<TokenElement*>
0079             (ElementFactory::createElement(tokenType(text[0]),0));
0080         token->insertText(0,text);
0081         undo=insertElement(token);
0082         if (undo) {
0083             undo->setRedoCursorPosition(FormulaCursor(token,text.length()));
0084         }
0085     }
0086     if (undo) {
0087         undo->setText(kundo2_i18n("Add text"));
0088     }
0089     return undo;
0090 }
0091 
0092 FormulaCommand* FormulaEditor::insertMathML( const QString& data )
0093 {
0094     // setup a DOM structure and start the actual loading process
0095     KoXmlDocument tmpDocument;
0096     tmpDocument.setContent( QString(data), false, 0, 0, 0 );
0097     BasicElement* element=ElementFactory::createElement(tmpDocument.documentElement().tagName(),0);
0098     element->readMathML( tmpDocument.documentElement() );     // and load the new formula
0099     FormulaCommand* command=insertElement( element );
0100     debugFormula << "Inserting "<< tmpDocument.documentElement().tagName();
0101     if (command==0) {
0102         delete element;
0103     }
0104     return command;
0105 }
0106 
0107 FormulaCommand* FormulaEditor::changeTable ( bool insert, bool rows )
0108 {
0109     FormulaCommand* undo;
0110     TableDataElement* data=m_cursor.currentElement()->parentTableData();
0111     if (data) {
0112         TableElement* table=static_cast<TableElement*>(data->parentElement()->parentElement());
0113         int rowNumber=table->childElements().indexOf(data->parentElement());
0114         int columnNumber=data->parentElement()->childElements().indexOf(data);
0115         if (rows) {
0116             //Changing rows
0117             if (insert) {
0118                 undo=new FormulaCommandReplaceRow(formulaData(),cursor(),table,rowNumber,0,1);
0119                 if (undo) {
0120                     undo->setText(kundo2_i18n("Insert row"));
0121                 }
0122             } else {
0123                 undo=new FormulaCommandReplaceRow(formulaData(),cursor(),table,rowNumber,1,0);
0124                 if (undo) {
0125                     undo->setText(kundo2_i18n("Remove row"));
0126                 }
0127             }
0128         } else {
0129             //Changing columns
0130             if (insert) {
0131                 undo=new FormulaCommandReplaceColumn(formulaData(),cursor(),table,columnNumber,0,1);
0132                 if (undo) {
0133                     undo->setText(kundo2_i18n("Insert column"));
0134                 }
0135             } else {
0136                 undo=new FormulaCommandReplaceColumn(formulaData(),cursor(),table,columnNumber,1,0);
0137                 if (undo) {
0138                     undo->setText(kundo2_i18n("Remove column"));
0139                 }
0140             }
0141         }
0142     } else {
0143         return 0;
0144     }
0145     return undo;
0146 }
0147 
0148 FormulaCommand* FormulaEditor::insertElement( BasicElement* element )
0149 {
0150     FormulaCommand *undo = 0;
0151     if (m_cursor.insideInferredRow()) {
0152         RowElement* tmprow=static_cast<RowElement*>(m_cursor.currentElement());
0153         QList<BasicElement*> list;
0154         list<<element;
0155         if (m_cursor.hasSelection()) {
0156             undo=new FormulaCommandReplaceElements(tmprow,m_cursor.selection().first,m_cursor.selection().second-m_cursor.selection().first,list,true);
0157         } else {
0158             undo=new FormulaCommandReplaceElements(tmprow,m_cursor.position(),0,list,false);
0159         }
0160     } else if (m_cursor.insideToken() && element->elementType()==Glyph) {
0161         //TODO: implement the insertion of glyphs
0162     }
0163     if (undo) {
0164         undo->setText(kundo2_i18n("Insert formula elements."));
0165         undo->setUndoCursorPosition(cursor());
0166     }
0167     return undo;
0168 }
0169 
0170 FormulaCommand* FormulaEditor::remove( bool elementBeforePosition )
0171 {
0172     FormulaCommand *undo=0;
0173     if (m_cursor.insideInferredRow()) {
0174         RowElement* tmprow=static_cast<RowElement*>(m_cursor.currentElement());
0175         if (m_cursor.isSelecting()) {
0176             undo=new FormulaCommandReplaceElements(tmprow,m_cursor.selection().first,m_cursor.selection().second-m_cursor.selection().first,QList<BasicElement*>());
0177         } else {
0178             if (elementBeforePosition && !m_cursor.isHome()) {
0179                 undo=new FormulaCommandReplaceElements(tmprow,m_cursor.position()-1,1,QList<BasicElement*>());
0180             } else if (!elementBeforePosition && !m_cursor.isEnd()) {
0181                 undo=new FormulaCommandReplaceElements(tmprow,m_cursor.position(),1,QList<BasicElement*>());
0182             }
0183         }
0184     } else if (m_cursor.insideToken()) {
0185         TokenElement* tmptoken=static_cast<TokenElement*>(m_cursor.currentElement());
0186         if (m_cursor.hasSelection()) {
0187             undo=new FormulaCommandReplaceText(tmptoken,m_cursor.selection().first,m_cursor.selection().second-m_cursor.selection().first,"");
0188         } else {
0189             if (elementBeforePosition && !m_cursor.isHome()) {
0190                 undo=new FormulaCommandReplaceText(tmptoken,m_cursor.position()-1,1,"");
0191             } else if (!elementBeforePosition && !m_cursor.isEnd()) {
0192                 undo=new FormulaCommandReplaceText(tmptoken,m_cursor.position(),1,"");
0193             }
0194         }
0195     }
0196     if (undo) {
0197         undo->setText(kundo2_i18n("Remove formula elements"));
0198         undo->setUndoCursorPosition(cursor());
0199     }
0200     return undo;
0201 }
0202 
0203 void FormulaEditor::setData ( FormulaData* data )
0204 {
0205     m_data=data;
0206 }
0207 
0208 
0209 FormulaData* FormulaEditor::formulaData() const
0210 {
0211     return m_data;
0212 }
0213 
0214 QString FormulaEditor::inputBuffer() const
0215 {
0216     return m_inputBuffer;
0217 }
0218 
0219 QString FormulaEditor::tokenType ( const QChar& character ) const
0220 {
0221     QChar::Category chat=character.category();
0222     if (character.isNumber()) {
0223         return "mn";
0224     }
0225     else if (chat==QChar::Punctuation_Connector ||
0226              chat==QChar::Punctuation_Dash ||
0227              chat==QChar::Punctuation_Open ||
0228              chat==QChar::Punctuation_Close ||
0229              chat==QChar::Punctuation_InitialQuote ||
0230              chat==QChar::Punctuation_FinalQuote ||
0231              chat==QChar::Symbol_Math) {
0232         return "mo";
0233     }
0234     else if (character.isLetter()) {
0235         return "mi";
0236     }
0237     return "mi";
0238 }
0239 
0240 
0241 FormulaCursor& FormulaEditor::cursor() 
0242 {
0243     return m_cursor;
0244 }
0245 
0246 void FormulaEditor::setCursor ( FormulaCursor& cursor )
0247 {
0248     m_cursor=cursor;
0249 }
0250