From 72fd175ea97deaebd4408bee5ef055fb5f7b2a15 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Sun, 30 Aug 2020 12:53:34 +0200 Subject: [PATCH] Autocomplete action parameters in script editor --- libnymea-app/devicemanager.cpp | 21 ++++--- libnymea-app/devicemanager.h | 3 +- libnymea-app/scripting/codecompletion.cpp | 75 ++++++++++++++++++++--- libnymea-app/scripting/codecompletion.h | 1 + 4 files changed, 83 insertions(+), 17 deletions(-) diff --git a/libnymea-app/devicemanager.cpp b/libnymea-app/devicemanager.cpp index c95b568b..7b46a240 100644 --- a/libnymea-app/devicemanager.cpp +++ b/libnymea-app/devicemanager.cpp @@ -43,7 +43,7 @@ DeviceManager::DeviceManager(JsonRpcClient* jsonclient, QObject *parent) : m_vendors(new Vendors(this)), m_plugins(new Plugins(this)), m_devices(new Devices(this)), - m_deviceClasses(new DeviceClasses(this)), + m_thingClasses(new DeviceClasses(this)), m_ioConnections(new IOConnections(this)), m_jsonClient(jsonclient) { @@ -53,7 +53,7 @@ DeviceManager::DeviceManager(JsonRpcClient* jsonclient, QObject *parent) : void DeviceManager::clear() { m_devices->clearModel(); - m_deviceClasses->clearModel(); + m_thingClasses->clearModel(); m_vendors->clearModel(); m_plugins->clearModel(); m_ioConnections->clearModel(); @@ -133,7 +133,12 @@ Devices *DeviceManager::things() const DeviceClasses *DeviceManager::deviceClasses() const { - return m_deviceClasses; + return m_thingClasses; +} + +DeviceClasses *DeviceManager::thingClasses() const +{ + return m_thingClasses; } IOConnections *DeviceManager::ioConnections() const @@ -170,7 +175,7 @@ void DeviceManager::notificationReceived(const QVariantMap &data) // qDebug() << "Device state changed for:" << dev->name() << "State name:" << dev->thingClass()->stateTypes()->getStateType(stateTyoeId) << "value:" << value; dev->setStateValue(stateTyoeId, value); } else if (notification == "Devices.DeviceAdded") { - Device *dev = JsonTypes::unpackDevice(this, data.value("params").toMap().value("device").toMap(), m_deviceClasses); + Device *dev = JsonTypes::unpackDevice(this, data.value("params").toMap().value("device").toMap(), m_thingClasses); if (!dev) { qWarning() << "Cannot parse json device:" << data; return; @@ -200,7 +205,7 @@ void DeviceManager::notificationReceived(const QVariantMap &data) qWarning() << "Received a device changed notification for a device we don't know"; return; } - if (!JsonTypes::unpackDevice(this, data.value("params").toMap().value("device").toMap(), m_deviceClasses, oldDevice)) { + if (!JsonTypes::unpackDevice(this, data.value("params").toMap().value("device").toMap(), m_thingClasses, oldDevice)) { qWarning() << "Error parsing device changed notification"; return; } @@ -279,7 +284,7 @@ void DeviceManager::getSupportedDevicesResponse(const QVariantMap ¶ms) QVariantList deviceClassList = params.value("params").toMap().value("deviceClasses").toList(); foreach (QVariant deviceClassVariant, deviceClassList) { DeviceClass *deviceClass = JsonTypes::unpackDeviceClass(deviceClassVariant.toMap(), deviceClasses()); - m_deviceClasses->addDeviceClass(deviceClass); + m_thingClasses->addDeviceClass(deviceClass); } } m_jsonClient->sendCommand("Devices.GetConfiguredDevices", this, "getConfiguredDevicesResponse"); @@ -333,7 +338,7 @@ void DeviceManager::getConfiguredDevicesResponse(const QVariantMap ¶ms) if (params.value("params").toMap().keys().contains("devices")) { QVariantList deviceList = params.value("params").toMap().value("devices").toList(); foreach (QVariant deviceVariant, deviceList) { - Device *device = JsonTypes::unpackDevice(this, deviceVariant.toMap(), m_deviceClasses); + Device *device = JsonTypes::unpackDevice(this, deviceVariant.toMap(), m_thingClasses); if (!device) { qWarning() << "Error unpacking device" << deviceVariant.toMap().value("name").toString(); continue; @@ -378,7 +383,7 @@ void DeviceManager::addDeviceResponse(const QVariantMap ¶ms) qWarning() << "Failed to add the device:" << params.value("params").toMap().value("deviceError").toString(); } else if (params.value("params").toMap().keys().contains("device")) { QVariantMap deviceVariant = params.value("params").toMap().value("device").toMap(); - Device *device = JsonTypes::unpackDevice(this, deviceVariant, m_deviceClasses); + Device *device = JsonTypes::unpackDevice(this, deviceVariant, m_thingClasses); if (!device) { qWarning() << "Couldn't parse json in addDeviceResponse"; return; diff --git a/libnymea-app/devicemanager.h b/libnymea-app/devicemanager.h index 872bd480..23726671 100644 --- a/libnymea-app/devicemanager.h +++ b/libnymea-app/devicemanager.h @@ -81,6 +81,7 @@ public: Devices* devices() const; Devices* things() const; DeviceClasses* deviceClasses() const; + DeviceClasses* thingClasses() const; IOConnections* ioConnections() const; bool fetchingData() const; @@ -156,7 +157,7 @@ private: Vendors *m_vendors; Plugins *m_plugins; Devices *m_devices; - DeviceClasses *m_deviceClasses; + DeviceClasses *m_thingClasses; IOConnections *m_ioConnections; bool m_fetchingData = false; diff --git a/libnymea-app/scripting/codecompletion.cpp b/libnymea-app/scripting/codecompletion.cpp index 9c1fc99b..16d751ab 100644 --- a/libnymea-app/scripting/codecompletion.cpp +++ b/libnymea-app/scripting/codecompletion.cpp @@ -427,7 +427,41 @@ void CodeCompletion::update() entries.append(CompletionModel::Entry(property, property, "property")); } foreach (const QString &method, m_classes.value(type).methods) { - entries.append(CompletionModel::Entry(method + "(", method, "method", "", ")")); + QString paramString; + if (method == "execute") { + int blockposition = getBlockPosition(id); + qDebug() << "Blockposition:" << blockposition; + if (blockposition >= 0) { + BlockInfo info = getBlockInfo(blockposition); + qDebug() << "actionType" << info.properties.keys() << info.properties.value("actionName") << info.properties.value("actionTypeId"); + if (info.valid) { + QString thingId = info.properties.value("thingId"); + if (thingId.isEmpty()) { + thingId = info.properties.value("deviceId"); + } + Device *d = m_engine->thingManager()->things()->getDevice(QUuid(thingId)); + if (d) { + ActionType *at = nullptr; + if (info.properties.contains("actionTypeId")) { + at = d->thingClass()->actionTypes()->getActionType(info.properties.value("actionTypeId")); + } else if (info.properties.contains("actionName")) { + at = d->thingClass()->actionTypes()->findByName(info.properties.value("actionName")); + } + if (at) { + QStringList params; + QStringList nonEscapeTypes = {"Int", "Bool", "Double"}; + for (int i = 0; i < at->paramTypes()->rowCount(); i++) { + ParamType *pt = at->paramTypes()->get(i); + QString escapeChar = nonEscapeTypes.contains(pt->type()) ? "" : "\""; + params.append("\"" + pt->name() + "\": " + escapeChar + pt->defaultValue().toString() + escapeChar); + } + paramString = "{" + params.join(", ") + "}"; + } + } + } + } + } + entries.append(CompletionModel::Entry(method + "(", method, "method", "", paramString + ")")); } // Attached classes/properties foreach (const QString &property, m_attachedClasses.value(id).properties) { @@ -537,6 +571,7 @@ CodeCompletion::BlockInfo CodeCompletion::getBlockInfo(int position) const { BlockInfo info; + // Find start of block QTextCursor blockStart = m_document->textDocument()->find("{", position, QTextDocument::FindBackward); QTextCursor blockEnd = m_document->textDocument()->find("}", position, QTextDocument::FindBackward); while (blockEnd.position() > blockStart.position() && !blockStart.isNull()) { @@ -548,21 +583,26 @@ CodeCompletion::BlockInfo CodeCompletion::getBlockInfo(int position) const return info; } + // Find end of block + QTextCursor tmp = blockStart; + blockEnd = blockStart; + while (!tmp.isNull() && blockEnd >= tmp) { + tmp = m_document->textDocument()->find("{", tmp.position()); + blockEnd = m_document->textDocument()->find("}", blockEnd.position()); + } + info.start = blockStart.position(); - info.end = m_document->textDocument()->find("}", position).position(); + info.end = blockEnd.position(); //m_document->textDocument()->find("}", position).position(); info.valid = true; - qDebug() << "block name" << blockStart.block().text(); info.name = blockStart.block().text(); info.name.remove(QRegExp(" *\\{ *")); - qDebug() << "stripped klammer" << info.name; while (info.name.contains(" ")) { info.name.remove(QRegExp(".* ")); } - qDebug() << "final name" << info.name; int childBlocks = 0; - while (!blockStart.isNull() && blockStart.position() < position) { + while (!blockStart.isNull() && blockStart.position() < info.end) { QString line = blockStart.block().text(); if (line.endsWith("{")) { childBlocks++; @@ -584,14 +624,12 @@ CodeCompletion::BlockInfo CodeCompletion::getBlockInfo(int position) const continue; } foreach (const QString &statement, blockStart.block().text().split(";")) { -// qDebug() << "Have statement" << statement; QStringList parts = statement.split(":"); if (parts.length() != 2) { continue; } QString propName = parts.first().trimmed(); QString propValue = parts.last().split("//").first().trimmed().remove("\""); -// qDebug() << "inserting:" << propName << "->" << propValue; info.properties.insert(propName, propValue); } if (!blockStart.movePosition(QTextCursor::NextBlock)) { @@ -836,3 +874,24 @@ void CodeCompletion::moveCursor(CodeCompletion::MoveOperation moveOperation, int } } } + +int CodeCompletion::getBlockPosition(const QString &id) const +{ + // Find block with id "id" in the doc + QTextCursor tmp = QTextCursor(m_document->textDocument()); + while (!tmp.atEnd()) { + tmp.movePosition(QTextCursor::StartOfWord, QTextCursor::MoveAnchor); + tmp.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor); + QString word = tmp.selectedText(); + if (word == "id") { + tmp.movePosition(QTextCursor::NextWord, QTextCursor::MoveAnchor); + tmp.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor); + QString idName = tmp.selectedText(); + if (idName == id) { + return tmp.position(); + } + } + tmp.movePosition(QTextCursor::NextWord); + } + return -1; +} diff --git a/libnymea-app/scripting/codecompletion.h b/libnymea-app/scripting/codecompletion.h index d01e77bb..3694c425 100644 --- a/libnymea-app/scripting/codecompletion.h +++ b/libnymea-app/scripting/codecompletion.h @@ -113,6 +113,7 @@ private: QStringList events; }; + int getBlockPosition(const QString &id) const; BlockInfo getBlockInfo(int postition) const; QList getIds() const; QHash getIdTypes() const;