More work on the script editor
This commit is contained in:
parent
d1d599a8ec
commit
0c6d75cdd0
@ -21,6 +21,7 @@
|
||||
#include "engine.h"
|
||||
|
||||
#include "rulemanager.h"
|
||||
#include "scriptmanager.h"
|
||||
#include "logmanager.h"
|
||||
#include "tagsmanager.h"
|
||||
#include "configuration/nymeaconfiguration.h"
|
||||
@ -39,6 +40,7 @@ Engine::Engine(QObject *parent) :
|
||||
m_jsonRpcClient(new JsonRpcClient(m_connection, this)),
|
||||
m_deviceManager(new DeviceManager(m_jsonRpcClient, this)),
|
||||
m_ruleManager(new RuleManager(m_jsonRpcClient, this)),
|
||||
m_scriptManager(new ScriptManager(m_jsonRpcClient, this)),
|
||||
m_logManager(new LogManager(m_jsonRpcClient, this)),
|
||||
m_tagsManager(new TagsManager(m_jsonRpcClient, this)),
|
||||
m_nymeaConfiguration(new NymeaConfiguration(m_jsonRpcClient, this)),
|
||||
@ -80,6 +82,11 @@ RuleManager *Engine::ruleManager() const
|
||||
return m_ruleManager;
|
||||
}
|
||||
|
||||
ScriptManager *Engine::scriptManager() const
|
||||
{
|
||||
return m_scriptManager;
|
||||
}
|
||||
|
||||
TagsManager *Engine::tagsManager() const
|
||||
{
|
||||
return m_tagsManager;
|
||||
@ -144,6 +151,7 @@ void Engine::onDeviceManagerFetchingChanged()
|
||||
{
|
||||
if (!m_deviceManager->fetchingData()) {
|
||||
m_ruleManager->init();
|
||||
m_scriptManager->init();
|
||||
m_nymeaConfiguration->init();
|
||||
m_systemController->init();
|
||||
if (m_jsonRpcClient->ensureServerVersion("1.7")) {
|
||||
|
||||
@ -29,6 +29,7 @@
|
||||
#include "wifisetup/bluetoothdiscovery.h"
|
||||
|
||||
class RuleManager;
|
||||
class ScriptManager;
|
||||
class LogManager;
|
||||
class TagsManager;
|
||||
class NymeaConfiguration;
|
||||
@ -41,6 +42,7 @@ class Engine : public QObject
|
||||
Q_PROPERTY(NymeaConnection* connection READ connection CONSTANT)
|
||||
Q_PROPERTY(DeviceManager* deviceManager READ deviceManager CONSTANT)
|
||||
Q_PROPERTY(RuleManager* ruleManager READ ruleManager CONSTANT)
|
||||
Q_PROPERTY(ScriptManager* scriptManager READ scriptManager CONSTANT)
|
||||
Q_PROPERTY(TagsManager* tagsManager READ tagsManager CONSTANT)
|
||||
Q_PROPERTY(JsonRpcClient* jsonRpcClient READ jsonRpcClient CONSTANT)
|
||||
Q_PROPERTY(NymeaConfiguration* nymeaConfiguration READ nymeaConfiguration CONSTANT)
|
||||
@ -55,6 +57,7 @@ public:
|
||||
NymeaConnection *connection() const;
|
||||
DeviceManager *deviceManager() const;
|
||||
RuleManager *ruleManager() const;
|
||||
ScriptManager *scriptManager() const;
|
||||
TagsManager *tagsManager() const;
|
||||
JsonRpcClient *jsonRpcClient() const;
|
||||
LogManager *logManager() const;
|
||||
@ -68,6 +71,7 @@ private:
|
||||
JsonRpcClient *m_jsonRpcClient;
|
||||
DeviceManager *m_deviceManager;
|
||||
RuleManager *m_ruleManager;
|
||||
ScriptManager *m_scriptManager;
|
||||
LogManager *m_logManager;
|
||||
TagsManager *m_tagsManager;
|
||||
NymeaConfiguration *m_nymeaConfiguration;
|
||||
|
||||
@ -69,6 +69,9 @@
|
||||
#include "types/networkdevices.h"
|
||||
#include "types/networkdevice.h"
|
||||
#include "scriptsyntaxhighlighter.h"
|
||||
#include "scriptmanager.h"
|
||||
#include "types/script.h"
|
||||
#include "types/scripts.h"
|
||||
|
||||
#include <QtQml/qqml.h>
|
||||
|
||||
@ -232,6 +235,9 @@ void registerQmlTypes() {
|
||||
qmlRegisterUncreatableType<WiredNetworkDevice>(uri, 1, 0, "WiredNetworkDevice", "Get it from NetworkDevices");
|
||||
qmlRegisterUncreatableType<WirelessNetworkDevice>(uri, 1, 0, "WirelessNetworkDevice", "Get it from NetworkDevices");
|
||||
|
||||
qmlRegisterUncreatableType<ScriptManager>(uri, 1, 0, "ScriptManager", "Get it from Engine");
|
||||
qmlRegisterUncreatableType<Scripts>(uri, 1, 0, "Scripts", "Getit from ScriptManager");
|
||||
qmlRegisterUncreatableType<Script>(uri, 1, 0, "Script", "Getit from Scripts");
|
||||
qmlRegisterType<ScriptSyntaxHighlighter>(uri, 1, 0, "ScriptSyntaxHighlighter");
|
||||
qmlRegisterUncreatableType<CompletionProxyModel>(uri, 1, 0, "CompletionProxyModel", "Get it from ScriptSyntaxHighlighter");
|
||||
}
|
||||
|
||||
@ -48,6 +48,7 @@ SOURCES += \
|
||||
devicediscovery.cpp \
|
||||
models/packagesfiltermodel.cpp \
|
||||
models/taglistmodel.cpp \
|
||||
scriptmanager.cpp \
|
||||
scriptsyntaxhighlighter.cpp \
|
||||
vendorsproxy.cpp \
|
||||
pluginsproxy.cpp \
|
||||
@ -112,6 +113,7 @@ HEADERS += \
|
||||
devicediscovery.h \
|
||||
models/packagesfiltermodel.h \
|
||||
models/taglistmodel.h \
|
||||
scriptmanager.h \
|
||||
scriptsyntaxhighlighter.h \
|
||||
vendorsproxy.h \
|
||||
pluginsproxy.h \
|
||||
|
||||
83
libnymea-app-core/scriptmanager.cpp
Normal file
83
libnymea-app-core/scriptmanager.cpp
Normal file
@ -0,0 +1,83 @@
|
||||
#include "scriptmanager.h"
|
||||
|
||||
#include "types/script.h"
|
||||
#include "types/scripts.h"
|
||||
|
||||
ScriptManager::ScriptManager(JsonRpcClient *jsonClient, QObject *parent):
|
||||
QObject(parent),
|
||||
m_client(jsonClient)
|
||||
{
|
||||
m_scripts = new Scripts(this);
|
||||
}
|
||||
|
||||
void ScriptManager::init()
|
||||
{
|
||||
m_scripts->clear();
|
||||
m_client->sendCommand("Scripts.GetScripts", QVariantMap(), this, "onScriptsFetched");
|
||||
}
|
||||
|
||||
Scripts *ScriptManager::scripts() const
|
||||
{
|
||||
return m_scripts;
|
||||
}
|
||||
|
||||
int ScriptManager::addScript(const QString &content)
|
||||
{
|
||||
QVariantMap params;
|
||||
params.insert("name", "Test");
|
||||
params.insert("content", content);
|
||||
return m_client->sendCommand("Scripts.AddScript", params, this, "onScriptAdded");
|
||||
}
|
||||
|
||||
int ScriptManager::editScript(const QUuid &id, const QString &content)
|
||||
{
|
||||
QVariantMap params;
|
||||
params.insert("id", id);
|
||||
params.insert("content", content);
|
||||
return m_client->sendCommand("Scripts.EditScript", params, this, "onScriptEdited");
|
||||
}
|
||||
|
||||
int ScriptManager::removeScript(const QUuid &id)
|
||||
{
|
||||
QVariantMap params;
|
||||
params.insert("id", id);
|
||||
return m_client->sendCommand("Scripts.RemoveScript", params, this, "onScriptRemoved");
|
||||
}
|
||||
|
||||
void ScriptManager::onScriptsFetched(const QVariantMap ¶ms)
|
||||
{
|
||||
qDebug() << "scripts fetched" << params;
|
||||
foreach (const QVariant &variant, params.value("params").toMap().value("scripts").toList()) {
|
||||
qDebug() << "script" << variant.toMap().value("id").toUuid();
|
||||
QUuid id = variant.toMap().value("id").toUuid();
|
||||
Script *script = new Script(id);
|
||||
script->setName(variant.toMap().value("name").toString());
|
||||
m_scripts->addScript(script);
|
||||
qDebug() << "Script added";
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptManager::onScriptAdded(const QVariantMap ¶ms)
|
||||
{
|
||||
qDebug() << "Script added" << params;
|
||||
emit scriptAdded(params.value("id").toInt(),
|
||||
params.value("params").toMap().value("scriptError").toString(),
|
||||
params.value("params").toMap().value("script").toMap().value("id").toUuid(),
|
||||
params.value("params").toMap().value("errors").toStringList());
|
||||
|
||||
}
|
||||
|
||||
void ScriptManager::onScriptEdited(const QVariantMap ¶ms)
|
||||
{
|
||||
qDebug() << "Script edited" << params;
|
||||
// emit scriptAdded(params.value("id").toInt(), params.value("script").toMap().value("id").toUuid());
|
||||
emit scriptEdited(params.value("id").toInt(),
|
||||
params.value("params").toMap().value("scriptError").toString(),
|
||||
params.value("params").toMap().value("errors").toStringList());
|
||||
|
||||
}
|
||||
|
||||
void ScriptManager::onScriptRemoved(const QVariantMap ¶ms)
|
||||
{
|
||||
emit scriptRemoved(params.value("id").toInt(), params.value("params").toMap().value("scriptError").toString());
|
||||
}
|
||||
43
libnymea-app-core/scriptmanager.h
Normal file
43
libnymea-app-core/scriptmanager.h
Normal file
@ -0,0 +1,43 @@
|
||||
#ifndef SCRIPTMANAGER_H
|
||||
#define SCRIPTMANAGER_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "jsonrpc/jsonrpcclient.h"
|
||||
|
||||
class Scripts;
|
||||
|
||||
class ScriptManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(Scripts* scripts READ scripts CONSTANT)
|
||||
|
||||
public:
|
||||
explicit ScriptManager(JsonRpcClient* jsonClient, QObject *parent = nullptr);
|
||||
|
||||
void init();
|
||||
|
||||
Scripts *scripts() const;
|
||||
|
||||
public slots:
|
||||
int addScript(const QString &content);
|
||||
int editScript(const QUuid &id, const QString &content);
|
||||
int removeScript(const QUuid &id);
|
||||
|
||||
signals:
|
||||
void scriptAdded(int id, const QString &scriptError, const QUuid &scriptId, const QStringList &errors);
|
||||
void scriptEdited(int id, const QString &scriptError, const QStringList &errors);
|
||||
void scriptRemoved(int id, const QString &scriptError);
|
||||
|
||||
private slots:
|
||||
void onScriptsFetched(const QVariantMap ¶ms);
|
||||
void onScriptAdded(const QVariantMap ¶ms);
|
||||
void onScriptEdited(const QVariantMap ¶ms);
|
||||
void onScriptRemoved(const QVariantMap ¶ms);
|
||||
|
||||
private:
|
||||
JsonRpcClient* m_client = nullptr;
|
||||
Scripts *m_scripts = nullptr;
|
||||
};
|
||||
|
||||
#endif // SCRIPTMANAGER_H
|
||||
@ -16,6 +16,8 @@ HEADERS += \
|
||||
types/packages.h \
|
||||
types/repositories.h \
|
||||
types/repository.h \
|
||||
types/script.h \
|
||||
types/scripts.h \
|
||||
types/types.h \
|
||||
types/vendor.h \
|
||||
types/vendors.h \
|
||||
@ -72,6 +74,8 @@ SOURCES += \
|
||||
types/packages.cpp \
|
||||
types/repositories.cpp \
|
||||
types/repository.cpp \
|
||||
types/script.cpp \
|
||||
types/scripts.cpp \
|
||||
types/vendor.cpp \
|
||||
types/vendors.cpp \
|
||||
types/deviceclass.cpp \
|
||||
|
||||
26
libnymea-common/types/script.cpp
Normal file
26
libnymea-common/types/script.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
#include "script.h"
|
||||
|
||||
Script::Script(const QUuid &id, QObject *parent):
|
||||
QObject(parent),
|
||||
m_id(id)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QUuid Script::id() const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
QString Script::name() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
void Script::setName(const QString &name)
|
||||
{
|
||||
if (m_name != name) {
|
||||
m_name = name;
|
||||
emit nameChanged();
|
||||
}
|
||||
}
|
||||
28
libnymea-common/types/script.h
Normal file
28
libnymea-common/types/script.h
Normal file
@ -0,0 +1,28 @@
|
||||
#ifndef SCRIPT_H
|
||||
#define SCRIPT_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QUuid>
|
||||
|
||||
class Script : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QUuid id READ id CONSTANT)
|
||||
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
|
||||
public:
|
||||
explicit Script(const QUuid &id, QObject *parent = nullptr);
|
||||
|
||||
QUuid id() const;
|
||||
|
||||
QString name() const;
|
||||
void setName(const QString &name);
|
||||
|
||||
signals:
|
||||
void nameChanged();
|
||||
|
||||
private:
|
||||
QUuid m_id;
|
||||
QString m_name;
|
||||
};
|
||||
|
||||
#endif // SCRIPT_H
|
||||
52
libnymea-common/types/scripts.cpp
Normal file
52
libnymea-common/types/scripts.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
#include "scripts.h"
|
||||
|
||||
#include "script.h"
|
||||
|
||||
Scripts::Scripts(QObject *parent) : QAbstractListModel(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int Scripts::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
return m_list.count();
|
||||
}
|
||||
|
||||
QVariant Scripts::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
switch (role) {
|
||||
case RoleId:
|
||||
return m_list.at(index.row())->id();
|
||||
case RoleName:
|
||||
return m_list.at(index.row())->name();
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> Scripts::roleNames() const
|
||||
{
|
||||
QHash<int, QByteArray> roles;
|
||||
roles.insert(RoleId, "id");
|
||||
roles.insert(RoleName, "name");
|
||||
return roles;
|
||||
|
||||
}
|
||||
|
||||
void Scripts::clear()
|
||||
{
|
||||
beginResetModel();
|
||||
qDeleteAll(m_list);
|
||||
m_list.clear();
|
||||
endResetModel();
|
||||
emit countChanged();
|
||||
}
|
||||
|
||||
void Scripts::addScript(Script *script)
|
||||
{
|
||||
script->setParent(this);
|
||||
beginInsertRows(QModelIndex(), m_list.count(), m_list.count());
|
||||
m_list.append(script);
|
||||
endInsertRows();
|
||||
emit countChanged();
|
||||
}
|
||||
35
libnymea-common/types/scripts.h
Normal file
35
libnymea-common/types/scripts.h
Normal file
@ -0,0 +1,35 @@
|
||||
#ifndef SCRIPTS_H
|
||||
#define SCRIPTS_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QAbstractListModel>
|
||||
|
||||
class Script;
|
||||
|
||||
class Scripts : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
|
||||
public:
|
||||
enum Roles {
|
||||
RoleId,
|
||||
RoleName
|
||||
};
|
||||
|
||||
explicit Scripts(QObject *parent = nullptr);
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
void clear();
|
||||
void addScript(Script *script);
|
||||
signals:
|
||||
void countChanged();
|
||||
|
||||
private:
|
||||
QList<Script*> m_list;
|
||||
|
||||
};
|
||||
|
||||
#endif // SCRIPTS_H
|
||||
@ -204,5 +204,6 @@
|
||||
<file>ui/components/TimePicker.qml</file>
|
||||
<file>ui/components/DatePicker.qml</file>
|
||||
<file>ui/magic/ScriptEditor.qml</file>
|
||||
<file>ui/magic/ScriptsPage.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@ -13,7 +13,7 @@ Page {
|
||||
HeaderButton {
|
||||
imageSource: Qt.resolvedUrl("images/magic.svg")
|
||||
onClicked: {
|
||||
pageStack.push("magic/ScriptEditor.qml")
|
||||
pageStack.push("magic/ScriptsPage.qml")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@ import QtQuick 2.0
|
||||
import QtQuick.Controls 2.2
|
||||
import "../components"
|
||||
import Nymea 1.0
|
||||
import QtQuick.Layouts 1.2
|
||||
|
||||
Page {
|
||||
id: root
|
||||
@ -9,124 +10,179 @@ Page {
|
||||
header: NymeaHeader {
|
||||
text: qsTr("Script editor")
|
||||
onBackPressed: pageStack.pop()
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
color: "white"
|
||||
anchors.fill: parent
|
||||
|
||||
TextEdit {
|
||||
id: scriptEdit
|
||||
anchors.fill: parent
|
||||
font.family: "Monospace"
|
||||
Keys.onPressed: {
|
||||
print("key", event.key)
|
||||
// Things only to happen when we're not autocompleting
|
||||
if (!completionBox.visible) {
|
||||
switch (event.key) {
|
||||
case Qt.Key_Return:
|
||||
case Qt.Key_Enter:
|
||||
syntax.newLine();
|
||||
event.accepted = true;
|
||||
return;
|
||||
case Qt.Key_Tab:
|
||||
syntax.indent(selectionStart, selectionEnd);
|
||||
event.accepted = true;
|
||||
return;
|
||||
case Qt.Key_Backtab:
|
||||
syntax.unindent(selectionStart, selectionEnd);
|
||||
event.accepted = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// things to happen in any case
|
||||
switch (event.key) {
|
||||
case Qt.Key_BraceRight:
|
||||
syntax.closeBlock();
|
||||
event.accepted = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// Things to do only when we're autocompleting
|
||||
if (completionBox.visible) {
|
||||
switch (event.key) {
|
||||
case Qt.Key_Escape:
|
||||
completionBox.hide();
|
||||
event.accepted = true;
|
||||
break;
|
||||
case Qt.Key_Down:
|
||||
completionBox.next();
|
||||
event.accepted = true;
|
||||
break;
|
||||
case Qt.Key_Up:
|
||||
completionBox.previous();
|
||||
event.accepted = true;
|
||||
break;
|
||||
case Qt.Key_Enter:
|
||||
case Qt.Key_Return:
|
||||
syntax.complete(completionBox.currentIndex)
|
||||
event.accepted = true;
|
||||
break;
|
||||
}
|
||||
HeaderButton {
|
||||
imageSource: "../images/tick.svg"
|
||||
onClicked: {
|
||||
if (!d.scriptId) {
|
||||
d.callId = engine.scriptManager.addScript(scriptEdit.text)
|
||||
} else {
|
||||
print("editing script", d.scriptId)
|
||||
d.callId = engine.scriptManager.editScript(d.scriptId, scriptEdit.text)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: completionBox
|
||||
border.width: 1
|
||||
border.color: "black"
|
||||
height: syntax.completionModel.count * 30
|
||||
width: 200
|
||||
x: scriptEdit.cursorRectangle.x
|
||||
y: scriptEdit.cursorRectangle.y + scriptEdit.cursorRectangle.height
|
||||
visible: syntax.completionModel.count > 0 && !hidden
|
||||
property bool hidden: false
|
||||
Connections {
|
||||
target: syntax.completionModel
|
||||
onCountChanged: {
|
||||
completionBox.hidden = false;
|
||||
completionBox.currentIndex = 0;
|
||||
}
|
||||
}
|
||||
QtObject {
|
||||
id: d
|
||||
property int callId
|
||||
property var scriptId
|
||||
}
|
||||
|
||||
property int currentIndex: 0
|
||||
function next() { currentIndex = (currentIndex + 1) % syntax.completionModel.count}
|
||||
function previous() {
|
||||
currentIndex--;
|
||||
if (currentIndex < 0) {
|
||||
currentIndex = syntax.completionModel.count - 1
|
||||
}
|
||||
}
|
||||
function hide() {
|
||||
hidden = true;
|
||||
}
|
||||
Component.onCompleted: {
|
||||
d.callId = engine.scriptManager.addScript(scriptEdit.text);
|
||||
}
|
||||
|
||||
ListView {
|
||||
anchors.fill: parent
|
||||
model: syntax.completionModel
|
||||
delegate: Rectangle {
|
||||
height: 30
|
||||
width: parent.width
|
||||
color: index == completionBox.currentIndex ? "blue" : "white"
|
||||
Label {
|
||||
text: model.displayText
|
||||
color: "black"
|
||||
width: parent.width
|
||||
elide: Text.ElideRight
|
||||
Connections {
|
||||
target: engine.scriptManager
|
||||
onScriptAdded: {
|
||||
if (id == d.callId) {
|
||||
if (scriptError == "ScriptErrorNoError") {
|
||||
d.scriptId = scriptId;
|
||||
}
|
||||
errorListView.model = errors
|
||||
}
|
||||
}
|
||||
onScriptEdited: {
|
||||
if (id == d.callId) {
|
||||
errorListView.model = errors
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
|
||||
Rectangle {
|
||||
color: "white"
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
TextEdit {
|
||||
id: scriptEdit
|
||||
anchors.fill: parent
|
||||
font.family: "Monospace"
|
||||
Keys.onPressed: {
|
||||
print("key", event.key)
|
||||
// Things only to happen when we're not autocompleting
|
||||
if (!completionBox.visible) {
|
||||
switch (event.key) {
|
||||
case Qt.Key_Return:
|
||||
case Qt.Key_Enter:
|
||||
syntax.newLine();
|
||||
event.accepted = true;
|
||||
return;
|
||||
case Qt.Key_Tab:
|
||||
syntax.indent(selectionStart, selectionEnd);
|
||||
event.accepted = true;
|
||||
return;
|
||||
case Qt.Key_Backtab:
|
||||
syntax.unindent(selectionStart, selectionEnd);
|
||||
event.accepted = true;
|
||||
return;
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
syntax.complete(index)
|
||||
}
|
||||
|
||||
// things to happen in any case
|
||||
switch (event.key) {
|
||||
case Qt.Key_BraceRight:
|
||||
syntax.closeBlock();
|
||||
event.accepted = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// Things to do only when we're autocompleting
|
||||
if (completionBox.visible) {
|
||||
switch (event.key) {
|
||||
case Qt.Key_Escape:
|
||||
completionBox.hide();
|
||||
event.accepted = true;
|
||||
break;
|
||||
case Qt.Key_Down:
|
||||
completionBox.next();
|
||||
event.accepted = true;
|
||||
break;
|
||||
case Qt.Key_Up:
|
||||
completionBox.previous();
|
||||
event.accepted = true;
|
||||
break;
|
||||
case Qt.Key_Enter:
|
||||
case Qt.Key_Return:
|
||||
syntax.complete(completionBox.currentIndex)
|
||||
event.accepted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: completionBox
|
||||
border.width: 1
|
||||
border.color: "black"
|
||||
height: syntax.completionModel.count * 30
|
||||
width: 200
|
||||
x: scriptEdit.cursorRectangle.x
|
||||
y: scriptEdit.cursorRectangle.y + scriptEdit.cursorRectangle.height
|
||||
visible: syntax.completionModel.count > 0 && !hidden
|
||||
property bool hidden: false
|
||||
Connections {
|
||||
target: syntax.completionModel
|
||||
onCountChanged: {
|
||||
completionBox.hidden = false;
|
||||
completionBox.currentIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
property int currentIndex: 0
|
||||
function next() { currentIndex = (currentIndex + 1) % syntax.completionModel.count}
|
||||
function previous() {
|
||||
currentIndex--;
|
||||
if (currentIndex < 0) {
|
||||
currentIndex = syntax.completionModel.count - 1
|
||||
}
|
||||
}
|
||||
function hide() {
|
||||
hidden = true;
|
||||
}
|
||||
|
||||
ListView {
|
||||
anchors.fill: parent
|
||||
model: syntax.completionModel
|
||||
delegate: Rectangle {
|
||||
height: 30
|
||||
width: parent.width
|
||||
color: index == completionBox.currentIndex ? "blue" : "white"
|
||||
Label {
|
||||
text: model.displayText
|
||||
color: "black"
|
||||
width: parent.width
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
syntax.complete(index)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: errorListView
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 100
|
||||
delegate: Label {
|
||||
width: parent.width
|
||||
text: modelData
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ScriptSyntaxHighlighter {
|
||||
id: syntax
|
||||
engine: _engine
|
||||
|
||||
53
nymea-app/ui/magic/ScriptsPage.qml
Normal file
53
nymea-app/ui/magic/ScriptsPage.qml
Normal file
@ -0,0 +1,53 @@
|
||||
import QtQuick 2.0
|
||||
import Nymea 1.0
|
||||
import QtQuick.Controls 2.2
|
||||
import "../components"
|
||||
|
||||
Page {
|
||||
header: NymeaHeader {
|
||||
text: qsTr("Scripts")
|
||||
onBackPressed: pageStack.pop();
|
||||
|
||||
HeaderButton {
|
||||
text: qsTr("Add new script")
|
||||
imageSource: "../images/add.svg"
|
||||
onClicked: {
|
||||
pageStack.push("ScriptEditor.qml");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
property int pendingAction: -1
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: engine.scriptManager
|
||||
onScriptRemoved: {
|
||||
if (id == d.pendingAction) {
|
||||
d.pendingAction = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ListView {
|
||||
anchors.fill: parent
|
||||
model: engine.scriptManager.scripts
|
||||
delegate: NymeaListItemDelegate {
|
||||
width: parent.width
|
||||
text: model.name
|
||||
subText: model.id
|
||||
canDelete: true
|
||||
onDeleteClicked: {
|
||||
print("removing script", model.id)
|
||||
d.pendingAction = engine.scriptManager.removeScript(model.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BusyOverlay {
|
||||
id: busyOverlay
|
||||
visible: d.pendingAction != -1
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user