Warning, file /education/cantor/src/lib/expression.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 SPDX-License-Identifier: GPL-2.0-or-later 0003 SPDX-FileCopyrightText: 2009 Alexander Rieder <alexanderrieder@gmail.com> 0004 */ 0005 0006 #include "expression.h" 0007 #include "latexrenderer.h" 0008 using namespace Cantor; 0009 0010 #include <config-cantorlib.h> 0011 0012 #include "session.h" 0013 #include "result.h" 0014 #include "textresult.h" 0015 #include "imageresult.h" 0016 #include "latexresult.h" 0017 #include "settings.h" 0018 0019 #include <QDebug> 0020 #include <QFileInfo> 0021 #include <QString> 0022 #include <QFileSystemWatcher> 0023 0024 #include <KProcess> 0025 #include <KZip> 0026 0027 class Cantor::ExpressionPrivate 0028 { 0029 public: 0030 ExpressionPrivate() : id(-1) {} 0031 0032 int id{-1}; 0033 QString command; 0034 QString error; 0035 QList<QString> information; 0036 QVector<Result*> results; 0037 Expression::Status status{Expression::Done}; 0038 Session* session{nullptr}; 0039 Expression::FinishingBehavior finishingBehavior{Expression::DoNotDelete}; 0040 bool internal{false}; 0041 bool helpRequest{false}; 0042 QFileSystemWatcher* fileWatcher{nullptr}; 0043 }; 0044 0045 static const QString tex=QLatin1String("\\documentclass[12pt,fleqn]{article} \n "\ 0046 "\\usepackage{latexsym,amsfonts,amssymb,ulem} \n "\ 0047 "\\usepackage[dvips]{graphicx} \n "\ 0048 "\\setlength\\textwidth{5in} \n "\ 0049 "\\setlength{\\parindent}{0pt} \n "\ 0050 "%1 \n "\ 0051 "\\pagestyle{empty} \n "\ 0052 "\\begin{document} \n "\ 0053 "%2 \n "\ 0054 "\\end{document}\n"); 0055 0056 0057 Expression::Expression( Session* session, bool internal ) : QObject( session ), 0058 d(new ExpressionPrivate) 0059 { 0060 d->session=session; 0061 d->internal = internal; 0062 if (!internal && session) 0063 d->id=session->nextExpressionId(); 0064 else 0065 d->id = -1; 0066 } 0067 0068 Expression::Expression( Session* session, bool internal, int id ) : QObject( session ), d(new ExpressionPrivate) 0069 { 0070 d->session = session; 0071 d->internal = internal; 0072 d->id = id; 0073 } 0074 0075 Expression::~Expression() 0076 { 0077 qDeleteAll(d->results); 0078 if (d->fileWatcher) 0079 delete d->fileWatcher; 0080 0081 delete d; 0082 } 0083 0084 void Expression::setCommand(const QString& command) 0085 { 0086 d->command=command; 0087 } 0088 0089 QString Expression::command() 0090 { 0091 return d->command; 0092 } 0093 0094 QString Expression::internalCommand() 0095 { 0096 return d->command; 0097 } 0098 0099 void Expression::setErrorMessage(const QString& error) 0100 { 0101 d->error=error; 0102 } 0103 0104 QString Expression::errorMessage() 0105 { 0106 return d->error; 0107 } 0108 0109 void Expression::setResult(Result* result) 0110 { 0111 clearResults(); 0112 addResult(result); 0113 } 0114 0115 void Expression::addResult(Result* result) 0116 { 0117 if(result!=nullptr) 0118 { 0119 qDebug()<<"setting result to a type "<<result->type()<<" result"; 0120 #ifdef WITH_EPS 0121 //If it's text, and latex typesetting is enabled, render it 0122 if ( session() && 0123 session()->isTypesettingEnabled()&& 0124 result->type()==TextResult::Type && 0125 static_cast<TextResult*>(result)->format()==TextResult::LatexFormat && 0126 !result->toHtml().trimmed().isEmpty() && 0127 finishingBehavior()!=DeleteOnFinish && 0128 !isInternal() 0129 ) 0130 { 0131 renderResultAsLatex(result); 0132 return; 0133 } 0134 #endif 0135 } 0136 0137 d->results << result; 0138 emit gotResult(); 0139 } 0140 0141 void Expression::clearResults() 0142 { 0143 qDeleteAll(d->results); 0144 d->results.clear(); 0145 emit resultsCleared(); 0146 } 0147 0148 void Expression::removeResult(Result* result) 0149 { 0150 int index = d->results.indexOf(result); 0151 d->results.remove(index); 0152 delete result; 0153 emit resultRemoved(index); 0154 } 0155 0156 void Expression::replaceResult(int index, Result* result) 0157 { 0158 if (result) 0159 { 0160 //insert the new result 0161 d->results.insert(index, result); 0162 0163 //delete the previous result 0164 Result* oldResult = d->results.at(index+1); 0165 d->results.remove(index+1); 0166 delete oldResult; 0167 0168 //notify about the replacement 0169 emit resultReplaced(index); 0170 } 0171 } 0172 0173 Result* Expression::result() 0174 { 0175 if (!d->results.isEmpty()) 0176 return d->results.first(); 0177 else 0178 return nullptr; 0179 } 0180 0181 const QVector<Result*>& Expression::results() const 0182 { 0183 return d->results; 0184 } 0185 0186 void Expression::setStatus(Expression::Status status) 0187 { 0188 d->status=status; 0189 emit statusChanged(status); 0190 0191 bool isFinished = status == Expression::Done || status == Expression::Error || status == Expression::Interrupted; 0192 if (isFinished) 0193 { 0194 emit expressionFinished(status); 0195 if(d->finishingBehavior==Expression::DeleteOnFinish) 0196 deleteLater(); 0197 } 0198 } 0199 0200 Expression::Status Expression::status() 0201 { 0202 return d->status; 0203 } 0204 0205 Session* Expression::session() 0206 { 0207 return d->session; 0208 } 0209 void Expression::renderResultAsLatex(Result* result) 0210 { 0211 LatexRenderer* renderer=new LatexRenderer(this); 0212 renderer->setLatexCode(result->data().toString().trimmed()); 0213 renderer->addHeader(additionalLatexHeaders()); 0214 0215 connect(renderer, &LatexRenderer::done, [=] { latexRendered(renderer, result); }); 0216 connect(renderer, &LatexRenderer::error, [=] { latexRendered(renderer, result); }); 0217 0218 renderer->render(); 0219 } 0220 0221 void Expression::latexRendered(LatexRenderer* renderer, Result* result) 0222 { 0223 qDebug()<<"rendered a result to "<<renderer->imagePath(); 0224 //replace the textresult with the rendered latex image result 0225 //ImageResult* latex=new ImageResult( d->latexFilename ); 0226 if(renderer->renderingSuccessful()) 0227 { 0228 if (result->type() == TextResult::Type) 0229 { 0230 TextResult* r = static_cast<TextResult*>(result); 0231 LatexResult* latex=new LatexResult(r->data().toString().trimmed(), QUrl::fromLocalFile(renderer->imagePath()), r->plain()); 0232 addResult( latex ); 0233 } 0234 else if (result->type() == LatexResult::Type) 0235 { 0236 LatexResult* previousLatexResult = static_cast<LatexResult*>(result); 0237 LatexResult* latex=new LatexResult(previousLatexResult->data().toString().trimmed(), QUrl::fromLocalFile(renderer->imagePath()), previousLatexResult->plain()); 0238 addResult( latex ); 0239 } 0240 }else 0241 { 0242 //if rendering with latex was not successful, just use the plain text version 0243 //if available 0244 TextResult* r=dynamic_cast<TextResult*>(result); 0245 if (r) 0246 addResult(new TextResult(r->plain())); 0247 qDebug()<<"error rendering latex: "<<renderer->errorMessage(); 0248 } 0249 0250 delete result; 0251 0252 renderer->deleteLater(); 0253 } 0254 0255 void Expression::addInformation(const QString& information) 0256 { 0257 d->information.append(information); 0258 } 0259 0260 QString Expression::additionalLatexHeaders() 0261 { 0262 return QString(); 0263 } 0264 0265 QFileSystemWatcher* Expression::fileWatcher() { 0266 if (!d->fileWatcher) 0267 d->fileWatcher = new QFileSystemWatcher(); 0268 0269 return d->fileWatcher; 0270 } 0271 0272 int Expression::id() 0273 { 0274 return d->id; 0275 } 0276 0277 void Expression::setId(int id) 0278 { 0279 d->id=id; 0280 emit idChanged(); 0281 } 0282 0283 void Expression::setFinishingBehavior(Expression::FinishingBehavior behavior) 0284 { 0285 d->finishingBehavior=behavior; 0286 } 0287 0288 Expression::FinishingBehavior Expression::finishingBehavior() 0289 { 0290 return d->finishingBehavior; 0291 } 0292 0293 bool Expression::isInternal() const 0294 { 0295 return d->internal; 0296 } 0297 0298 void Expression::setIsHelpRequest(bool value) 0299 { 0300 d->helpRequest = value; 0301 } 0302 0303 bool Expression::isHelpRequest() const 0304 { 0305 return d->helpRequest; 0306 }