File indexing completed on 2024-04-28 11:20:46

0001 /*
0002     SPDX-License-Identifier: GPL-2.0-or-later
0003     SPDX-FileCopyrightText: 2019 Sirgienko Nikita <warquark@gmail.com>
0004 */
0005 
0006 #include "htmlresult.h"
0007 
0008 #include <QFile>
0009 #include <QTextStream>
0010 #include <QJsonArray>
0011 #include <QJsonObject>
0012 #include <QJsonDocument>
0013 
0014 #include "jupyterutils.h"
0015 
0016 using namespace Cantor;
0017 
0018 class Cantor::HtmlResultPrivate
0019 {
0020 public:
0021     QString html;
0022     QString plain;
0023     std::map<QString, QJsonValue> alternatives; // Useful only for Jupyter, it think
0024     Cantor::HtmlResult::Format format{Cantor::HtmlResult::Html};
0025 };
0026 
0027 HtmlResult::HtmlResult(const QString& html, const QString& plain, const std::map<QString, QJsonValue>& alternatives) : d(new HtmlResultPrivate())
0028 {
0029     d->html = html;
0030     d->plain = plain;
0031     d->alternatives = alternatives;
0032 }
0033 
0034 HtmlResult::~HtmlResult()
0035 {
0036     delete d;
0037 }
0038 
0039 QString HtmlResult::toHtml()
0040 {
0041     switch(d->format)
0042     {
0043         case HtmlResult::Html:
0044             return d->html;
0045 
0046         case HtmlResult::HtmlSource:
0047             return QStringLiteral("<code><pre>") + d->html.toHtmlEscaped() + QStringLiteral("</pre></code>");
0048 
0049         case HtmlResult::PlainAlternative:
0050             return QStringLiteral("<pre>") + d->plain.toHtmlEscaped() + QStringLiteral("</pre>");
0051 
0052         default:
0053             return QString();
0054     }
0055 }
0056 
0057 QVariant Cantor::HtmlResult::data()
0058 {
0059     return d->html;
0060 }
0061 
0062 QString Cantor::HtmlResult::plain()
0063 {
0064     return d->plain;
0065 }
0066 
0067 void Cantor::HtmlResult::setFormat(HtmlResult::Format format)
0068 {
0069     d->format = format;
0070 }
0071 
0072 HtmlResult::Format Cantor::HtmlResult::format()
0073 {
0074     return d->format;
0075 }
0076 
0077 int Cantor::HtmlResult::type()
0078 {
0079     return HtmlResult::Type;
0080 }
0081 
0082 QString Cantor::HtmlResult::mimeType()
0083 {
0084     return QStringLiteral("text/html");
0085 }
0086 
0087 QDomElement Cantor::HtmlResult::toXml(QDomDocument& doc)
0088 {
0089     QDomElement e=doc.createElement(QStringLiteral("Result"));
0090     e.setAttribute(QStringLiteral("type"), QStringLiteral("html"));
0091     switch(d->format)
0092     {
0093         case HtmlResult::HtmlSource:
0094             e.setAttribute(QStringLiteral("format"), QStringLiteral("htmlSource"));
0095             break;
0096 
0097         case HtmlResult::PlainAlternative:
0098             e.setAttribute(QStringLiteral("format"), QStringLiteral("plain"));
0099             break;
0100 
0101         // Html format used by default, so don't set it
0102         default:
0103             break;
0104     }
0105 
0106     QDomElement plainE = doc.createElement(QStringLiteral("Plain"));
0107     plainE.appendChild(doc.createTextNode(d->plain));
0108     e.appendChild(plainE);
0109 
0110     QDomElement htmlE = doc.createElement(QStringLiteral("Html"));
0111     htmlE.appendChild(doc.createTextNode(d->html));
0112     e.appendChild(htmlE);
0113 
0114     for (auto iter = d->alternatives.begin(); iter != d->alternatives.end(); iter++)
0115     {
0116         QJsonDocument jsonDoc;
0117         QJsonObject obj;
0118         obj.insert(QLatin1String("root"), iter->second);
0119         jsonDoc.setObject(obj);
0120 
0121         QDomElement content = doc.createElement(QStringLiteral("Alternative"));
0122         content.setAttribute(QStringLiteral("key"), iter->first);
0123         content.appendChild(doc.createTextNode(QString::fromUtf8(jsonDoc.toJson())));
0124         e.appendChild(content);
0125     }
0126 
0127     return e;
0128 }
0129 
0130 QJsonValue Cantor::HtmlResult::toJupyterJson()
0131 {
0132     QJsonObject root;
0133     if (executionIndex() != -1)
0134     {
0135         root.insert(QLatin1String("output_type"), QLatin1String("execute_result"));
0136         root.insert(QLatin1String("execution_count"), executionIndex());
0137     }
0138     else
0139         root.insert(QLatin1String("output_type"), QLatin1String("display_data"));
0140 
0141 
0142     QJsonObject data;
0143     data.insert(QLatin1String("text/html"), JupyterUtils::toJupyterMultiline(d->html));
0144     if (!d->plain.isEmpty())
0145         data.insert(QLatin1String("text/plain"), JupyterUtils::toJupyterMultiline(d->plain));
0146 
0147     for (auto iter = d->alternatives.begin(); iter != d->alternatives.end(); iter++)
0148         data.insert(iter->first, iter->second);
0149 
0150     root.insert(QLatin1String("data"), data);
0151 
0152     root.insert(QLatin1String("metadata"), jupyterMetadata());
0153 
0154     return root;
0155 }
0156 
0157 void Cantor::HtmlResult::save(const QString& filename)
0158 {
0159     QFile file(filename);
0160 
0161     if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
0162         return;
0163 
0164     QTextStream stream(&file);
0165 
0166     stream<<d->html;
0167 
0168     file.close();
0169 }