blob: a5baa0c4c81599a057253159b92890126a4c13a5 [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));
swissChilia44bf722022-04-16 18:41:54 -070059 _runningAll = false;
60}
61
62void Notebook::runAll()
63{
64 if (_cells.size() > 0)
65 {
66 _rt->queueCell(_cells.first());
67 _runningAll = true;
68 }
69}
70
71void Notebook::reset()
72{
73 _rt->reset();
swissChilid85daa92022-02-24 15:29:02 -080074}
75
swissChilid2af6ad2022-04-16 14:42:17 -070076void Notebook::fromJson(QJsonDocument doc)
77{
78 QJsonObject nb = doc.object();
79 QJsonArray cellArray = nb["cells"].toArray();
80
81 for (const QJsonValueRef &cell : cellArray)
82 {
83 cellModel()->insertCellBefore(cellModel()->rowCount());
84 _cells.last()->fromJson(cell.toObject());
85 }
86}
87
88void Notebook::open(QString path)
89{
90 QFile file(path);
91
92 if (file.exists())
93 {
94 file.open(QFile::ReadOnly);
95
96 QJsonParseError error;
97 QJsonDocument doc = QJsonDocument::fromJson(file.readAll(), &error);
98
99 if (error.error == QJsonParseError::NoError)
100 {
101 fromJson(doc);
102 }
103 else
104 {
105 qWarning() << error.errorString();
106 }
107
108 file.close();
109 setSavePath(path);
110 }
111 else
112 {
113 qWarning() << "File does not exist" << path;
114 }
115}
116
swissChili505de412022-03-24 12:35:08 -0700117QJsonDocument Notebook::toJson() const
118{
119 QJsonObject nb;
120 QJsonArray cellArray;
121
122 for (const Cell *cell : _cells)
123 {
124 cellArray.append(cell->toJson());
125 }
126
127 nb["cells"] = cellArray;
128
129 return QJsonDocument(nb);
130}
131
132void Notebook::save()
133{
134 if (_savePath == "")
135 {
swissChilia44bf722022-04-16 18:41:54 -0700136 setSavePath(QFileDialog::getSaveFileName(nullptr, "Open REFAL Notebook", "", "REFAL Notebook (*.refnb)"));
swissChili505de412022-03-24 12:35:08 -0700137 }
138
139 QJsonDocument doc = toJson();
140 QFile save(_savePath);
141 save.open(QFile::WriteOnly);
142
143 if (!save.isOpen())
144 {
145 emit saveError(save.errorString());
146 return;
147 }
148
149 save.write(doc.toJson(QJsonDocument::Indented));
150 save.close();
swissChilia44bf722022-04-16 18:41:54 -0700151
152 emit saved();
swissChili505de412022-03-24 12:35:08 -0700153}
154
155bool Notebook::savePathSet()
156{
157 return _savePath != "";
158}
159
160QString Notebook::savePath()
161{
162 return _savePath;
163}
164
165void Notebook::setSavePath(QString savePath)
166{
167 _savePath = savePath;
168 emit savePathChanged(savePath);
169}
170
swissChilid85daa92022-02-24 15:29:02 -0800171void Notebook::cellFinishedRunning(Cell *cell, RuntimeResult result)
172{
173 qInfo() << "cellFinishedRunning" << cell->uuid() << pprint(result);
174 cell->setResult(pprint(result));
175 cell->setStatus(Cell::IDLE);
swissChiliece1ac82022-02-25 11:20:42 -0800176 cell->setResultType(Cell::EXPRESSION);
swissChilia44bf722022-04-16 18:41:54 -0700177
178 if (_runningAll)
179 {
180 int index = _cells.indexOf(cell);
181
182 // not last
183 if (index < _cells.size() - 1)
184 {
185 _rt->queueCell(_cells[index + 1]);
186 }
187 else
188 {
189 _runningAll = false;
190 }
191 }
swissChilid85daa92022-02-24 15:29:02 -0800192}
193
swissChiliece1ac82022-02-25 11:20:42 -0800194void Notebook::cellFailedToParse(Cell *cell, ParseResult result, Parser parser)
swissChilid85daa92022-02-24 15:29:02 -0800195{
swissChiliece1ac82022-02-25 11:20:42 -0800196 qInfo() << "cellFailedToParse" << cell->uuid() << pprint(result, parser);
197 cell->setResult(pprint(result, parser, PPrint::HTML));
swissChilid85daa92022-02-24 15:29:02 -0800198 cell->setStatus(Cell::IDLE);
swissChiliece1ac82022-02-25 11:20:42 -0800199 cell->setResultType(Cell::DIAGNOSTIC);
swissChilia44bf722022-04-16 18:41:54 -0700200
201 _runningAll = false;
swissChilid85daa92022-02-24 15:29:02 -0800202}
203
204void Notebook::cellWaiting(Cell *cell)
205{
206 qInfo() << "cellWaiting" << cell->uuid();
207 cell->setStatus(Cell::WAITING);
208}
209
210void Notebook::cellRunning(Cell *cell)
211{
212 qInfo() << "cellRunning" << cell->uuid();
213 cell->setStatus(Cell::RUNNING);
214}
215
216void Notebook::cellQuit(Cell *cell)
217{
218 qInfo() << "cellQuit" << cell->uuid();
219 cell->setResult("");
220 cell->setStatus(Cell::IDLE);
swissChilia44bf722022-04-16 18:41:54 -0700221
222 _runningAll = false;
swissChilid85daa92022-02-24 15:29:02 -0800223}