blob: 36cc0a307953c228d64f2eb6c6570274fc84deed [file] [log] [blame]
swissChili25620b02022-02-23 17:15:16 -08001#include "Notebook.h"
2#include "CellModel.h"
swissChilid85daa92022-02-24 15:29:02 -08003#include "../PPrint.h"
swissChili25620b02022-02-23 17:15:16 -08004
swissChili505de412022-03-24 12:35:08 -07005#include <QJsonObject>
6#include <QJsonArray>
7#include <QFileDialog>
swissChilid2af6ad2022-04-16 14:42:17 -07008#include <QDebug>
swissChili505de412022-03-24 12:35:08 -07009
swissChili5d3e5562022-02-24 16:49:19 -080010// TODO: avoid potential race condition if Cell is deleted, pass by value with same UUID instead
11
swissChili732628e2022-02-25 10:35:56 -080012Notebook::~Notebook()
13{
14 _rtThread->quit();
15 _rtThread->wait();
swissChiliece1ac82022-02-25 11:20:42 -080016
17 delete _rt;
swissChili732628e2022-02-25 10:35:56 -080018}
19
swissChili25620b02022-02-23 17:15:16 -080020Notebook::Notebook(QObject *parent)
21 : QObject(parent)
22 , _cellModel(new CellModel(this))
swissChili732628e2022-02-25 10:35:56 -080023 , _rtThread(new QThread(this))
swissChiliece1ac82022-02-25 11:20:42 -080024 , _rt(new NbRuntime)
swissChili25620b02022-02-23 17:15:16 -080025{
swissChili732628e2022-02-25 10:35:56 -080026 connect(_rt, &NbRuntime::cellFailedToParse, this, &Notebook::cellFailedToParse);
27 connect(_rt, &NbRuntime::cellFinishedRunning, this, &Notebook::cellFinishedRunning);
28 connect(_rt, &NbRuntime::cellQuit, this, &Notebook::cellQuit);
29 connect(_rt, &NbRuntime::cellRunning, this, &Notebook::cellRunning);
30 connect(_rt, &NbRuntime::cellWaiting, this, &Notebook::cellWaiting);
swissChili25620b02022-02-23 17:15:16 -080031
swissChili732628e2022-02-25 10:35:56 -080032 _rt->moveToThread(_rtThread);
33 _rtThread->start();
swissChili25620b02022-02-23 17:15:16 -080034}
35
36Notebook::Notebook(const Notebook &other, QObject *parent)
swissChilid85daa92022-02-24 15:29:02 -080037 : Notebook(parent)
swissChili25620b02022-02-23 17:15:16 -080038{
swissChilid85daa92022-02-24 15:29:02 -080039 for (const Cell *cell : other._cells)
40 {
41 _cells.append(new Cell(*cell, this));
42 }
swissChili25620b02022-02-23 17:15:16 -080043}
44
45CellModel *Notebook::cellModel()
46{
47 return _cellModel;
48}
swissChilid85daa92022-02-24 15:29:02 -080049
50void Notebook::runCell(QUuid uuid)
51{
52 qInfo() << "Running cell" << uuid;
swissChili732628e2022-02-25 10:35:56 -080053 _rt->queueCell(Cell::cellFromUuid(uuid));
swissChilid85daa92022-02-24 15:29:02 -080054}
55
56void Notebook::quitCell(QUuid uuid)
57{
swissChili732628e2022-02-25 10:35:56 -080058 _rt->unqueueCell(Cell::cellFromUuid(uuid));
swissChilid85daa92022-02-24 15:29:02 -080059}
60
swissChilid2af6ad2022-04-16 14:42:17 -070061void Notebook::fromJson(QJsonDocument doc)
62{
63 QJsonObject nb = doc.object();
64 QJsonArray cellArray = nb["cells"].toArray();
65
66 for (const QJsonValueRef &cell : cellArray)
67 {
68 cellModel()->insertCellBefore(cellModel()->rowCount());
69 _cells.last()->fromJson(cell.toObject());
70 }
71}
72
73void Notebook::open(QString path)
74{
75 QFile file(path);
76
77 if (file.exists())
78 {
79 file.open(QFile::ReadOnly);
80
81 QJsonParseError error;
82 QJsonDocument doc = QJsonDocument::fromJson(file.readAll(), &error);
83
84 if (error.error == QJsonParseError::NoError)
85 {
86 fromJson(doc);
87 }
88 else
89 {
90 qWarning() << error.errorString();
91 }
92
93 file.close();
94 setSavePath(path);
95 }
96 else
97 {
98 qWarning() << "File does not exist" << path;
99 }
100}
101
swissChili505de412022-03-24 12:35:08 -0700102QJsonDocument Notebook::toJson() const
103{
104 QJsonObject nb;
105 QJsonArray cellArray;
106
107 for (const Cell *cell : _cells)
108 {
109 cellArray.append(cell->toJson());
110 }
111
112 nb["cells"] = cellArray;
113
114 return QJsonDocument(nb);
115}
116
117void Notebook::save()
118{
119 if (_savePath == "")
120 {
121 setSavePath(QFileDialog::getSaveFileName(nullptr, "Open Refal Notebook", "", "Refal Notebooks (*.refnb)"));
122 }
123
124 QJsonDocument doc = toJson();
125 QFile save(_savePath);
126 save.open(QFile::WriteOnly);
127
128 if (!save.isOpen())
129 {
130 emit saveError(save.errorString());
131 return;
132 }
133
134 save.write(doc.toJson(QJsonDocument::Indented));
135 save.close();
136}
137
138bool Notebook::savePathSet()
139{
140 return _savePath != "";
141}
142
143QString Notebook::savePath()
144{
145 return _savePath;
146}
147
148void Notebook::setSavePath(QString savePath)
149{
150 _savePath = savePath;
151 emit savePathChanged(savePath);
152}
153
swissChilid85daa92022-02-24 15:29:02 -0800154void Notebook::cellFinishedRunning(Cell *cell, RuntimeResult result)
155{
156 qInfo() << "cellFinishedRunning" << cell->uuid() << pprint(result);
157 cell->setResult(pprint(result));
158 cell->setStatus(Cell::IDLE);
swissChiliece1ac82022-02-25 11:20:42 -0800159 cell->setResultType(Cell::EXPRESSION);
swissChilid85daa92022-02-24 15:29:02 -0800160}
161
swissChiliece1ac82022-02-25 11:20:42 -0800162void Notebook::cellFailedToParse(Cell *cell, ParseResult result, Parser parser)
swissChilid85daa92022-02-24 15:29:02 -0800163{
swissChiliece1ac82022-02-25 11:20:42 -0800164 qInfo() << "cellFailedToParse" << cell->uuid() << pprint(result, parser);
165 cell->setResult(pprint(result, parser, PPrint::HTML));
swissChilid85daa92022-02-24 15:29:02 -0800166 cell->setStatus(Cell::IDLE);
swissChiliece1ac82022-02-25 11:20:42 -0800167 cell->setResultType(Cell::DIAGNOSTIC);
swissChilid85daa92022-02-24 15:29:02 -0800168}
169
170void Notebook::cellWaiting(Cell *cell)
171{
172 qInfo() << "cellWaiting" << cell->uuid();
173 cell->setStatus(Cell::WAITING);
174}
175
176void Notebook::cellRunning(Cell *cell)
177{
178 qInfo() << "cellRunning" << cell->uuid();
179 cell->setStatus(Cell::RUNNING);
180}
181
182void Notebook::cellQuit(Cell *cell)
183{
184 qInfo() << "cellQuit" << cell->uuid();
185 cell->setResult("");
186 cell->setStatus(Cell::IDLE);
187}