Add Notebook
diff --git a/ide/CellModel.cpp b/ide/CellModel.cpp
index 911c9a9..41acbe7 100644
--- a/ide/CellModel.cpp
+++ b/ide/CellModel.cpp
@@ -1,14 +1,14 @@
#include "CellModel.h"
-CellModel::CellModel(QObject *parent)
+CellModel::CellModel(Notebook *parent)
: QAbstractListModel(parent)
+ , _notebook(parent)
{
}
-CellModel::CellModel(const CellModel &model, QObject *parent)
- : CellModel(parent)
+CellModel::CellModel(const CellModel &other)
+ : CellModel(other._notebook)
{
- _cells = model._cells;
}
int CellModel::rowCount(const QModelIndex &parent) const
@@ -18,7 +18,7 @@
if (parent.isValid())
return 0;
- return _cells.size();
+ return _notebook->_cells.size();
}
QVariant CellModel::data(const QModelIndex &index, int role) const
@@ -29,9 +29,9 @@
switch (role)
{
case CodeRole:
- return _cells[index.row()].code();
+ return _notebook->_cells[index.row()].code();
case ResultRole:
- return _cells[index.row()].result();
+ return _notebook->_cells[index.row()].result();
default:
return QVariant();
}
@@ -44,10 +44,10 @@
switch (role)
{
case CodeRole:
- _cells[index.row()].setCode(value.toString());
+ _notebook->_cells[index.row()].setCode(value.toString());
break;
case ResultRole:
- _cells[index.row()].setResult(value.toString());
+ _notebook->_cells[index.row()].setResult(value.toString());
break;
default:
return false;
@@ -74,7 +74,7 @@
beginInsertRows(parent, row, row + count - 1);
for (int i = 0; i < count; i++)
- _cells.insert(row, Cell());
+ _notebook->_cells.insert(row, Cell());
endInsertRows();
@@ -86,7 +86,7 @@
beginRemoveRows(parent, row, row + count - 1);
for (int i = 0; i < count; i++)
- _cells.removeAt(row);
+ _notebook->_cells.removeAt(row);
endRemoveRows();
@@ -103,11 +103,11 @@
void CellModel::addCell(const Cell &cell)
{
- int i = _cells.size();
+ int i = _notebook->_cells.size();
insertRows(i, 1, QModelIndex());
- _cells[i] = cell;
+ _notebook->_cells[i] = cell;
emit dataChanged(index(i), index(i), {CodeRole, ResultRole});
}
diff --git a/ide/CellModel.h b/ide/CellModel.h
index 3920e38..16bfee5 100644
--- a/ide/CellModel.h
+++ b/ide/CellModel.h
@@ -3,16 +3,16 @@
#include <QAbstractListModel>
#include <qqml.h>
+#include "Notebook.h"
#include "Cell.h"
class CellModel : public QAbstractListModel
{
Q_OBJECT
- QML_ELEMENT
public:
- explicit CellModel(QObject *parent = nullptr);
- CellModel(const CellModel &model, QObject *parent = nullptr);
+ explicit CellModel(Notebook *parent = nullptr);
+ CellModel(const CellModel &other);
enum CellRoles
{
@@ -43,7 +43,8 @@
Q_INVOKABLE void addCell(QString code, QString result);
private:
- QList<Cell> _cells;
+ Notebook *_notebook;
};
Q_DECLARE_METATYPE(CellModel)
+Q_DECLARE_METATYPE(CellModel *)
diff --git a/ide/IDE.pri b/ide/IDE.pri
index 906b3cb..f656fd1 100644
--- a/ide/IDE.pri
+++ b/ide/IDE.pri
@@ -16,12 +16,14 @@
SOURCES += \
$$PWD/Cell.cpp \
$$PWD/CellModel.cpp \
- $$PWD/IdeMain.cpp
+ $$PWD/IdeMain.cpp \
+ $$PWD/Notebook.cpp
HEADERS += \
$$PWD/Cell.h \
$$PWD/CellModel.h \
- $$PWD/IdeMain.h
+ $$PWD/IdeMain.h \
+ $$PWD/Notebook.h
RESOURCES += \
$$PWD/resources.qrc
diff --git a/ide/IdeMain.cpp b/ide/IdeMain.cpp
index a8f918c..d76c955 100644
--- a/ide/IdeMain.cpp
+++ b/ide/IdeMain.cpp
@@ -3,6 +3,8 @@
#include <QQmlApplicationEngine>
#include <QQuickStyle>
+#include "CellModel.h"
+
int ideMain(QGuiApplication *app)
{
QQmlApplicationEngine engine;
@@ -12,6 +14,9 @@
QQuickStyle::setStyle("Material");
+ qRegisterMetaType<CellModel>();
+ qRegisterMetaType<CellModel *>();
+
const QUrl url(QStringLiteral("qrc:/qml/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
app, [url](QObject *obj, const QUrl &objUrl)
diff --git a/ide/Notebook.cpp b/ide/Notebook.cpp
new file mode 100644
index 0000000..9beb332
--- /dev/null
+++ b/ide/Notebook.cpp
@@ -0,0 +1,21 @@
+#include "Notebook.h"
+#include "CellModel.h"
+
+Notebook::Notebook(QObject *parent)
+ : QObject(parent)
+ , _cellModel(new CellModel(this))
+{
+
+}
+
+Notebook::Notebook(const Notebook &other, QObject *parent)
+ : QObject(parent)
+ , _cells(other._cells)
+ , _cellModel(new CellModel(this))
+{
+}
+
+CellModel *Notebook::cellModel()
+{
+ return _cellModel;
+}
diff --git a/ide/Notebook.h b/ide/Notebook.h
new file mode 100644
index 0000000..0bd84ec
--- /dev/null
+++ b/ide/Notebook.h
@@ -0,0 +1,32 @@
+#pragma once
+
+#include <QObject>
+
+#include "Cell.h"
+
+class CellModel;
+
+class Notebook : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+
+ Q_PROPERTY(CellModel *cellModel READ cellModel NOTIFY cellModelChanged)
+
+public:
+ explicit Notebook(QObject *parent = nullptr);
+ Notebook(const Notebook &other, QObject *parent = nullptr);
+
+ CellModel *cellModel();
+
+signals:
+ void cellModelChanged();
+
+protected:
+ friend class CellModel;
+
+ QList<Cell> _cells;
+ CellModel *_cellModel;
+};
+
+Q_DECLARE_METATYPE(Notebook)
diff --git a/ide/icons/trash.svg b/ide/icons/trash.svg
new file mode 100644
index 0000000..d7da9e1
--- /dev/null
+++ b/ide/icons/trash.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M128 405.429C128 428.846 147.198 448 170.667 448h170.667C364.802 448 384 428.846 384 405.429V160H128v245.429zM416 96h-80l-26.785-32H202.786L176 96H96v32h320V96z"/></svg>
\ No newline at end of file
diff --git a/ide/qml/InsertRow.qml b/ide/qml/InsertRow.qml
index 00bad8b..fd7d8b9 100644
--- a/ide/qml/InsertRow.qml
+++ b/ide/qml/InsertRow.qml
@@ -6,6 +6,8 @@
Rectangle {
id: root
+ signal insertClicked()
+
color: Material.color(Material.Grey, Material.theme == Material.Dark ? Material.Shade800 : Material.Shade300)
height: 2
Layout.fillWidth: true
@@ -51,12 +53,14 @@
height: 24
width: 24
- Button {
+ RoundButton {
id: addButton
anchors.centerIn: parent
icon.source: "qrc:///icons/add.svg"
icon.color: Material.color(Material.Grey, Material.theme == Material.Dark ? Material.Shade400 : Material.Shade600)
flat: true
+
+ onClicked: root.insertClicked()
}
}
}
diff --git a/ide/qml/NotebookCell.qml b/ide/qml/NotebookCell.qml
index a441b73..3466d05 100644
--- a/ide/qml/NotebookCell.qml
+++ b/ide/qml/NotebookCell.qml
@@ -3,51 +3,89 @@
import QtQuick.Controls.Material 2.0
import QtQuick.Layouts 1.0
-ColumnLayout {
+Item {
id: root
required property string code
required property string result
- RowLayout {
- Layout.fillWidth: true
+ signal insertBelowClicked()
+ signal codeEditingFinished(string code)
+ signal cellFocused()
- Button {
- Layout.alignment: Qt.AlignTop
- icon.source: "qrc:///icons/play-circle.svg"
- icon.color: Material.color(Material.Grey, Material.Shade600)
- flat: true
- }
+ height: column.height
- ColumnLayout {
+ MouseArea {
+ id: selectCell
+
+ anchors.fill: column
+
+ onClicked: root.cellFocused()
+ }
+
+ ColumnLayout {
+ id: column
+
+ width: parent.width
+
+ RowLayout {
+ id: row
Layout.fillWidth: true
- Layout.fillHeight: true
- TextArea {
+ RoundButton {
+ Layout.alignment: Qt.AlignTop
+ icon.source: "qrc:///icons/play-circle.svg"
+ icon.color: Material.color(Material.Grey, Material.Shade600)
+ flat: true
+ }
+
+ ColumnLayout {
Layout.fillWidth: true
Layout.fillHeight: true
- id: code
- font.family: "monospace"
- text: root.code
- selectByMouse: true
- wrapMode: TextEdit.WrapAtWordBoundaryOrAnywhere
- Keys.onTabPressed: {
- var pos = cursorPosition + 4
- text += " ";
- cursorPosition = pos
+ TextArea {
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ id: code
+ font.family: "monospace"
+ text: root.code
+ selectByMouse: true
+ wrapMode: TextEdit.WrapAtWordBoundaryOrAnywhere
+
+ Keys.onTabPressed: {
+ var pos = cursorPosition + 4
+ text = text.slice(0, cursorPosition) + " " + text.slice(cursorPosition);
+ cursorPosition = pos
+ }
+
+ Keys.onEscapePressed: {
+ root.forceActiveFocus()
+ }
+
+ onEditingFinished: {
+ root.codeEditingFinished(text)
+ }
+
+ onFocusChanged: if (focus) root.cellFocused()
+ }
+
+ Label {
+ visible: root.result.length > 0
+ Layout.fillWidth: true
+ font.family: "monospace"
+ text: root.result
}
}
- Label {
- Layout.fillWidth: true
- font.family: "monospace"
- text: root.result
+ RoundButton {
+ icon.source: "qrc:///icons/trash.svg"
+ icon.color: Material.color(Material.Grey, Material.theme == Material.Dark ? Material.Shade400 : Material.Shade600)
+ flat: true
}
}
- }
- InsertRow {
-
+ InsertRow {
+ onInsertClicked: root.insertBelowClicked()
+ }
}
}
diff --git a/ide/qml/main.qml b/ide/qml/main.qml
index 73a4581..a28d47d 100644
--- a/ide/qml/main.qml
+++ b/ide/qml/main.qml
@@ -15,14 +15,14 @@
Material.theme: Material.Light
Material.accent: Material.Orange
- CellModel {
- id: model
+ Notebook {
+ id: notebook
}
Component.onCompleted: {
- model.addCell("Refal { = Hi!; }", "");
- model.addCell("<Refal>", "Hi!");
- model.addCell("Hello there", "Hello there");
+ notebook.cellModel.addCell("Refal { = Hi!; }", "");
+ notebook.cellModel.addCell("<Refal>", "Hi!");
+ notebook.cellModel.addCell("Hello there", "Hello there");
}
ColumnLayout {
@@ -36,14 +36,17 @@
TabButton {
text: "Example Workspace"
+ width: implicitWidth
}
TabButton {
text: "Another Workspace"
+ width: implicitWidth
}
TabButton {
text: "Testing"
+ width: implicitWidth
}
}
@@ -57,11 +60,26 @@
id: codeEditor
SplitView.fillWidth: true
SplitView.minimumWidth: 400
- model: model
+ model: notebook.cellModel
clip: true
delegate: NotebookCell {
+ id: notebookCell
+
+ required property var model
+ required property var index
+
width: codeEditor.width - 5
+
+ code: model.code
+ result: model.result
+
+ onCodeEditingFinished: model.code = code
+
+ onInsertBelowClicked: {
+ console.info(index)
+ cellModel.insertRows(cellModel.index(0, index), 1)
+ }
}
}
diff --git a/ide/resources.qrc b/ide/resources.qrc
index f48925a..a77a977 100644
--- a/ide/resources.qrc
+++ b/ide/resources.qrc
@@ -5,5 +5,6 @@
<file>icons/play-circle.svg</file>
<file>icons/add.svg</file>
<file>qml/InsertRow.qml</file>
+ <file>icons/trash.svg</file>
</qresource>
</RCC>