Commit 863ea08e authored by Nikita Sirgienko's avatar Nikita Sirgienko
Browse files

[Jupyter] First iteration of export (saving) feature. On this moment, works...

[Jupyter] First iteration of export (saving) feature. On this moment, works only command entry (with text and image results) and makrdown entry.
parent 9a6a6398
......@@ -195,7 +195,7 @@ void CantorShell::fileOpen()
// this slot is called whenever the File->Open menu is selected,
// the Open shortcut is pressed (usually CTRL+O) or the Open toolbar
// button is clicked
QUrl url = QFileDialog::getOpenFileUrl(this, i18n("Open file"), QUrl(), i18n("Cantor Worksheet (*.cws);;Jupyter notebook (*.ipynb)"));
QUrl url = QFileDialog::getOpenFileUrl(this, i18n("Open file"), QUrl(), i18n("Cantor Worksheet (*.cws)") + QLatin1String(";;") + i18n("Jupyter Notebook (*.ipynb)"));
if (url.isEmpty() == false)
{
......
......@@ -456,8 +456,9 @@ bool CantorPart::saveFile()
void CantorPart::fileSaveAs()
{
// this slot is called whenever the File->Save As menu is selected
QString worksheetFilter = i18n("Cantor Worksheet (*.cws)");
QString filter = worksheetFilter;
static const QString& worksheetFilter = i18n("Cantor Worksheet (*.cws)");
static const QString& notebookFilter = i18n("Jupyter Notebook (*.ipynb)");
QString filter = worksheetFilter + QLatin1String(";;") + notebookFilter;
if (!m_worksheet->isReadOnly())
{
......@@ -480,6 +481,14 @@ void CantorPart::fileSaveAs()
{
if (!file_name.endsWith(QLatin1String(".cws")))
file_name += QLatin1String(".cws");
m_worksheet->setType(Worksheet::CantorWorksheet);
saveAs(QUrl::fromLocalFile(file_name));
}
else if (selectedFilter == notebookFilter)
{
if (!file_name.endsWith(QLatin1String(".ipynb")))
file_name += QLatin1String(".ipynb");
m_worksheet->setType(Worksheet::JupyterNotebook);
saveAs(QUrl::fromLocalFile(file_name));
}
else
......
......@@ -25,6 +25,8 @@
#include "loadedexpression.h"
#include "lib/result.h"
#include "lib/helpresult.h"
#include "lib/epsresult.h"
#include "lib/latexresult.h"
#include "lib/completionobject.h"
#include "lib/syntaxhelpobject.h"
#include "lib/session.h"
......@@ -39,6 +41,7 @@
#include <QGraphicsWidget>
#include <QJsonArray>
#include <QJsonObject>
#include <QBuffer>
#include <KLocalizedString>
#include <KColorScheme>
......@@ -462,6 +465,71 @@ void CommandEntry::setContentFromJupyter(const QJsonObject& cell)
setExpression(expr);
}
QJsonValue CommandEntry::toJupyterJson()
{
QJsonObject entry;
entry.insert(QLatin1String("cell_type"), QLatin1String("code"));
QJsonValue executionCountValue;
if (expression() && expression()->id() != -1)
executionCountValue = QJsonValue(expression()->id());
entry.insert(QLatin1String("execution_count"), executionCountValue);
// Jupyter TODO: support metadata info, collapsed for example
QJsonObject metadata;
entry.insert(QLatin1String("metadata"), metadata);
QJsonArray text;
const QStringList& lines = command().split(QLatin1Char('\n'));
for (int i = 0; i < lines.size(); i++)
{
QString line = lines[i];
// Don't add \n to last line
if (i != lines.size() - 1)
line.append(QLatin1Char('\n'));
text.append(line);
}
entry.insert(QLatin1String("source"), text);
QJsonArray outputs;
if (expression())
for (Cantor::Result * const result: expression()->results())
{
const QJsonValue& resultJson = result->toJupyterJson();
// Jupyter TODO: Convert EpsResult here?
if (result->type() == Cantor::EpsResult::Type || result->type() == Cantor::LatexResult::Type)
{
QJsonObject root;
root.insert(QLatin1String("output_type"), QLatin1String("display_data"));
QJsonObject data;
data.insert(QLatin1String("text/plain"), QString());
const QImage& image = worksheet()->epsRenderer()->renderToImage(result->data().toUrl());
QByteArray ba;
QBuffer buffer(&ba);
buffer.open(QIODevice::WriteOnly);
image.save(&buffer, "PNG");
data.insert(QLatin1String("image/png"), QString::fromLatin1(ba.toBase64()));
root.insert(QLatin1String("data"), data);
// Jupyter TODO: handle metadata?
root.insert(QLatin1String("metadata"), QJsonObject());
outputs.append(root);
}
else if (!resultJson.isNull())
outputs.append(resultJson);
}
entry.insert(QLatin1String("outputs"), outputs);
return entry;
}
void CommandEntry::showCompletion()
{
......
......@@ -64,9 +64,10 @@ class CommandEntry : public WorksheetEntry
void setContent(const QString& content) override;
void setContent(const QDomElement& content, const KZip& file) override;
void setContentFromJupyter(const QJsonObject& cell);
void setContentFromJupyter(const QJsonObject& cell) override;
QDomElement toXml(QDomDocument& doc, KZip* archive) override;
QJsonValue toJupyterJson() override;
QString toPlain(const QString& commandSep, const QString& commentStartingSeq, const QString& commentEndingSeq) override;
void setCompletion(Cantor::CompletionObject* tc);
......
......@@ -26,6 +26,7 @@
#include <QDebug>
#include <QMenu>
#include <QFileSystemWatcher>
#include <QJsonValue>
ImageEntry::ImageEntry(Worksheet* worksheet) : WorksheetEntry(worksheet)
{
......@@ -101,6 +102,17 @@ void ImageEntry::setContent(const QDomElement& content, const KZip& file)
updateEntry();
}
void ImageEntry::setContentFromJupyter(const QJsonObject& cell)
{
// Jupyter TODO: Add realization
}
QJsonValue ImageEntry::toJupyterJson()
{
// Jupyter TODO: Add realization
return QJsonValue();
}
QDomElement ImageEntry::toXml(QDomDocument& doc, KZip* archive)
{
Q_UNUSED(archive);
......
......@@ -46,7 +46,9 @@ class ImageEntry : public WorksheetEntry
bool acceptRichText() override;
void setContent(const QString& content) override;
void setContent(const QDomElement& content, const KZip& file) override;
void setContentFromJupyter(const QJsonObject & cell) override;
QDomElement toXml(QDomDocument& doc, KZip* archive) override;
QJsonValue toJupyterJson() override;
QString toPlain(const QString& commandSep, const QString& commentStartingSeq, const QString& commentEndingSeq) override;
QSizeF imageSize(const ImageSize& imgSize);
......
......@@ -34,6 +34,7 @@
#include <QDebug>
#include <QBuffer>
#include <QUuid>
#include <QJsonValue>
#include <KLocalizedString>
LatexEntry::LatexEntry(Worksheet* worksheet) : WorksheetEntry(worksheet), m_textItem(new WorksheetTextItem(this, Qt::TextEditorInteraction))
......@@ -171,6 +172,17 @@ void LatexEntry::setContent(const QDomElement& content, const KZip& file)
cursor.insertText(latexCode);
}
void LatexEntry::setContentFromJupyter(const QJsonObject& cell)
{
// Jupyter TODO: Add realization
}
QJsonValue LatexEntry::toJupyterJson()
{
// Jupyter TODO: Add realization
return QJsonValue();
}
QDomElement LatexEntry::toXml(QDomDocument& doc, KZip* archive)
{
QDomElement el = doc.createElement(QLatin1String("Latex"));
......
......@@ -44,8 +44,10 @@ class LatexEntry : public WorksheetEntry
void setContent(const QString& content) override;
void setContent(const QDomElement& content, const KZip& file) override;
void setContentFromJupyter(const QJsonObject & cell) override;
QDomElement toXml(QDomDocument& doc, KZip* archive) override;
QJsonValue toJupyterJson() override;
QString toPlain(const QString& commandSep, const QString& commentStartingSeq, const QString& commentEndingSeq) override;
void interruptEvaluation() override;
......
......@@ -93,6 +93,12 @@ QDomElement AnimationResult::toXml(QDomDocument& doc)
return e;
}
QJsonValue Cantor::AnimationResult::toJupyterJson()
{
// Jupyter TODO: add support for this result type
return QJsonValue();
}
void AnimationResult::saveAdditionalData(KZip* archive)
{
archive->addLocalFile(d->url.toLocalFile(), d->url.fileName());
......
......@@ -42,6 +42,7 @@ class CANTOR_EXPORT AnimationResult : public Result
QString mimeType() override;
QDomElement toXml(QDomDocument& doc) override;
QJsonValue toJupyterJson() override;
void saveAdditionalData(KZip* archive) override;
void save(const QString& filename) override;
......
......@@ -24,6 +24,8 @@ using namespace Cantor;
#include <config-cantorlib.h>
#include <QDebug>
#include <QJsonValue>
#include <KZip>
#include <KIO/Job>
......@@ -87,6 +89,15 @@ QDomElement EpsResult::toXml(QDomDocument& doc)
return e;
}
QJsonValue Cantor::EpsResult::toJupyterJson()
{
// Juputer TODO: Technically, I could convert .eps file to Image via EpsRenderer
// But EpsRender don't available from Cantor core library
// I will handle this result type in worksheet, but it's not look nice...
return QJsonValue();
}
void EpsResult::saveAdditionalData(KZip* archive)
{
archive->addLocalFile(d->url.toLocalFile(), d->url.fileName());
......
......@@ -45,6 +45,7 @@ class CANTOR_EXPORT EpsResult : public Result
QString mimeType() override;
QDomElement toXml(QDomDocument& doc) override;
QJsonValue toJupyterJson() override;
void saveAdditionalData(KZip* archive) override;
void save(const QString& filename) override;
......
......@@ -18,6 +18,8 @@
Copyright (C) 2009 Alexander Rieder <alexanderrieder@gmail.com>
*/
#include <QJsonValue>
#include "helpresult.h"
using namespace Cantor;
......@@ -58,6 +60,12 @@ QDomElement HelpResult::toXml(QDomDocument& doc)
return e;
}
QJsonValue Cantor::HelpResult::toJupyterJson()
{
// No need to save help result
return QJsonValue();
}
QString HelpResult::toHtml()
{
return d->html;
......
......@@ -45,6 +45,7 @@ class CANTOR_EXPORT HelpResult: public Result
QString mimeType() override;
QDomElement toXml(QDomDocument& doc) override;
QJsonValue toJupyterJson() override;
void save(const QString& filename) override;
private:
......
......@@ -25,6 +25,7 @@ using namespace Cantor;
#include <QImageWriter>
#include <KZip>
#include <QDebug>
#include <QBuffer>
class Cantor::ImageResultPrivate
{
......@@ -99,6 +100,35 @@ QDomElement ImageResult::toXml(QDomDocument& doc)
return e;
}
QJsonValue Cantor::ImageResult::toJupyterJson()
{
QJsonObject root;
root.insert(QLatin1String("output_type"), QLatin1String("display_data"));
QJsonObject data;
data.insert(QLatin1String("text/plain"), d->alt);
QImage image;
if (d->img.isNull())
image.load(d->url.toLocalFile());
else
image = d->img;
QByteArray ba;
QBuffer buffer(&ba);
buffer.open(QIODevice::WriteOnly);
image.save(&buffer, "PNG");
data.insert(QLatin1String("image/png"), QString::fromLatin1(ba.toBase64()));
root.insert(QLatin1String("data"), data);
// Jupyter TODO: handle metadata?
root.insert(QLatin1String("metadata"), QJsonObject());
return root;
}
void ImageResult::saveAdditionalData(KZip* archive)
{
archive->addLocalFile(d->url.toLocalFile(), d->url.fileName());
......
......@@ -44,6 +44,7 @@ class CANTOR_EXPORT ImageResult : public Result
QString mimeType() override;
QDomElement toXml(QDomDocument& doc) override;
QJsonValue toJupyterJson() override;
void saveAdditionalData(KZip* archive) override;
void save(const QString& filename) override;
......
......@@ -23,6 +23,7 @@ using namespace Cantor;
#include <QFile>
#include <QTextStream>
#include <QJsonValue>
#include <QDebug>
class Cantor::LatexResultPrivate
......@@ -127,6 +128,11 @@ QDomElement LatexResult::toXml(QDomDocument& doc)
return e;
}
QJsonValue Cantor::LatexResult::toJupyterJson()
{
return QJsonValue();
}
void LatexResult::save(const QString& filename)
{
if(isCodeShown())
......
......@@ -38,7 +38,7 @@ class CANTOR_EXPORT LatexResult : public EpsResult
enum {Type=7};
LatexResult( const QString& code, const QUrl& url, const QString& plain = QString());
~LatexResult() override;
int type() override;
QString mimeType() override;
......@@ -54,7 +54,8 @@ class CANTOR_EXPORT LatexResult : public EpsResult
QVariant data() override;
QDomElement toXml(QDomDocument& doc) override;
QJsonValue toJupyterJson() override;
void save(const QString& filename) override;
private:
......
......@@ -99,6 +99,10 @@ class CANTOR_EXPORT Result
*/
virtual void saveAdditionalData(KZip* archive);
/**
* return a Jupyter json object, containing the information of the result
*/
virtual QJsonValue toJupyterJson() = 0;
/**
* saves this to a file
* @param filename name of the file
......
......@@ -25,6 +25,8 @@ using namespace Cantor;
#include <QFile>
#include <QTextStream>
#include <QJsonArray>
#include <QJsonObject>
QString rtrim(const QString& s)
{
......@@ -120,6 +122,30 @@ QDomElement TextResult::toXml(QDomDocument& doc)
return e;
}
QJsonValue Cantor::TextResult::toJupyterJson()
{
QJsonObject root;
root.insert(QLatin1String("output_type"), QLatin1String("stream"));
// Jupyter TODO: what about stderr?
root.insert(QLatin1String("name"), QLatin1String("stdout"));
QJsonArray text;
// Jupyter TODO: use data? Or toHtml?
const QStringList& lines = d->data.split(QLatin1Char('\n'));
for (int i = 0; i < lines.size(); i++)
{
QString line = lines[i];
// Don't add \n to last line
if (i != lines.size() - 1)
line.append(QLatin1Char('\n'));
text.append(line);
}
root.insert(QLatin1String("text"), text);
return root;
}
void TextResult::save(const QString& filename)
{
QFile file(filename);
......
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