1 /* This file is part of the KDE project
2    Copyright (C) 2011 Cyrille Berger <cberger@cberger.net>
3 
4    This library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Library General Public
6    License as published by the Free Software Foundation; either
7    version 2 of the License, or (at your option) any later version.
8 
9    This library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Library General Public License for more details.
13 
14    You should have received a copy of the GNU Library General Public License
15    along with this library; see the file COPYING.LIB.  If not, write to
16    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17    Boston, MA 02110-1301, USA.
18  */
19 
20 #include "KoM2MMLForumulaTool.h"
21 
22 #ifdef HAVE_M2MML
23 #include <m2mml.h>
24 #endif
25 
26 #include <string>
27 
28 #include <QComboBox>
29 #include <QHBoxLayout>
30 #include <QLabel>
31 #include <QLineEdit>
32 #include <QSpacerItem>
33 #include <QWidget>
34 
35 #include <KoCanvasBase.h>
36 #include <KoIcon.h>
37 #include <KoXmlReader.h>
38 
39 #include <AnnotationElement.h>
40 #include "FormulaDebug.h"
41 #include "KoFormulaShape.h"
42 #include "FormulaCommand.h"
43 #include "FormulaCommandUpdate.h"
44 #include "3rdparty/itexToMML/itex2MML.h"
45 
KoM2MMLFormulaTool(KoCanvasBase * canvas)46 KoM2MMLFormulaTool::KoM2MMLFormulaTool(KoCanvasBase* canvas): KoToolBase(canvas), m_lineEdit(0), m_errorLabel(0), m_formulaShape(0), m_comboBox(0)
47 {
48 
49 }
50 
activate(KoToolBase::ToolActivation toolActivation,const QSet<KoShape * > & shapes)51 void KoM2MMLFormulaTool::activate(KoToolBase::ToolActivation toolActivation, const QSet< KoShape* >& shapes)
52 {
53     Q_UNUSED(toolActivation);
54 
55     foreach (KoShape *shape, shapes) {
56         m_formulaShape = dynamic_cast<KoFormulaShape*>( shape );
57         if( m_formulaShape )
58             break;
59     }
60 
61     if( m_formulaShape == 0 )  // none found
62     {
63         emit done();
64         return;
65     }
66     FormulaElement* element = m_formulaShape->formulaData()->formulaElement();
67     foreach(BasicElement* elt, element->childElements())
68     {
69         if(elt->elementType() == Annotation)
70         {
71             AnnotationElement* annot = static_cast<AnnotationElement*>(elt);
72             m_text = annot->content();
73             m_mode = annot->attribute("mode");
74         }
75     }
76 
77     if(m_lineEdit)
78     {
79         m_lineEdit->setText(m_text);
80     }
81 }
82 
mouseMoveEvent(KoPointerEvent * event)83 void KoM2MMLFormulaTool::mouseMoveEvent(KoPointerEvent* event)
84 {
85     Q_UNUSED(event);
86 }
87 
mousePressEvent(KoPointerEvent * event)88 void KoM2MMLFormulaTool::mousePressEvent(KoPointerEvent* event)
89 {
90     Q_UNUSED(event);
91 }
92 
mouseReleaseEvent(KoPointerEvent * event)93 void KoM2MMLFormulaTool::mouseReleaseEvent(KoPointerEvent* event)
94 {
95     Q_UNUSED(event);
96 }
97 
paint(QPainter & painter,const KoViewConverter & converter)98 void KoM2MMLFormulaTool::paint(QPainter& painter, const KoViewConverter& converter)
99 {
100     Q_UNUSED(painter);
101     Q_UNUSED(converter);
102 }
103 
createOptionWidget()104 QWidget* KoM2MMLFormulaTool::createOptionWidget()
105 {
106     QWidget* widget = new QWidget;
107     QVBoxLayout* layout = new QVBoxLayout;
108 
109     // Combobox to select between latex or matlab
110     QLabel* modeLabel = new QLabel(i18n("Mode: "));
111     m_comboBox = new QComboBox;
112 
113     m_comboBox->addItem(i18n("LaTeX"));
114 #ifdef HAVE_M2MML
115     m_comboBox->addItem(i18n("Matlab"));
116 
117     if(m_mode == "Matlab")
118     {
119         m_comboBox->setCurrentIndex(1);
120     }
121 #endif
122 
123     QHBoxLayout* hlayout = new QHBoxLayout();
124     hlayout->addWidget(modeLabel);
125     hlayout->addWidget(m_comboBox);
126     layout->addLayout(hlayout);
127 
128     // Edit line
129     widget->setLayout(layout);
130     m_lineEdit = new QLineEdit(widget);
131     layout->addWidget(m_lineEdit);
132 
133     // Error label
134     m_errorLabel = new QLabel(widget);
135     layout->addWidget(m_errorLabel);
136     m_errorLabel->setText("");
137 
138     layout->addSpacerItem(new QSpacerItem(0,0));
139 
140     connect(m_lineEdit, SIGNAL(editingFinished()), SLOT(textEdited()));
141     connect(m_lineEdit, SIGNAL(returnPressed()), SLOT(textEdited()));
142     m_lineEdit->setText(m_text);
143 
144     return widget;
145 }
146 
147 // Not sure why but the toStdString/fromStdString in QString are not accessible
QStringtoStdString(const QString & str)148 inline std::string QStringtoStdString(const QString& str)
149 { const QByteArray latin1 = str.toLatin1(); return std::string(latin1.constData(), latin1.length()); }
150 
QStringfromStdString(const std::string & s)151 inline QString QStringfromStdString(const std::string &s)
152 { return QString::fromLatin1(s.data(), int(s.size())); }
153 
textEdited()154 void KoM2MMLFormulaTool::textEdited()
155 {
156     if(!m_formulaShape) return;
157     if(!m_lineEdit) return;
158 
159 #ifdef HAVE_M2MML
160     if(m_comboBox->currentIndex() == 1)
161     {
162         std::string source = QStringtoStdString(m_lineEdit->text());
163         std::string mathml;
164         std::string errmsg;
165 
166         if(m2mml(source, mathml, &errmsg))
167         {
168             setMathML(QStringfromStdString(mathml), "Matlab");
169         } else {
170             m_errorLabel->setText(QStringfromStdString(errmsg));
171         }
172     } else {
173 #endif
174         std::string source = QStringtoStdString(m_lineEdit->text());
175         source = '$' + source + '$';
176         char * mathml = itex2MML_parse (source.c_str(), source.size());
177 
178         if(mathml)
179         {
180             setMathML(mathml, "LaTeX");
181             itex2MML_free_string(mathml);
182             mathml = 0;
183         } else {
184             m_errorLabel->setText(i18n("Parse error."));
185         }
186 #ifdef HAVE_M2MML
187     }
188 #endif
189 }
190 
setMathML(const QString & mathml,const QString & mode)191 void KoM2MMLFormulaTool::setMathML(const QString& mathml, const QString& mode)
192 {
193     KoXmlDocument tmpDocument;
194     tmpDocument.setContent( QString(mathml), false, 0, 0, 0 );
195     FormulaElement* formulaElement = new FormulaElement();     // create a new root element
196     formulaElement->readMathML( tmpDocument.documentElement() );     // and load the new formula
197 
198     AnnotationElement* annot = new AnnotationElement;
199     annot->setContent(m_lineEdit->text());
200     annot->setAttribute("mode", mode);
201     formulaElement->insertChild(0, annot);
202 
203     debugFormula << mathml;
204 
205     canvas()->addCommand(new FormulaCommandUpdate(m_formulaShape, new FormulaCommandLoad(m_formulaShape->formulaData(), formulaElement)));
206     m_errorLabel->setText("");
207 }
208 
209 
KoM2MMLFormulaToolFactory()210 KoM2MMLFormulaToolFactory::KoM2MMLFormulaToolFactory()
211            : KoToolFactoryBase("KoM2MMLFormulaToolFactoryId")
212 {
213 #ifdef HAVE_M2MML
214     setToolTip( i18n( "Edit formula with LaTeX/Matlab syntax" ) );
215 #else
216     setToolTip( i18n( "Edit formula with LaTeX syntax" ) );
217 #endif
218     setToolType( dynamicToolType() );
219     setIconName(koIconName("edittext"));
220     setPriority( 1 );
221     setActivationShapeId( KoFormulaShapeId );
222 }
223 
~KoM2MMLFormulaToolFactory()224 KoM2MMLFormulaToolFactory::~KoM2MMLFormulaToolFactory()
225 {}
226 
createTool(KoCanvasBase * canvas)227 KoToolBase* KoM2MMLFormulaToolFactory::createTool( KoCanvasBase* canvas )
228 {
229     return new KoM2MMLFormulaTool( canvas );
230 }
231