Add recent file view, implement runtime options
diff --git a/Evaluator.cpp b/Evaluator.cpp
index 9ce5bf7..92979c4 100644
--- a/Evaluator.cpp
+++ b/Evaluator.cpp
@@ -244,6 +244,13 @@
throw EvalQuitException();
}
+void Evaluator::reset()
+{
+ _vars = {};
+ _functions = {};
+ _shouldContinue = true;
+}
+
QList<Token> Evaluator::dig(QString name)
{
if (_vars.contains(name))
diff --git a/Evaluator.h b/Evaluator.h
index 7034669..a88e809 100644
--- a/Evaluator.h
+++ b/Evaluator.h
@@ -88,6 +88,8 @@
// Throws an EvalQuitException
void quit();
+ void reset();
+
private:
QMap<QString, Function> _functions;
QMap<QString, QStack<QList<Token>>> _vars;
diff --git a/VarContext.cpp b/VarContext.cpp
index a67df2b..f444faa 100644
--- a/VarContext.cpp
+++ b/VarContext.cpp
@@ -1,7 +1,7 @@
#include "VarContext.h"
void VarContext::add(char t, const QString &name, const Token &value) {
- _vars.insert(name, Var{t, value});
+ _vars.insert(name, Var{t, value, {}});
}
char VarContext::exists(const QString &name) {
diff --git a/VarContext.h b/VarContext.h
index 6e5ea13..5ae93d5 100644
--- a/VarContext.h
+++ b/VarContext.h
@@ -8,7 +8,8 @@
{
public:
VarContext() = default;
- VarContext(VarContext const &other) noexcept;
+ VarContext(VarContext const &other) noexcept;
+ VarContext &operator =(const VarContext &other) = default;
void add(char t, const QString &name, const Token &value);
void add(char t, const QString &name, const QList<Token> &value);
diff --git a/examples/Book Examples.refnb b/examples/Book Examples.refnb
new file mode 100644
index 0000000..142aa60
--- /dev/null
+++ b/examples/Book Examples.refnb
@@ -0,0 +1,10 @@
+{
+ "cells": [
+ {
+ "code": "* These are examples from the book",
+ "result": "Garbage at end of input at 1:1<br>* These are examples from the book<br><font color=\"red\">^~~</font>",
+ "resultType": 1,
+ "status": 1
+ }
+ ]
+}
diff --git a/ide/IDE.pri b/ide/IDE.pri
index 69856d7..d086a61 100644
--- a/ide/IDE.pri
+++ b/ide/IDE.pri
@@ -18,14 +18,16 @@
$$PWD/CellModel.cpp \
$$PWD/IdeMain.cpp \
$$PWD/NbRuntime.cpp \
- $$PWD/Notebook.cpp
+ $$PWD/Notebook.cpp \
+ $$PWD/RecentModel.cpp
HEADERS += \
$$PWD/Cell.h \
$$PWD/CellModel.h \
$$PWD/IdeMain.h \
$$PWD/NbRuntime.h \
- $$PWD/Notebook.h
+ $$PWD/Notebook.h \
+ $$PWD/RecentModel.h
RESOURCES += \
$$PWD/resources.qrc
diff --git a/ide/IdeMain.cpp b/ide/IdeMain.cpp
index ff8025f..7efe5fa 100644
--- a/ide/IdeMain.cpp
+++ b/ide/IdeMain.cpp
@@ -5,6 +5,7 @@
#include <QTranslator>
#include "CellModel.h"
+#include "RecentModel.h"
int ideMain(Application *app)
{
@@ -14,11 +15,17 @@
qRegisterMetaType<CellModel>();
qRegisterMetaType<CellModel *>();
+ qRegisterMetaType<RecentModel>();
+ qRegisterMetaType<RecentModel *>();
QTranslator translator;
qInfo() << "loading translations" << translator.load(QLocale(), "refal", "_", ":/ts/", ".qm");
app->installTranslator(&translator);
+ app->setOrganizationName("swissChili");
+ app->setOrganizationDomain("swisschili.sh");
+ app->setApplicationName("REFAL Studio");
+
const QUrl url(QStringLiteral("qrc:/qml/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
app, [url](QObject *obj, const QUrl &objUrl)
diff --git a/ide/NbRuntime.cpp b/ide/NbRuntime.cpp
index a2111a7..debda5b 100644
--- a/ide/NbRuntime.cpp
+++ b/ide/NbRuntime.cpp
@@ -10,6 +10,12 @@
StdLib().load(_eval);
}
+void NbRuntime::reset()
+{
+ _eval.reset();
+ _ctx = {};
+}
+
void NbRuntime::queueCell(Cell *cell)
{
if (!_cells.contains(cell))
diff --git a/ide/NbRuntime.h b/ide/NbRuntime.h
index e7a4b3d..d98daa3 100644
--- a/ide/NbRuntime.h
+++ b/ide/NbRuntime.h
@@ -16,6 +16,8 @@
public:
explicit NbRuntime(QObject *parent = nullptr);
+ void reset();
+
public slots:
void queueCell(Cell *cell);
void unqueueCell(Cell *cell);
diff --git a/ide/Notebook.cpp b/ide/Notebook.cpp
index 36cc0a3..a5baa0c 100644
--- a/ide/Notebook.cpp
+++ b/ide/Notebook.cpp
@@ -56,6 +56,21 @@
void Notebook::quitCell(QUuid uuid)
{
_rt->unqueueCell(Cell::cellFromUuid(uuid));
+ _runningAll = false;
+}
+
+void Notebook::runAll()
+{
+ if (_cells.size() > 0)
+ {
+ _rt->queueCell(_cells.first());
+ _runningAll = true;
+ }
+}
+
+void Notebook::reset()
+{
+ _rt->reset();
}
void Notebook::fromJson(QJsonDocument doc)
@@ -118,7 +133,7 @@
{
if (_savePath == "")
{
- setSavePath(QFileDialog::getSaveFileName(nullptr, "Open Refal Notebook", "", "Refal Notebooks (*.refnb)"));
+ setSavePath(QFileDialog::getSaveFileName(nullptr, "Open REFAL Notebook", "", "REFAL Notebook (*.refnb)"));
}
QJsonDocument doc = toJson();
@@ -133,6 +148,8 @@
save.write(doc.toJson(QJsonDocument::Indented));
save.close();
+
+ emit saved();
}
bool Notebook::savePathSet()
@@ -157,6 +174,21 @@
cell->setResult(pprint(result));
cell->setStatus(Cell::IDLE);
cell->setResultType(Cell::EXPRESSION);
+
+ if (_runningAll)
+ {
+ int index = _cells.indexOf(cell);
+
+ // not last
+ if (index < _cells.size() - 1)
+ {
+ _rt->queueCell(_cells[index + 1]);
+ }
+ else
+ {
+ _runningAll = false;
+ }
+ }
}
void Notebook::cellFailedToParse(Cell *cell, ParseResult result, Parser parser)
@@ -165,6 +197,8 @@
cell->setResult(pprint(result, parser, PPrint::HTML));
cell->setStatus(Cell::IDLE);
cell->setResultType(Cell::DIAGNOSTIC);
+
+ _runningAll = false;
}
void Notebook::cellWaiting(Cell *cell)
@@ -184,4 +218,6 @@
qInfo() << "cellQuit" << cell->uuid();
cell->setResult("");
cell->setStatus(Cell::IDLE);
+
+ _runningAll = false;
}
diff --git a/ide/Notebook.h b/ide/Notebook.h
index 6a6541d..83f9fc7 100644
--- a/ide/Notebook.h
+++ b/ide/Notebook.h
@@ -25,6 +25,8 @@
Q_INVOKABLE void runCell(QUuid uuid);
Q_INVOKABLE void quitCell(QUuid uuid);
+ Q_INVOKABLE void runAll();
+ Q_INVOKABLE void reset();
Q_INVOKABLE void fromJson(QJsonDocument doc);
Q_INVOKABLE void open(QString path);
@@ -41,6 +43,7 @@
void cellModelChanged();
void saveError(QString message);
void savePathChanged(QString savePath);
+ void saved();
protected slots:
void cellFinishedRunning(Cell *cell, RuntimeResult result);
@@ -57,6 +60,7 @@
QThread *_rtThread;
NbRuntime *_rt;
QString _savePath = "";
+ bool _runningAll = false;
};
Q_DECLARE_METATYPE(Notebook)
diff --git a/ide/RecentModel.cpp b/ide/RecentModel.cpp
new file mode 100644
index 0000000..30824ed
--- /dev/null
+++ b/ide/RecentModel.cpp
@@ -0,0 +1,62 @@
+#include "RecentModel.h"
+#include <QSettings>
+
+RecentModel::RecentModel(QObject *parent)
+ : QAbstractListModel(parent)
+{
+ _recents = _settings.value("recents").toStringList();
+}
+
+RecentModel::RecentModel(const RecentModel &other, QObject *parent)
+ : RecentModel(parent)
+{
+ _recents = other._recents;
+}
+
+int RecentModel::rowCount(const QModelIndex &parent) const
+{
+ if (parent.isValid())
+ return 0;
+
+ return _recents.size();
+}
+
+QVariant RecentModel::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid())
+ return QVariant();
+
+ if (role == PathRole)
+ return _recents[index.row()];
+
+ return QVariant();
+}
+
+QHash<int, QByteArray> RecentModel::roleNames() const
+{
+ return {{PathRole, "path"}};
+}
+
+void RecentModel::add(QString path)
+{
+ remove(path);
+
+ beginInsertRows(QModelIndex(), 0, 0);
+ _recents.prepend(path);
+ endInsertRows();
+
+ _settings.setValue("recents", _recents);
+}
+
+void RecentModel::remove(QString path)
+{
+ if (_recents.contains(path))
+ {
+ int index = _recents.indexOf(path);
+ beginRemoveRows(QModelIndex(), index, index);
+ _recents.removeAt(index);
+ endRemoveRows();
+
+ _settings.setValue("recents", _recents);
+ }
+}
diff --git a/ide/RecentModel.h b/ide/RecentModel.h
new file mode 100644
index 0000000..76cd461
--- /dev/null
+++ b/ide/RecentModel.h
@@ -0,0 +1,36 @@
+#pragma once
+
+#include <QAbstractListModel>
+#include <qqml.h>
+#include <QSettings>
+
+class RecentModel : public QAbstractListModel
+{
+ Q_OBJECT
+ QML_ELEMENT
+
+public:
+ explicit RecentModel(QObject *parent = nullptr);
+ RecentModel(const RecentModel &other, QObject *parent = nullptr);
+
+ enum
+ {
+ PathRole = Qt::UserRole + 1
+ };
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+
+ QHash<int, QByteArray> roleNames() const override;
+
+ Q_INVOKABLE void add(QString path);
+ Q_INVOKABLE void remove(QString path);
+
+private:
+ QStringList _recents;
+ QSettings _settings;
+};
+
+Q_DECLARE_METATYPE(RecentModel)
+Q_DECLARE_METATYPE(RecentModel *)
diff --git a/ide/qml/NbWindow.qml b/ide/qml/NbWindow.qml
index 5710c9e..858fb5e 100644
--- a/ide/qml/NbWindow.qml
+++ b/ide/qml/NbWindow.qml
@@ -15,7 +15,8 @@
Material.theme: Material.Light
Material.accent: Material.Orange
- minimumWidth: column.implicitWidth
+ minimumWidth: 600
+ minimumHeight: 400
required property ApplicationWindow welcomeWindow
@@ -92,10 +93,14 @@
Action {
text: qsTr("Run &All")
+
+ onTriggered: notebook.runAll();
}
Action {
text: qsTr("&Reset Runtime State")
+
+ onTriggered: notebook.reset();
}
}
}
@@ -107,6 +112,8 @@
{
console.error(message)
}
+
+ onSaved: welcomeWindow.recentModel.add(notebook.savePath)
}
ColumnLayout {
@@ -137,7 +144,7 @@
ColumnLayout {
Label {
font.pointSize: 18
- text: qsTr("Notebook")
+ text: notebook.savePath != "" ? notebook.savePath.split("/").pop().split(".").slice(0,-1).join('.') : qsTr("Notebook")
}
Label {
diff --git a/ide/qml/RecentNotebook.qml b/ide/qml/RecentNotebook.qml
index d0b1120..194424c 100644
--- a/ide/qml/RecentNotebook.qml
+++ b/ide/qml/RecentNotebook.qml
@@ -8,6 +8,7 @@
property string name: "Hello.refnb"
property alias containsMouse: mouseArea.containsMouse
signal clicked()
+ signal removeClicked()
Image {
id: nbIcon
@@ -27,7 +28,24 @@
anchors.fill: parent
hoverEnabled: true
- onClicked: root.clicked()
+ acceptedButtons: Qt.LeftButton | Qt.RightButton
+
+ onClicked: {
+ if (mouse.button == Qt.LeftButton)
+ root.clicked();
+ else if (mouse.button == Qt.RightButton)
+ contextMenu.popup();
+ }
+ }
+
+ Menu {
+ id: contextMenu
+
+ MenuItem {
+ text: qsTr("Remove")
+
+ onClicked: root.removeClicked()
+ }
}
}
}
diff --git a/ide/qml/main.qml b/ide/qml/main.qml
index 23f8926..210640c 100644
--- a/ide/qml/main.qml
+++ b/ide/qml/main.qml
@@ -2,6 +2,9 @@
import QtQuick.Controls 2.15
import QtQuick.Controls.Material 2.0
import QtQuick.Layouts 1.11
+import Qt.labs.settings 1.0
+
+import sh.swisschili.REFAL 1.0
ApplicationWindow {
id: root
@@ -19,6 +22,8 @@
visible: true
+ property alias recentModel: recents
+
function openNotebook(path=null) {
let NbWindow = Qt.createComponent("qrc:///qml/NbWindow.qml");
let window = NbWindow.createObject(null, {welcomeWindow: root});
@@ -36,6 +41,10 @@
show();
}
+ RecentModel {
+ id: recents
+ }
+
Label {
id: textRefal
text: qsTr("REFAL")
@@ -125,21 +134,20 @@
Layout.fillWidth: true
Layout.fillHeight: false
- model: [
- // "~/Documents/Hello.refnb", "~/Downloads/stuff/Goodbye.refnb", "/home/ch/dev/REFAL/build/test.refnb"
- ]
+ model: recents
delegate: RecentNotebook {
Layout.leftMargin: 8
Layout.rightMargin: 8
- name: modelData.split("/").pop()
+ name: path.split("/").pop()
- ToolTip.text: modelData
+ ToolTip.text: path
ToolTip.visible: containsMouse
ToolTip.delay: 1000
- onClicked: root.openNotebook(modelData)
+ onClicked: root.openNotebook(path)
+ onRemoveClicked: recents.remove(path)
}
}
diff --git a/ts/refal_en_US.qm b/ts/refal_en_US.qm
index 71c6570..899dbe0 100644
--- a/ts/refal_en_US.qm
+++ b/ts/refal_en_US.qm
Binary files differ
diff --git a/ts/refal_en_US.ts b/ts/refal_en_US.ts
index cf241b8..a22f35a 100644
--- a/ts/refal_en_US.ts
+++ b/ts/refal_en_US.ts
@@ -21,27 +21,27 @@
<translation>&New</translation>
</message>
<message>
- <location filename="../ide/qml/NbWindow.qml" line="35"/>
+ <location filename="../ide/qml/NbWindow.qml" line="39"/>
<source>&Save</source>
<translation>&Save</translation>
</message>
<message>
- <location filename="../ide/qml/NbWindow.qml" line="44"/>
+ <location filename="../ide/qml/NbWindow.qml" line="48"/>
<source>&Open</source>
<translation>&Open</translation>
</message>
<message>
- <location filename="../ide/qml/NbWindow.qml" line="54"/>
+ <location filename="../ide/qml/NbWindow.qml" line="58"/>
<source>&View</source>
<translation>&View</translation>
</message>
<message>
- <location filename="../ide/qml/NbWindow.qml" line="57"/>
+ <location filename="../ide/qml/NbWindow.qml" line="61"/>
<source>&Welcome Window</source>
<translation>&Welcome Window</translation>
</message>
<message>
- <location filename="../ide/qml/NbWindow.qml" line="69"/>
+ <location filename="../ide/qml/NbWindow.qml" line="73"/>
<source>&Variable Inspector</source>
<translation>&Variable Inspector</translation>
</message>
@@ -61,22 +61,22 @@
<translation>Run &All</translation>
</message>
<message>
- <location filename="../ide/qml/NbWindow.qml" line="98"/>
+ <location filename="../ide/qml/NbWindow.qml" line="100"/>
<source>&Reset Runtime State</source>
<translation>&Reset Runtime State</translation>
</message>
<message>
- <location filename="../ide/qml/NbWindow.qml" line="140"/>
+ <location filename="../ide/qml/NbWindow.qml" line="146"/>
<source>Notebook</source>
<translation>Notebook</translation>
</message>
<message>
- <location filename="../ide/qml/NbWindow.qml" line="146"/>
+ <location filename="../ide/qml/NbWindow.qml" line="152"/>
<source>Looks like you haven't created any cells yet. Click the + button below to create one.</source>
<translation>Looks like you haven't created any cells yet. Click the + button below to create one.</translation>
</message>
<message>
- <location filename="../ide/qml/NbWindow.qml" line="208"/>
+ <location filename="../ide/qml/NbWindow.qml" line="214"/>
<source>Variables</source>
<translation>Variables</translation>
</message>
@@ -95,29 +95,37 @@
</message>
</context>
<context>
+ <name>RecentNotebook</name>
+ <message>
+ <location filename="../ide/qml/RecentNotebook.qml" line="45"/>
+ <source>Remove</source>
+ <translation>Remove</translation>
+ </message>
+</context>
+<context>
<name>main</name>
<message>
- <location filename="../ide/qml/main.qml" line="41"/>
+ <location filename="../ide/qml/main.qml" line="50"/>
<source>REFAL</source>
<translation>REFAL</translation>
</message>
<message>
- <location filename="../ide/qml/main.qml" line="55"/>
+ <location filename="../ide/qml/main.qml" line="64"/>
<source>Studio</source>
<translation>Studio</translation>
</message>
<message>
- <location filename="../ide/qml/main.qml" line="106"/>
+ <location filename="../ide/qml/main.qml" line="115"/>
<source>New Notebook</source>
<translation>New Notebook</translation>
</message>
<message>
- <location filename="../ide/qml/main.qml" line="117"/>
+ <location filename="../ide/qml/main.qml" line="126"/>
<source>Open Existing</source>
<translation>Open Existing</translation>
</message>
<message>
- <location filename="../ide/qml/main.qml" line="151"/>
+ <location filename="../ide/qml/main.qml" line="159"/>
<source>Your recent notebooks will appear here</source>
<translation>Your recent notebooks will appear here</translation>
</message>
diff --git a/ts/refal_ru_RU.qm b/ts/refal_ru_RU.qm
index ca42b3a..dc0fcd2 100644
--- a/ts/refal_ru_RU.qm
+++ b/ts/refal_ru_RU.qm
Binary files differ
diff --git a/ts/refal_ru_RU.ts b/ts/refal_ru_RU.ts
index fbf55af..214753f 100644
--- a/ts/refal_ru_RU.ts
+++ b/ts/refal_ru_RU.ts
@@ -21,27 +21,27 @@
<translation>Создать &Новую Тетрадь</translation>
</message>
<message>
- <location filename="../ide/qml/NbWindow.qml" line="35"/>
+ <location filename="../ide/qml/NbWindow.qml" line="39"/>
<source>&Save</source>
<translation>&Сохранить</translation>
</message>
<message>
- <location filename="../ide/qml/NbWindow.qml" line="44"/>
+ <location filename="../ide/qml/NbWindow.qml" line="48"/>
<source>&Open</source>
<translation>&Открыть</translation>
</message>
<message>
- <location filename="../ide/qml/NbWindow.qml" line="54"/>
+ <location filename="../ide/qml/NbWindow.qml" line="58"/>
<source>&View</source>
- <translation>&Видеть</translation>
+ <translation>&Вид</translation>
</message>
<message>
- <location filename="../ide/qml/NbWindow.qml" line="57"/>
+ <location filename="../ide/qml/NbWindow.qml" line="61"/>
<source>&Welcome Window</source>
<translation>&Стартовая Страниця</translation>
</message>
<message>
- <location filename="../ide/qml/NbWindow.qml" line="69"/>
+ <location filename="../ide/qml/NbWindow.qml" line="73"/>
<source>&Variable Inspector</source>
<translation>Инспектор &Переменных</translation>
</message>
@@ -61,22 +61,22 @@
<translation>Запустить &Все Ячейки</translation>
</message>
<message>
- <location filename="../ide/qml/NbWindow.qml" line="98"/>
+ <location filename="../ide/qml/NbWindow.qml" line="100"/>
<source>&Reset Runtime State</source>
<translation>Востоновить &Исходное Состояние</translation>
</message>
<message>
- <location filename="../ide/qml/NbWindow.qml" line="140"/>
+ <location filename="../ide/qml/NbWindow.qml" line="146"/>
<source>Notebook</source>
<translation>Тетрадь</translation>
</message>
<message>
- <location filename="../ide/qml/NbWindow.qml" line="146"/>
+ <location filename="../ide/qml/NbWindow.qml" line="152"/>
<source>Looks like you haven't created any cells yet. Click the + button below to create one.</source>
<translation>Вы еще не создали ячейку, нажмите кнопку + снизы что бы её создать.</translation>
</message>
<message>
- <location filename="../ide/qml/NbWindow.qml" line="208"/>
+ <location filename="../ide/qml/NbWindow.qml" line="214"/>
<source>Variables</source>
<translation>Переменные</translation>
</message>
@@ -95,29 +95,37 @@
</message>
</context>
<context>
+ <name>RecentNotebook</name>
+ <message>
+ <location filename="../ide/qml/RecentNotebook.qml" line="45"/>
+ <source>Remove</source>
+ <translation>Убрать</translation>
+ </message>
+</context>
+<context>
<name>main</name>
<message>
- <location filename="../ide/qml/main.qml" line="41"/>
+ <location filename="../ide/qml/main.qml" line="50"/>
<source>REFAL</source>
<translation>РЕФАЛ</translation>
</message>
<message>
- <location filename="../ide/qml/main.qml" line="55"/>
+ <location filename="../ide/qml/main.qml" line="64"/>
<source>Studio</source>
<translation>Студия</translation>
</message>
<message>
- <location filename="../ide/qml/main.qml" line="106"/>
+ <location filename="../ide/qml/main.qml" line="115"/>
<source>New Notebook</source>
<translation>Создать Тетрадь</translation>
</message>
<message>
- <location filename="../ide/qml/main.qml" line="117"/>
+ <location filename="../ide/qml/main.qml" line="126"/>
<source>Open Existing</source>
<translation>Открыть</translation>
</message>
<message>
- <location filename="../ide/qml/main.qml" line="151"/>
+ <location filename="../ide/qml/main.qml" line="159"/>
<source>Your recent notebooks will appear here</source>
<translation>Ваши недавние тетради появится здесь</translation>
</message>