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