blob: 72261cfeb131cdb9da3418fd6819e456f5a25ba2 [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{
swissChili8c5cefa2023-01-17 13:04:36 +010058 qDebug() << "Quitting cell" << uuid;
swissChili732628e2022-02-25 10:35:56 -080059 _rt->unqueueCell(Cell::cellFromUuid(uuid));
swissChilia44bf722022-04-16 18:41:54 -070060 _runningAll = false;
61}
62
63void Notebook::runAll()
64{
65 if (_cells.size() > 0)
66 {
67 _rt->queueCell(_cells.first());
68 _runningAll = true;
69 }
70}
71
72void Notebook::reset()
73{
74 _rt->reset();
swissChilid85daa92022-02-24 15:29:02 -080075}
76
swissChilid2af6ad2022-04-16 14:42:17 -070077void Notebook::fromJson(QJsonDocument doc)
78{
79 QJsonObject nb = doc.object();
80 QJsonArray cellArray = nb["cells"].toArray();
81
82 for (const QJsonValueRef &cell : cellArray)
83 {
84 cellModel()->insertCellBefore(cellModel()->rowCount());
85 _cells.last()->fromJson(cell.toObject());
86 }
87}
88
89void Notebook::open(QString path)
90{
91 QFile file(path);
92
93 if (file.exists())
94 {
95 file.open(QFile::ReadOnly);
96
97 QJsonParseError error;
98 QJsonDocument doc = QJsonDocument::fromJson(file.readAll(), &error);
99
100 if (error.error == QJsonParseError::NoError)
101 {
102 fromJson(doc);
103 }
104 else
105 {
106 qWarning() << error.errorString();
107 }
108
109 file.close();
110 setSavePath(path);
111 }
112 else
113 {
114 qWarning() << "File does not exist" << path;
115 }
116}
117
swissChili505de412022-03-24 12:35:08 -0700118QJsonDocument Notebook::toJson() const
119{
120 QJsonObject nb;
121 QJsonArray cellArray;
122
123 for (const Cell *cell : _cells)
124 {
125 cellArray.append(cell->toJson());
126 }
127
128 nb["cells"] = cellArray;
129
130 return QJsonDocument(nb);
131}
132
133void Notebook::save()
134{
135 if (_savePath == "")
136 {
swissChilia44bf722022-04-16 18:41:54 -0700137 setSavePath(QFileDialog::getSaveFileName(nullptr, "Open REFAL Notebook", "", "REFAL Notebook (*.refnb)"));
swissChili505de412022-03-24 12:35:08 -0700138 }
139
140 QJsonDocument doc = toJson();
141 QFile save(_savePath);
142 save.open(QFile::WriteOnly);
143
144 if (!save.isOpen())
145 {
146 emit saveError(save.errorString());
147 return;
148 }
149
150 save.write(doc.toJson(QJsonDocument::Indented));
151 save.close();
swissChilia44bf722022-04-16 18:41:54 -0700152
153 emit saved();
swissChili505de412022-03-24 12:35:08 -0700154}
155
156bool Notebook::savePathSet()
157{
158 return _savePath != "";
159}
160
161QString Notebook::savePath()
162{
163 return _savePath;
164}
165
166void Notebook::setSavePath(QString savePath)
167{
168 _savePath = savePath;
169 emit savePathChanged(savePath);
170}
171
swissChilid85daa92022-02-24 15:29:02 -0800172void Notebook::cellFinishedRunning(Cell *cell, RuntimeResult result)
173{
174 qInfo() << "cellFinishedRunning" << cell->uuid() << pprint(result);
175 cell->setResult(pprint(result));
176 cell->setStatus(Cell::IDLE);
swissChiliece1ac82022-02-25 11:20:42 -0800177 cell->setResultType(Cell::EXPRESSION);
swissChilia44bf722022-04-16 18:41:54 -0700178
179 if (_runningAll)
180 {
181 int index = _cells.indexOf(cell);
182
183 // not last
184 if (index < _cells.size() - 1)
185 {
186 _rt->queueCell(_cells[index + 1]);
187 }
188 else
189 {
190 _runningAll = false;
191 }
192 }
swissChilid85daa92022-02-24 15:29:02 -0800193}
194
swissChiliece1ac82022-02-25 11:20:42 -0800195void Notebook::cellFailedToParse(Cell *cell, ParseResult result, Parser parser)
swissChilid85daa92022-02-24 15:29:02 -0800196{
swissChiliece1ac82022-02-25 11:20:42 -0800197 qInfo() << "cellFailedToParse" << cell->uuid() << pprint(result, parser);
198 cell->setResult(pprint(result, parser, PPrint::HTML));
swissChilid85daa92022-02-24 15:29:02 -0800199 cell->setStatus(Cell::IDLE);
swissChiliece1ac82022-02-25 11:20:42 -0800200 cell->setResultType(Cell::DIAGNOSTIC);
swissChilia44bf722022-04-16 18:41:54 -0700201
202 _runningAll = false;
swissChilid85daa92022-02-24 15:29:02 -0800203}
204
205void Notebook::cellWaiting(Cell *cell)
206{
207 qInfo() << "cellWaiting" << cell->uuid();
208 cell->setStatus(Cell::WAITING);
209}
210
211void Notebook::cellRunning(Cell *cell)
212{
213 qInfo() << "cellRunning" << cell->uuid();
214 cell->setStatus(Cell::RUNNING);
215}
216
217void Notebook::cellQuit(Cell *cell)
218{
219 qInfo() << "cellQuit" << cell->uuid();
220 cell->setResult("");
221 cell->setStatus(Cell::IDLE);
swissChilia44bf722022-04-16 18:41:54 -0700222
223 _runningAll = false;
swissChilid85daa92022-02-24 15:29:02 -0800224}