Warning, file /education/parley/src/practice/latexrenderer.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-FileCopyrightText: 2010 Daniel Laidig <laidig@kde.org> 0003 SPDX-FileCopyrightText: 2009 Alexander Rieder <alexanderrieder@gmail.com> 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "latexrenderer.h" 0008 0009 #include <KLocalizedString> 0010 #include <KProcess> 0011 #include <QColor> 0012 #include <QDebug> 0013 #include <QFileInfo> 0014 #include <QGuiApplication> 0015 #include <QLabel> 0016 #include <QTemporaryDir> 0017 #include <QTemporaryFile> 0018 #include <QtGlobal> 0019 #include <complex> 0020 0021 using namespace Practice; 0022 0023 const char *texTemplate = 0024 "\\documentclass[12pt,fleqn]{article} \n " 0025 "\\usepackage{latexsym,amsfonts,amssymb,ulem} \n " 0026 "\\usepackage[dvips]{graphicx} \n " 0027 "\\setlength\\textwidth{5in} \n " 0028 "\\setlength{\\parindent}{0pt} \n " 0029 "\\usepackage{amsmath} \n " 0030 "\\usepackage{color} \n " 0031 "\\pagestyle{empty} \n " 0032 "\\begin{document} \n " 0033 "{\\definecolor{mycolor}{rgb}{%1} \n " 0034 "{\\color{mycolor} \n " 0035 "%2 } \n " 0036 "\\end{document}\n"; 0037 0038 LatexRenderer::LatexRenderer(QObject *parent) 0039 : QObject(parent) 0040 { 0041 } 0042 0043 void LatexRenderer::renderLatex(QString tex) 0044 { 0045 if (m_label) { 0046 m_label->setText(i18n("Rendering...")); 0047 m_label->setToolTip(tex); 0048 } 0049 0050 if (tex.startsWith(QLatin1String("$$"))) { 0051 tex.replace(0, 2, QStringLiteral("\\begin{eqnarray*}")).remove(-2, 2).append("\\end{eqnarray*}"); 0052 } else { 0053 tex.remove(0, 2).remove(-2, 2); 0054 } 0055 qDebug() << "rendering as latex"; 0056 0057 // Check if the parley subdir exists, if not, create it 0058 QString dir(QDir::tempPath() + QLatin1Char('/') + QCoreApplication::applicationName()); 0059 QTemporaryFile *texFile = new QTemporaryFile(dir + QLatin1Char('/') + QLatin1String("XXXXXX") + ".tex"); 0060 if (!texFile->open()) { 0061 return; 0062 } 0063 0064 QColor color = QGuiApplication::palette().color(QPalette::WindowText); 0065 QString colorString = QString::number(color.redF()) + ',' + QString::number(color.greenF()) + ',' + QString::number(color.blueF()); 0066 QString expressionTex = QString(texTemplate).arg(colorString, tex.trimmed()); 0067 0068 texFile->write(expressionTex.toUtf8()); 0069 texFile->flush(); 0070 0071 QString fileName = texFile->fileName(); 0072 qDebug() << "fileName: " << fileName; 0073 m_latexFilename = fileName; 0074 m_latexFilename.replace(QLatin1String(".tex"), QLatin1String(".eps")); 0075 KProcess *p = new KProcess(this); 0076 p->setWorkingDirectory(dir); 0077 0078 (*p) << QStringLiteral("latex") << QStringLiteral("-interaction=batchmode") << QStringLiteral("-halt-on-error") << fileName; 0079 0080 connect(p, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, &LatexRenderer::convertToPs); 0081 connect(p, &QProcess::errorOccurred, this, &LatexRenderer::latexRendered); 0082 p->start(); 0083 } 0084 0085 bool LatexRenderer::isLatex(const QString &tex) 0086 { 0087 return tex.length() > 4 && tex.mid(2, tex.length() - 4).simplified().length() > 0 0088 && ((tex.startsWith(QLatin1String("$$")) && tex.endsWith(QLatin1String("$$"))) 0089 || (tex.startsWith(QStringLiteral("§§")) && tex.endsWith(QStringLiteral("§§")))); 0090 } 0091 0092 void LatexRenderer::convertToPs() 0093 { 0094 qDebug() << "converting to ps"; 0095 QString dviFile = m_latexFilename; 0096 dviFile.replace(QLatin1String(".eps"), QLatin1String(".dvi")); 0097 KProcess *p = new KProcess(this); 0098 qDebug() << "running: " 0099 << "dvips" 0100 << "-E" 0101 << "-o" << m_latexFilename << dviFile; 0102 (*p) << QStringLiteral("dvips") << QStringLiteral("-E") << QStringLiteral("-o") << m_latexFilename << dviFile; 0103 0104 connect(p, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, &LatexRenderer::convertToImage); 0105 connect(p, &QProcess::errorOccurred, this, &LatexRenderer::latexRendered); 0106 p->start(); 0107 } 0108 0109 void LatexRenderer::convertToImage() 0110 { 0111 qDebug() << "converting to ps"; 0112 QString pngFile = m_latexFilename; 0113 pngFile.replace(QLatin1String(".eps"), QLatin1String(".png")); 0114 KProcess *p = new KProcess(this); 0115 qDebug() << "running:" 0116 << "convert" << m_latexFilename << pngFile; 0117 (*p) << QStringLiteral("convert") << QStringLiteral("-density") << QStringLiteral("85") << m_latexFilename << pngFile; 0118 0119 connect(p, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, &LatexRenderer::latexRendered); 0120 connect(p, &QProcess::errorOccurred, this, &LatexRenderer::latexRendered); 0121 p->start(); 0122 } 0123 0124 void LatexRenderer::latexRendered() 0125 { 0126 qDebug() << "rendered file " << m_latexFilename; 0127 0128 QString pngFile = m_latexFilename; 0129 pngFile.replace(QLatin1String(".eps"), QLatin1String(".png")); 0130 if (QFileInfo::exists(pngFile)) { 0131 QPixmap pixmap(pngFile); 0132 m_label->setPixmap(pixmap); 0133 m_label->setMinimumSize(pixmap.size().boundedTo(QSize(600, 300))); 0134 } else { 0135 m_label->setText(i18n("LaTeX error.")); // TODO: better error handling and error messages 0136 } 0137 0138 // cleanup the temp directory a bit... 0139 QStringList extensions; 0140 extensions << QStringLiteral(".log") << QStringLiteral(".aux") << QStringLiteral(".tex") << QStringLiteral(".dvi") << QStringLiteral(".eps") 0141 << QStringLiteral(".png"); 0142 for (const QString &ext : qAsConst(extensions)) { 0143 QString s = m_latexFilename; 0144 s.replace(QLatin1String(".eps"), ext); 0145 QFile f(s); 0146 f.remove(); 0147 } 0148 }