Commit 4d60bb3b authored by Nikita Sirgienko's avatar Nikita Sirgienko
Browse files

[Jupyter] Some fixes for embeded math in MarkdownEntry and TextEntry

parent c1a05e3d
......@@ -153,46 +153,58 @@ void MarkdownEntry::setContent(const QDomElement& content, const KZip& file)
// Handle math after setting html
const QDomNodeList& maths = content.elementsByTagName(QLatin1String("EmbeddedMath"));
foundMath.clear();
for (int i = 0; i < maths.count(); i++)
{
const QDomElement& math = maths.at(i).toElement();
bool mathRendered = math.attribute(QLatin1String("rendered")).toInt();
const QString mathCode = math.text();
foundMath.push_back(std::make_pair(mathCode, mathRendered));
foundMath.push_back(std::make_pair(mathCode, false));
}
if (rendered)
{
markUpMath();
if (rendered && mathRendered)
for (int i = 0; i < maths.count(); i++)
{
const KArchiveEntry* imageEntry=file.directory()->entry(math.attribute(QLatin1String("path")));
if (imageEntry && imageEntry->isFile())
const QDomElement& math = maths.at(i).toElement();
bool mathRendered = math.attribute(QLatin1String("rendered")).toInt();
const QString mathCode = math.text();
if (mathRendered)
{
const KArchiveFile* imageFile=static_cast<const KArchiveFile*>(imageEntry);
const QString& dir=QStandardPaths::writableLocation(QStandardPaths::TempLocation);
imageFile->copyTo(dir);
const QString& pdfPath = dir + QDir::separator() + imageFile->name();
QString latex;
Cantor::LatexRenderer::EquationType type;
std::tie(latex, type) = parseMathCode(mathCode);
// Get uuid by removing 'cantor_' and '.pdf' extention
// len('cantor_') == 7, len('.pdf') == 4
QString uuid = pdfPath;
uuid.remove(0, 7);
uuid.chop(4);
bool success;
const auto& data = worksheet()->mathRenderer()->renderExpressionFromPdf(pdfPath, uuid, latex, type, &success);
if (success)
const KArchiveEntry* imageEntry=file.directory()->entry(math.attribute(QLatin1String("path")));
if (imageEntry && imageEntry->isFile())
{
QUrl internal;
internal.setScheme(QLatin1String("internal"));
internal.setPath(uuid);
setRenderedMath(data.first, internal, data.second);
const KArchiveFile* imageFile=static_cast<const KArchiveFile*>(imageEntry);
const QString& dir=QStandardPaths::writableLocation(QStandardPaths::TempLocation);
imageFile->copyTo(dir);
const QString& pdfPath = dir + QDir::separator() + imageFile->name();
QString latex;
Cantor::LatexRenderer::EquationType type;
std::tie(latex, type) = parseMathCode(mathCode);
// Get uuid by removing 'cantor_' and '.pdf' extention
// len('cantor_') == 7, len('.pdf') == 4
QString uuid = pdfPath;
uuid.remove(0, 7);
uuid.chop(4);
bool success;
const auto& data = worksheet()->mathRenderer()->renderExpressionFromPdf(pdfPath, uuid, latex, type, &success);
if (success)
{
QUrl internal;
internal.setScheme(QLatin1String("internal"));
internal.setPath(uuid);
setRenderedMath(i+1, data.first, internal, data.second);
}
}
else
renderMathExpression(i+1, mathCode);
}
else
renderMathExpression(mathCode);
}
}
}
......@@ -283,7 +295,6 @@ QDomElement MarkdownEntry::toXml(QDomDocument& doc, KZip* archive)
if (code == data.first)
{
const QUrl& url = QUrl::fromLocalFile(format.property(EpsRenderer::ImagePath).toString());
qDebug() << QFile::exists(url.toLocalFile());
archive->addLocalFile(url.toLocalFile(), url.fileName());
mathEl.setAttribute(QStringLiteral("path"), url.fileName());
foundNeededImage = true;
......@@ -352,6 +363,9 @@ bool MarkdownEntry::evaluate(EvaluationOption evalOp)
{
setRenderedHtml(html);
rendered = true;
for (auto iter = foundMath.begin(); iter != foundMath.end(); iter++)
iter->second = false;
markUpMath();
}
else
{
......@@ -386,16 +400,17 @@ bool MarkdownEntry::renderMarkdown(QString& plain)
int latexDataSize = mkd_latextext(mdHandle, &latexData);
QStringList latexUnits = QString::fromUtf8(latexData, latexDataSize).split(QLatin1Char(31), QString::SkipEmptyParts);
foundMath.clear();
for (const QString& latex : latexUnits)
{
foundMath.push_back(std::make_pair(latex, false));
html.replace(latex, latex.toHtmlEscaped());
}
qDebug() << "founded math:" << foundMath;
mkd_cleanup(mdHandle);
setRenderedHtml(html);
QTextCursor cursor(m_textItem->document());
for (const QString& latex : latexUnits)
foundMath.push_back(std::make_pair(latex, false));
markUpMath();
return true;
#else
Q_UNUSED(plain);
......@@ -503,26 +518,10 @@ void MarkdownEntry::resolveImagesAtCursor()
void MarkdownEntry::renderMath()
{
// Jupyter TODO: what about \( \) and \[ \]? Supports or not?
QTextCursor cursor(m_textItem->document());
cursor.movePosition(QTextCursor::Start);
for (std::pair<QString, bool> pair : foundMath)
{
// Jupyter TODO: what about \( \) and \[ \]? Supports or not?
QString searchText = pair.first;
searchText.replace(QRegExp(QLatin1String("\\s+")), QLatin1String(" "));
QTextCursor found = m_textItem->document()->find(searchText, cursor);
if (found.isNull())
continue;
cursor = found;
QString latexCode = cursor.selectedText();
latexCode.replace(QChar::ParagraphSeparator, QLatin1Char('\n'));
latexCode.replace(QChar::LineSeparator, QLatin1Char('\n'));
qDebug()<<"found latex: " << latexCode;
renderMathExpression(latexCode);
}
for (int i = 0; i < (int)foundMath.size(); i++)
renderMathExpression(i+1, foundMath[i].first);
}
void MarkdownEntry::handleMathRender(QSharedPointer<MathRenderResult> result)
......@@ -533,16 +532,16 @@ void MarkdownEntry::handleMathRender(QSharedPointer<MathRenderResult> result)
return;
}
setRenderedMath(result->renderedMath, result->uniqueUrl, result->image);
setRenderedMath(result->jobId, result->renderedMath, result->uniqueUrl, result->image);
}
void MarkdownEntry::renderMathExpression(QString mathCode)
void MarkdownEntry::renderMathExpression(int jobId, QString mathCode)
{
QString latex;
Cantor::LatexRenderer::EquationType type;
std::tie(latex, type) = parseMathCode(mathCode);
if (!latex.isNull())
worksheet()->mathRenderer()->renderExpression(latex, type, this, SLOT(handleMathRender(QSharedPointer<MathRenderResult>)));
worksheet()->mathRenderer()->renderExpression(jobId, latex, type, this, SLOT(handleMathRender(QSharedPointer<MathRenderResult>)));
}
std::pair<QString, Cantor::LatexRenderer::EquationType> MarkdownEntry::parseMathCode(QString mathCode)
......@@ -568,28 +567,62 @@ std::pair<QString, Cantor::LatexRenderer::EquationType> MarkdownEntry::parseMath
return std::make_pair(QString(), Cantor::LatexRenderer::InlineEquation);
}
void MarkdownEntry::setRenderedMath(const QTextImageFormat& format, const QUrl& internal, const QImage& image)
void MarkdownEntry::setRenderedMath(int jobId, const QTextImageFormat& format, const QUrl& internal, const QImage& image)
{
const QString& code = format.property(EpsRenderer::Code).toString();
const QString& delimiter = format.property(EpsRenderer::Delimiter).toString();
QString searchText = delimiter + code + delimiter;
searchText.replace(QRegExp(QLatin1String("\\s")), QLatin1String(" "));
if ((int)foundMath.size() < jobId)
return;
const auto& iter = foundMath.begin() + jobId-1;
QTextCursor cursor = findMath(jobId);
QString searchText = iter->first;
searchText.replace(QRegExp(QLatin1String("\\s+")), QLatin1String(" "));
cursor = m_textItem->document()->find(searchText, cursor);
QTextCursor cursor = m_textItem->document()->find(searchText);
if (!cursor.isNull())
{
m_textItem->document()->addResource(QTextDocument::ImageResource, internal, QVariant(image));
cursor.insertText(QString(QChar::ObjectReplacementCharacter), format);
// Set that the formulas is rendered
for (auto iter = foundMath.begin(); iter != foundMath.end(); iter++)
{
const QString& formulas = delimiter + code + delimiter;
if (iter->first == formulas)
{
iter->second = true;
break;
}
}
iter->second = true;
}
}
QTextCursor MarkdownEntry::findMath(int id)
{
QTextCursor cursor(m_textItem->document());
do
{
QTextCharFormat format = cursor.charFormat();
if (format.intProperty(10000) == id)
break;
}
while (cursor.movePosition(QTextCursor::NextCharacter));
// Jupyter TODO: fix it
if (cursor.position() != 0)
cursor.movePosition(QTextCursor::PreviousCharacter);
return cursor;
}
void MarkdownEntry::markUpMath()
{
QTextCursor cursor(m_textItem->document());
for (int i = 0; i < (int)foundMath.size(); i++)
{
if (foundMath[i].second)
continue;
QString searchText = foundMath[i].first;
searchText.replace(QRegExp(QLatin1String("\\s+")), QLatin1String(" "));
cursor = m_textItem->document()->find(searchText, cursor);
QTextCharFormat format = cursor.charFormat();
// Use index+1 in math array as property tag
format.setProperty(10000, i+1);
cursor.setCharFormat(format);
}
}
......@@ -78,8 +78,10 @@ class MarkdownEntry : public WorksheetEntry
void setRenderedHtml(const QString& html);
void setPlainText(const QString& plain);
void renderMath();
void renderMathExpression(QString mathCode);
void setRenderedMath(const QTextImageFormat& format, const QUrl& internal, const QImage& image);
void renderMathExpression(int jobId, QString mathCode);
void setRenderedMath(int jobId, const QTextImageFormat& format, const QUrl& internal, const QImage& image);
QTextCursor findMath(int id);
void markUpMath();
static std::pair<QString, Cantor::LatexRenderer::EquationType> parseMathCode(QString mathCode);
......
......@@ -59,9 +59,9 @@ void MathRenderer::useHighResolution(bool b)
m_useHighRes = b;
}
void MathRenderer::renderExpression(const QString& mathExpression, Cantor::LatexRenderer::EquationType type, const QObject* receiver, const char* resultHandler)
void MathRenderer::renderExpression(int jobId, const QString& mathExpression, Cantor::LatexRenderer::EquationType type, const QObject* receiver, const char* resultHandler)
{
MathRenderTask* task = new MathRenderTask(mathExpression, type, m_scale, m_useHighRes, &popplerMutex);
MathRenderTask* task = new MathRenderTask(jobId, mathExpression, type, m_scale, m_useHighRes, &popplerMutex);
task->setHandler(receiver, resultHandler);
task->setAutoDelete(false);
......
......@@ -51,6 +51,7 @@ class MathRenderer : public QObject {
* receiver will be managed about pointer, task only create it
*/
void renderExpression(
int jobId,
const QString& mathExpression,
Cantor::LatexRenderer::EquationType type,
const QObject *receiver,
......
......@@ -59,12 +59,13 @@ static const QLatin1String eqnHeader("$\\displaystyle %1$");
static const QLatin1String inlineEqnHeader("$%1$");
MathRenderTask::MathRenderTask(
int jobId,
const QString& code,
Cantor::LatexRenderer::EquationType type,
double scale,
bool highResolution,
QMutex* mutex
): m_code(code), m_type(type), m_scale(scale), m_highResolution(highResolution), m_mutex(mutex)
): m_jobId(jobId), m_code(code), m_type(type), m_scale(scale), m_highResolution(highResolution), m_mutex(mutex)
{}
void MathRenderTask::setHandler(const QObject* receiver, const char* resultHandler)
......@@ -168,6 +169,7 @@ void MathRenderTask::run()
result->renderedMath = data.first;
result->image = data.second;
result->jobId = m_jobId;
QUrl internal;
internal.setScheme(QLatin1String("internal"));
......
......@@ -34,6 +34,7 @@ class QMutex;
struct MathRenderResult
{
int jobId;
bool successfull;
QString errorMessage;
QTextImageFormat renderedMath;
......@@ -48,6 +49,7 @@ class MathRenderTask : public QObject, public QRunnable
Q_OBJECT
public:
MathRenderTask(
int jobId,
const QString& code,
Cantor::LatexRenderer::EquationType type,
double scale,
......@@ -83,6 +85,7 @@ class MathRenderTask : public QObject, public QRunnable
void finalize(QSharedPointer<MathRenderResult> result);
private:
int m_jobId;
QString m_code;
Cantor::LatexRenderer::EquationType m_type;
double m_scale;
......
......@@ -280,6 +280,7 @@ void TextEntry::interruptEvaluation()
bool TextEntry::evaluate(EvaluationOption evalOp)
{
int i = 0;
if (worksheet()->embeddedMathEnabled())
{
// Render math in $$...$$ via Latex
......@@ -295,7 +296,8 @@ bool TextEntry::evaluate(EvaluationOption evalOp)
latexCode.replace(QChar::LineSeparator, QLatin1Char('\n'));
MathRenderer* renderer = worksheet()->mathRenderer();
renderer->renderExpression(latexCode, Cantor::LatexRenderer::InlineEquation, this, SLOT(handleMathRender(QSharedPointer<MathRenderResult>)));
renderer->renderExpression(++i, latexCode, Cantor::LatexRenderer::InlineEquation, this, SLOT(handleMathRender(QSharedPointer<MathRenderResult>)));
qDebug() << i;
cursor = findLatexCode(cursor);
}
......@@ -313,16 +315,9 @@ void TextEntry::updateEntry()
while(!cursor.isNull())
{
QTextImageFormat format=cursor.charFormat().toImageFormat();
if (format.hasProperty(EpsRenderer::CantorFormula))
{
qDebug() << "found a formula... rendering the eps...";
const QUrl& url=QUrl::fromLocalFile(format.property(EpsRenderer::ImagePath).toString());
QSizeF s = worksheet()->epsRenderer()->renderToResource(m_textItem->document(), url, QUrl(format.name()));
qDebug() << "rendering successful? " << s.isValid();
//cursor.deletePreviousChar();
//cursor.insertText(QString(QChar::ObjectReplacementCharacter), format);
}
if (format.hasProperty(EpsRenderer::CantorFormula))
worksheet()->mathRenderer()->rerender(m_textItem->document(), format);
cursor = m_textItem->document()->find(QString(QChar::ObjectReplacementCharacter), cursor);
}
......@@ -469,14 +464,11 @@ void TextEntry::handleMathRender(QSharedPointer<MathRenderResult> result)
}
const QString& code = result->renderedMath.property(EpsRenderer::Code).toString();
// Jupyter TODO: add support for $...$ math and starts use
// result->renderedMath.property(EpsRenderer::Delimiter).toString();
const QString& delimiter = QLatin1String("$$");
QTextCursor cursor = m_textItem->document()->find(delimiter + code + delimiter);
if (!cursor.isNull())
{
m_textItem->document()->addResource(QTextDocument::ImageResource, result->uniqueUrl, QVariant(result->image));
// Jupyter TODO: add support for $...$ math and don't change delimiter here (needed for image resolving)
result->renderedMath.setProperty(EpsRenderer::Delimiter, QLatin1String("$$"));
cursor.insertText(QString(QChar::ObjectReplacementCharacter), result->renderedMath);
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment