diff --git a/guh-control/devicemanager.cpp b/guh-control/devicemanager.cpp index a30146db..b7685868 100644 --- a/guh-control/devicemanager.cpp +++ b/guh-control/devicemanager.cpp @@ -85,7 +85,7 @@ void DeviceManager::notificationReceived(const QVariantMap &data) { QString notification = data.value("notification").toString(); if (notification == "Devices.StateChanged") { - qDebug() << "Device state changed" << data.value("params"); +// qDebug() << "Device state changed" << data.value("params"); Device *dev = m_devices->getDevice(data.value("params").toMap().value("deviceId").toUuid()); if (!dev) { qWarning() << "Device state change notification received for an unknown device"; diff --git a/guh-control/guh-control.pro b/guh-control/guh-control.pro index 4bdf0d04..82ff64ff 100644 --- a/guh-control/guh-control.pro +++ b/guh-control/guh-control.pro @@ -120,4 +120,6 @@ DISTFILES += \ ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android +target.path = /usr/bin +INSTALLS += target diff --git a/guh-control/jsonrpc/jsonrpcclient.cpp b/guh-control/jsonrpc/jsonrpcclient.cpp index 55c029fa..6b2652ae 100644 --- a/guh-control/jsonrpc/jsonrpcclient.cpp +++ b/guh-control/jsonrpc/jsonrpcclient.cpp @@ -254,10 +254,11 @@ void JsonRpcClient::dataReceived(const QByteArray &data) JsonHandler *handler = m_notificationHandlers.value(nameSpace).first; if (!handler) { - qWarning() << "JsonRpc: handler not implemented:" << nameSpace; +// qWarning() << "JsonRpc: handler not implemented:" << nameSpace; return; } +// qDebug() << "Incoming notification:" << jsonDoc.toJson(); QMetaObject::invokeMethod(handler, m_notificationHandlers.value(nameSpace).second.toLatin1().data(), Q_ARG(QVariantMap, dataMap)); } } diff --git a/guh-control/jsonrpc/jsontypes.cpp b/guh-control/jsonrpc/jsontypes.cpp index e65ee1ce..206f1c83 100644 --- a/guh-control/jsonrpc/jsontypes.cpp +++ b/guh-control/jsonrpc/jsontypes.cpp @@ -24,6 +24,13 @@ #include "deviceclasses.h" #include "types/params.h" #include "types/paramtypes.h" +#include "types/rule.h" +#include "types/ruleaction.h" +#include "types/ruleactions.h" +#include "types/eventdescriptor.h" +#include "types/eventdescriptors.h" +#include "types/ruleactionparam.h" +#include "types/ruleactionparams.h" #include @@ -165,7 +172,7 @@ EventType *JsonTypes::unpackEventType(const QVariantMap &eventTypeMap, QObject * ActionType *JsonTypes::unpackActionType(const QVariantMap &actionTypeMap, QObject *parent) { ActionType *actionType = new ActionType(parent); - actionType->setId(actionTypeMap.value("id").toUuid()); + actionType->setId(actionTypeMap.value("id").toString()); actionType->setName(actionTypeMap.value("name").toString()); actionType->setDisplayName(actionTypeMap.value("displayName").toString()); actionType->setIndex(actionTypeMap.value("index").toInt()); @@ -207,6 +214,58 @@ Device *JsonTypes::unpackDevice(const QVariantMap &deviceMap, QObject *parent) return device; } +QVariantMap JsonTypes::packRule(Rule *rule) +{ + QVariantMap ret; + ret.insert("ruleId", rule->id()); + ret.insert("name", rule->name()); + ret.insert("enabled", true); + + if (rule->ruleActions()->rowCount() > 0) { + QVariantList actions; + for (int i = 0; i < rule->ruleActions()->rowCount(); i++) { + QVariantMap ruleAction; + ruleAction.insert("actionTypeId", rule->ruleActions()->get(i)->actionTypeId()); + ruleAction.insert("deviceId", rule->ruleActions()->get(i)->deviceId()); + if (rule->ruleActions()->get(i)->ruleActionParams()->rowCount() > 0) { + QVariantList ruleActionParams; + for (int j = 0; j < rule->ruleActions()->get(i)->ruleActionParams()->rowCount(); j++) { + QVariantMap ruleActionParam; + ruleActionParam.insert("paramTypeId", rule->ruleActions()->get(i)->ruleActionParams()->get(j)->paramTypeId()); + ruleActionParam.insert("value", rule->ruleActions()->get(i)->ruleActionParams()->get(j)->value()); + ruleActionParams.append(ruleActionParam); + } + ruleAction.insert("ruleActionParams", ruleActionParams); + } + actions.append(ruleAction); + } + ret.insert("actions", actions); + } + + if (rule->eventDescriptors()->rowCount() > 0) { + QVariantList eventDescriptors; + for (int i = 0; i < rule->eventDescriptors()->rowCount(); i++) { + QVariantMap eventDescriptor; + eventDescriptor.insert("eventTypeId", rule->eventDescriptors()->get(i)->eventTypeId()); + eventDescriptor.insert("deviceId", rule->eventDescriptors()->get(i)->deviceId()); + if (rule->eventDescriptors()->get(i)->paramDescriptors()->rowCount() > 0) { + QVariantList paramDescriptors; + for (int j = 0; j < rule->eventDescriptors()->get(i)->paramDescriptors()->rowCount(); j++) { + QVariantMap paramDescriptor; + paramDescriptor.insert("paramTypeId", rule->eventDescriptors()->get(i)->paramDescriptors()->get(j)->id()); + paramDescriptor.insert("value", rule->eventDescriptors()->get(i)->paramDescriptors()->get(j)->value()); + paramDescriptors.append(paramDescriptor); + } + eventDescriptor.insert("paramDescriptors", paramDescriptors); + } + eventDescriptors.append(eventDescriptor); + } + ret.insert("eventDescriptors", eventDescriptors); + } + + return ret; +} + DeviceClass::SetupMethod JsonTypes::stringToSetupMethod(const QString &setupMethodString) { if (setupMethodString == "SetupMethodJustAdd") { diff --git a/guh-control/jsonrpc/jsontypes.h b/guh-control/jsonrpc/jsontypes.h index 7189feca..e750fc7c 100644 --- a/guh-control/jsonrpc/jsontypes.h +++ b/guh-control/jsonrpc/jsontypes.h @@ -37,6 +37,7 @@ #include "types/actiontype.h" class Vendor; +class Rule; class JsonTypes : public QObject { @@ -54,6 +55,7 @@ public: static ActionType *unpackActionType(const QVariantMap &actionTypeMap, QObject *parent); static Device *unpackDevice(const QVariantMap &deviceMap, QObject *parent); + static QVariantMap packRule(Rule* rule); private: static DeviceClass::SetupMethod stringToSetupMethod(const QString &setupMethodString); static QList stringListToBasicTags(const QStringList &basicTagsStringList); diff --git a/guh-control/main.cpp b/guh-control/main.cpp index e776a57a..1940d2b5 100644 --- a/guh-control/main.cpp +++ b/guh-control/main.cpp @@ -18,7 +18,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -#include +#include #include #include #include @@ -48,7 +48,7 @@ int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); - QCoreApplication application(argc, argv); + QGuiApplication application(argc, argv); application.setApplicationName("guh-control"); application.setOrganizationName("guh"); diff --git a/guh-control/resources.qrc b/guh-control/resources.qrc index bf861e17..6cc21e52 100644 --- a/guh-control/resources.qrc +++ b/guh-control/resources.qrc @@ -112,5 +112,8 @@ ui/magic/ComposeEventDescriptorPage.qml ui/images/view-expand.svg ui/images/view-collapse.svg + ui/magic/SelectRuleActionPage.qml + ui/magic/SelectRuleActionParamsPage.qml + ui/images/tick.svg diff --git a/guh-control/rulemanager.cpp b/guh-control/rulemanager.cpp index 962e531a..baef479c 100644 --- a/guh-control/rulemanager.cpp +++ b/guh-control/rulemanager.cpp @@ -1,6 +1,7 @@ #include "rulemanager.h" #include "jsonrpc/jsonrpcclient.h" +#include "jsonrpc/jsontypes.h" #include "types/rule.h" #include "types/eventdescriptor.h" #include "types/eventdescriptors.h" @@ -49,6 +50,12 @@ void RuleManager::addRule(const QVariantMap params) m_jsonClient->sendCommand("Rules.AddRule", params, this, "addRuleReply"); } +void RuleManager::addRule(Rule *rule) +{ + QVariantMap params = JsonTypes::packRule(rule); + m_jsonClient->sendCommand("Rules.AddRule", params, this, "addRuleReply"); +} + void RuleManager::removeRule(const QUuid &ruleId) { QVariantMap params; @@ -56,6 +63,13 @@ void RuleManager::removeRule(const QUuid &ruleId) m_jsonClient->sendCommand("Rules.RemoveRule", params, this, "removeRuleReply"); } +void RuleManager::editRule(Rule *rule) +{ + QVariantMap params = JsonTypes::packRule(rule); + m_jsonClient->sendCommand("Rules.EditRule", params, this, "editRuleReply"); + +} + void RuleManager::handleRulesNotification(const QVariantMap ¶ms) { qDebug() << "rules notification received" << params; @@ -124,6 +138,11 @@ void RuleManager::removeRuleReply(const QVariantMap ¶ms) qDebug() << "Have remove rule reply" << params; } +void RuleManager::editRuleReply(const QVariantMap ¶ms) +{ + qDebug() << "Edit rule reply:" << params; +} + void RuleManager::parseEventDescriptors(const QVariantList &eventDescriptorList, Rule *rule) { foreach (const QVariant &eventDescriptorVariant, eventDescriptorList) { @@ -156,9 +175,10 @@ StateEvaluator *RuleManager::parseStateEvaluator(const QVariantMap &stateEvaluat op = StateDescriptor::ValueOperatorGreaterOrEqual; } StateDescriptor *sd = new StateDescriptor(sdMap.value("deviceId").toUuid(), op, sdMap.value("stateTypeId").toUuid(), sdMap.value("value"), stateEvaluator); -// stateEvaluator-> + stateEvaluator->setStateDescriptor(sd); } + return stateEvaluator; } void RuleManager::parseRuleActions(const QVariantList &ruleActions, Rule *rule) diff --git a/guh-control/rulemanager.h b/guh-control/rulemanager.h index 183c99e5..fa2369b4 100644 --- a/guh-control/rulemanager.h +++ b/guh-control/rulemanager.h @@ -27,7 +27,9 @@ public: Q_INVOKABLE Rule* createNewRule(); Q_INVOKABLE void addRule(const QVariantMap params); + Q_INVOKABLE void addRule(Rule *rule); Q_INVOKABLE void removeRule(const QUuid &ruleId); + Q_INVOKABLE void editRule(Rule *rule); private slots: void handleRulesNotification(const QVariantMap ¶ms); @@ -35,6 +37,7 @@ private slots: void getRuleDetailsReply(const QVariantMap ¶ms); void addRuleReply(const QVariantMap ¶ms); void removeRuleReply(const QVariantMap ¶ms); + void editRuleReply(const QVariantMap ¶ms); private: void parseEventDescriptors(const QVariantList &eventDescriptorList, Rule *rule); diff --git a/guh-control/ui/MagicPage.qml b/guh-control/ui/MagicPage.qml index 3fdfefb4..a0527c02 100644 --- a/guh-control/ui/MagicPage.qml +++ b/guh-control/ui/MagicPage.qml @@ -11,7 +11,12 @@ Page { HeaderButton { imageSource: Qt.resolvedUrl("images/add.svg") - onClicked: pageStack.push(Qt.resolvedUrl("magic/NewRulePage.qml"), {rule: Engine.ruleManager.createNewRule() }) + onClicked: { + var newRulePage = pageStack.push(Qt.resolvedUrl("magic/EditRulePage.qml"), {rule: Engine.ruleManager.createNewRule() }); + newRulePage.onAccept.connect(function() { + Engine.ruleManager.addRule(newRulePage.rule); + }) + } } } @@ -19,15 +24,37 @@ Page { anchors.fill: parent model: Engine.ruleManager.rules - delegate: ItemDelegate { + delegate: SwipeDelegate { width: parent.width - Label { - text: model.name - } + text: model.name onClicked: { - pageStack.push(Qt.resolvedUrl("magic/EditRulePage.qml"), {rule: Engine.ruleManager.rules.get(index) }) + var editRulePage = pageStack.push(Qt.resolvedUrl("magic/EditRulePage.qml"), {rule: Engine.ruleManager.rules.get(index) }) + editRulePage.onAccept.connect(function() { + Engine.ruleManager.editRule(editRulePage.rule); + }) } + +// swipe.right: ColorIcon { +// name: "delete.svg" +// color: "red" +// } + + swipe.right: Label { + id: deleteLabel + text: qsTr("Delete") + color: "white" + verticalAlignment: Label.AlignVCenter + padding: 12 + height: parent.height + anchors.right: parent.right + + SwipeDelegate.onClicked: Engine.ruleManager.removeRule(model.id) + + background: Rectangle { + color: deleteLabel.SwipeDelegate.pressed ? Qt.darker("tomato", 1.1) : "tomato" + } + } } } } diff --git a/guh-control/ui/images/tick.svg b/guh-control/ui/images/tick.svg new file mode 100644 index 00000000..4b6f9ad8 --- /dev/null +++ b/guh-control/ui/images/tick.svg @@ -0,0 +1,17 @@ + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/guh-control/ui/magic/EditRulePage.qml b/guh-control/ui/magic/EditRulePage.qml index 89b051cc..c7ba0eb7 100644 --- a/guh-control/ui/magic/EditRulePage.qml +++ b/guh-control/ui/magic/EditRulePage.qml @@ -1,36 +1,167 @@ -import QtQuick 2.7 -import QtQuick.Controls 2.2 +import QtQuick 2.8 +import QtQuick.Layouts 1.3 +import QtQuick.Controls 2.1 import "../components" -import QtQuick.Layouts 1.2 import Guh 1.0 Page { + id: root + property var rule: null + signal accept(); + + function addEventDescriptor() { + var eventDescriptor = root.rule.eventDescriptors.createNewEventDescriptor(); + var page = pageStack.push(Qt.resolvedUrl("SelectThingPage.qml")); + page.onBackPressed.connect(function() { pageStack.pop(); }); + page.onThingSelected.connect(function(device) { + eventDescriptor.deviceId = device.id; + selectEventDescriptorData(eventDescriptor) + }) + page.onInterfaceSelected.connect(function(interfaceName) { + eventDescriptor.interfaceName = interfaceName; + selectEventDescriptorData(eventDescriptor) + }) + } + + function selectEventDescriptorData(eventDescriptor) { + var eventPage = pageStack.push(Qt.resolvedUrl("SelectEventPage.qml"), {text: "Select event", eventDescriptor: eventDescriptor}); + eventPage.onBackPressed.connect(function() {pageStack.pop()}) + eventPage.onDone.connect(function() { + root.rule.eventDescriptors.addEventDescriptor(eventPage.eventDescriptor); + pageStack.pop(root) + }) + } + + function addRuleAction() { + var ruleAction = root.rule.ruleActions.createNewRuleAction(); + var page = pageStack.push(Qt.resolvedUrl("SelectThingPage.qml")); + page.onBackPressed.connect(function() { pageStack.pop() }) + page.onThingSelected.connect(function(device) { + ruleAction.deviceId = device.id; + selectRuleActionData(ruleAction) + }) + page.onInterfaceSelected.connect(function(interfaceName) { + ruleAction.interfaceName = interfaceName; + selectRuleActionData(ruleAction) + }) + } + function selectRuleActionData(ruleAction) { + var ruleActionPage = pageStack.push(Qt.resolvedUrl("SelectRuleActionPage.qml"), {text: "Select action", ruleAction: ruleAction }); + ruleActionPage.onBackPressed.connect(function() { + ruleAction.destroy(); + pageStack.pop(root); + }) + ruleActionPage.onDone.connect(function() { + root.rule.ruleActions.addRuleAction(ruleAction) + pageStack.pop(root); + }) + } + header: GuhHeader { - text: "Add some magic" + text: "New rule" onBackPressed: pageStack.pop() + HeaderButton { + imageSource: "../images/tick.svg" + onClicked: { + root.accept() + } + } } ColumnLayout { anchors.fill: parent Label { - text: "When" + text: "Rule name" + } + TextField { + Layout.fillWidth: true + text: root.rule.name + onTextChanged: { + root.rule.name = text; + + } + } + + RowLayout { + Layout.fillWidth: true + RadioButton { + id: whenButton + text: "When" + checked: true + } + RadioButton { + id: whileButton + text: "While" + } + } + + RowLayout { + Layout.fillWidth: true + visible: eventsRepeater.count == 0 + Label { + Layout.fillWidth: true + text: "Add an event which should trigger the execution of the rule" + } + Button { + text: "+" + onClicked: root.addEventDescriptor(); + } } Repeater { - model: rule.eventDescriptors - ItemDelegate { - property var device: Engine.deviceManager.devices.getDevice(model.deviceId) + id: eventsRepeater + model: root.rule.eventDescriptors + delegate: ItemDelegate { + id: eventDelegate + property var device: Engine.deviceManager.devices.getDevice(root.rule.eventDescriptors.get(index).deviceId) property var deviceClass: device ? Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId) : null - property var eventType: deviceClass ? deviceClass.eventTypes.getEventType(model.eventTypeId) : null + property var eventType: deviceClass ? deviceClass.eventTypes.getEventType(root.rule.eventDescriptors.get(index).eventTypeId) : null contentItem: ColumnLayout { Label { - text: device ? device.name : "Unknown device" + text: eventDelegate.device ? eventDelegate.device.name : "Unknown device" + root.rule.eventDescriptors.get(index).deviceId Layout.fillWidth: true } Label { - text: eventType ? eventType.name : "Unknown event" + text: eventDelegate.eventType ? eventDelegate.eventType.displayName : "Unknown event" + root.rule.eventDescriptors.get(index).eventTypeId + } + } + } + } + + Label { + text: "do the following:" + root.rule.ruleActions.count + } + + RowLayout { + Layout.fillWidth: true + visible: actionsRepeater.count == 0 + Label { + Layout.fillWidth: true + text: "Add action which should be executed when the rule is triggered" + wrapMode: Text.WordWrap + } + Button { + text: "+" + onClicked: root.addRuleAction(); + } + } + + Repeater { + id: actionsRepeater + model: root.rule.ruleActions + delegate: ItemDelegate { + id: actionDelegate + property var device: Engine.deviceManager.devices.getDevice(root.rule.ruleActions.get(index).deviceId) + property var deviceClass: device ? Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId) : null + property var actionType: deviceClass ? deviceClass.actionTypes.getActionType(root.rule.ruleActions.get(index).actionTypeId) : null + contentItem: ColumnLayout { + Label { + text: actionDelegate.device.name + } + Label { + text: actionDelegate.actionType.displayName } } } diff --git a/guh-control/ui/magic/SelectRuleActionPage.qml b/guh-control/ui/magic/SelectRuleActionPage.qml new file mode 100644 index 00000000..7a4b1882 --- /dev/null +++ b/guh-control/ui/magic/SelectRuleActionPage.qml @@ -0,0 +1,122 @@ +import QtQuick 2.4 +import QtQuick.Controls 2.1 +import "../components" +import Guh 1.0 + +Page { + id: root + property alias text: header.text + + // a ruleAction object needs to be set and prefilled with either deviceId or interfaceName + property var ruleAction: null + + readonly property var device: ruleAction && ruleAction.deviceId ? Engine.deviceManager.devices.getDevice(ruleAction.deviceId) : null + readonly property var deviceClass: device ? Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId) : null + + signal backPressed(); + signal done(); + + onRuleActionChanged: buildInterface() + Component.onCompleted: buildInterface() + + header: GuhHeader { + id: header + onBackPressed: root.backPressed(); + + property bool interfacesMode: true + onInterfacesModeChanged: root.buildInterface() + + HeaderButton { + imageSource: header.interfacesMode ? "../images/view-expand.svg" : "../images/view-collapse.svg" + onClicked: header.interfacesMode = !header.interfacesMode + } + } + + ListModel { + id: actionTemplateModel + ListElement { interfaceName: "light"; text: "Switch light"; identifier: "switchLight"} + ListElement { interfaceName: "dimmablelight"; text: "Dim light"; identifier: "dimLight"} + ListElement { interfaceName: "colorlight"; text: "Set light color"; identifier: "colorLight" } + ListElement { interfaceName: "mediacontroller"; text: "Pause playback"; identifier: "pausePlayback" } + ListElement { interfaceName: "mediacontroller"; text: "Resume playback"; identifier: "resumePlayback" } + ListElement { interfaceName: "extendedvolumecontroller"; text: "Set volume"; identifier: "setVolume" } + ListElement { interfaceName: "extendedvolumecontroller"; text: "Mute"; identifier: "mute" } + ListElement { interfaceName: "extendedvolumecontroller"; text: "Unmute"; identifier: "unmute" } + ListElement { interfaceName: "notifications"; text: "Notify me"; identifier: "notify" } + } + + function buildInterface() { + actualModel.clear() + + if (header.interfacesMode) { + if (root.device) { + print("device supports interfaces", deviceClass.interfaces) + for (var i = 0; i < actionTemplateModel.count; i++) { + print("action is for interface", actionTemplateModel.get(i).interfaceName) + if (deviceClass.interfaces.indexOf(actionTemplateModel.get(i).interfaceName) >= 0) { + actualModel.append(actionTemplateModel.get(i)) + } + } + } else if (root.ruleAction.interfaceName !== "") { + for (var i = 0; i < actionTemplateModel.count; i++) { + if (actionTemplateModel.get(i).interfaceName === root.ruleAction.interfaceName) { + actualModel.append(actionTemplateModel.get(i)) + } + } + } else { + console.warn("You need to set device or interfaceName"); + } + } else { + if (root.device) { + print("fdsfasdfdsafdas", deviceClass.actionTypes.count) + for (var i = 0; i < deviceClass.actionTypes.count; i++) { + print("bla", deviceClass.actionTypes.get(i).name, deviceClass.actionTypes.get(i).displayName, deviceClass.actionTypes.get(i).id) + actualModel.append({text: deviceClass.actionTypes.get(i).displayName, actionTypeId: deviceClass.actionTypes.get(i).id}) + } + } + } + } + + ListModel { + id: actualModel + ListElement { text: ""; actionTypeId: "" } + } + + ListView { + anchors.fill: parent + model: actualModel + + delegate: ItemDelegate { + text: model.text + onClicked: { + if (header.interfacesMode) { + if (root.device) { + print("selected:", model.identifier) + switch (model.identfier) { + case "switchLight": + root.done(); + break; + default: + console.warn("FIXME: Unhandled interface action"); + } + } + } else { + if (root.device) { + var actionType = root.deviceClass.actionTypes.getActionType(model.actionTypeId); + console.log("ActionType", actionType.id, "selected. Has", actionType.paramTypes.count, "params"); + root.ruleAction.actionTypeId = actionType.id; + if (actionType.paramTypes.count > 0) { + var paramsPage = pageStack.push(Qt.resolvedUrl("SelectRuleActionParamsPage.qml"), {ruleAction: root.ruleAction}) + paramsPage.onCompleted.connect(function() { + pageStack.pop(); + root.done(); + }) + } else { + root.done(); + } + } + } + } + } + } +} diff --git a/guh-control/ui/magic/SelectRuleActionParamsPage.qml b/guh-control/ui/magic/SelectRuleActionParamsPage.qml new file mode 100644 index 00000000..43531505 --- /dev/null +++ b/guh-control/ui/magic/SelectRuleActionParamsPage.qml @@ -0,0 +1,53 @@ +import QtQuick 2.8 +import QtQuick.Controls 2.1 +import QtQuick.Layouts 1.2 +import "../components" +import "../paramdelegates" +import Guh 1.0 + +Page { + id: root + // Needs to be set and filled in with deviceId and actionTypeId + property var ruleAction + + readonly property var device: ruleAction && ruleAction.deviceId ? Engine.deviceManager.devices.getDevice(ruleAction.deviceId) : null + readonly property var actionType: device ? Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId).actionTypes.getActionType(ruleAction.actionTypeId) : null + + signal backPressed(); + signal completed(); + + header: GuhHeader { + text: "params" + onBackPressed: root.backPressed(); + } + + ColumnLayout { + anchors.fill: parent + Repeater { + id: delegateRepeater + model: root.actionType.paramTypes + delegate: ParamDelegate { + paramType: root.actionType.paramTypes.get(index) + value: paramType.defaultValue + + } + } + Item { + Layout.fillWidth: true + Layout.fillHeight: true + } + Button { + text: "OK" + Layout.fillWidth: true + Layout.margins: app.margins + onClicked: { + var params = []; + for (var i = 0; i < delegateRepeater.count; i++) { + var paramDelegate = delegateRepeater.itemAt(i); + root.ruleAction.ruleActionParams.setRuleActionParam(paramDelegate.paramType.id, paramDelegate.value) + } + root.completed() + } + } + } +} diff --git a/guh-control/ui/paramdelegates/ParamDelegate.qml b/guh-control/ui/paramdelegates/ParamDelegate.qml index c142aa39..e6277dc5 100644 --- a/guh-control/ui/paramdelegates/ParamDelegate.qml +++ b/guh-control/ui/paramdelegates/ParamDelegate.qml @@ -10,6 +10,7 @@ Loader { var comp; switch (loader.paramType.type) { case "bool": + case "Bool": comp = "Bool"; break; case "String": diff --git a/libguh-common/types/actiontype.cpp b/libguh-common/types/actiontype.cpp index 805f4363..dc6d1973 100644 --- a/libguh-common/types/actiontype.cpp +++ b/libguh-common/types/actiontype.cpp @@ -27,12 +27,12 @@ ActionType::ActionType(QObject *parent) : { } -QUuid ActionType::id() const +QString ActionType::id() const { return m_id; } -void ActionType::setId(const QUuid &id) +void ActionType::setId(const QString &id) { m_id = id; } diff --git a/libguh-common/types/actiontype.h b/libguh-common/types/actiontype.h index b53c4123..e1cc7e05 100644 --- a/libguh-common/types/actiontype.h +++ b/libguh-common/types/actiontype.h @@ -31,7 +31,7 @@ class ActionType : public QObject { Q_OBJECT - Q_PROPERTY(QUuid id READ id CONSTANT) + Q_PROPERTY(QString id READ id CONSTANT) Q_PROPERTY(QString name READ name CONSTANT) Q_PROPERTY(QString displayName READ displayName CONSTANT) Q_PROPERTY(int index READ index CONSTANT) @@ -40,8 +40,8 @@ class ActionType : public QObject public: explicit ActionType(QObject *parent = 0); - QUuid id() const; - void setId(const QUuid &id); + QString id() const; + void setId(const QString &id); QString name() const; void setName(const QString &name); @@ -56,7 +56,7 @@ public: void setParamTypes(ParamTypes *paramTypes); private: - QUuid m_id; + QString m_id; QString m_name; QString m_displayName; int m_index; diff --git a/libguh-common/types/actiontypes.cpp b/libguh-common/types/actiontypes.cpp index b8388113..bb62b387 100644 --- a/libguh-common/types/actiontypes.cpp +++ b/libguh-common/types/actiontypes.cpp @@ -33,17 +33,12 @@ QList ActionTypes::actionTypes() return m_actionTypes; } -int ActionTypes::count() const -{ - return m_actionTypes.count(); -} - ActionType *ActionTypes::get(int index) const { return m_actionTypes.at(index); } -ActionType *ActionTypes::getActionType(const QUuid &actionTypeId) const +ActionType *ActionTypes::getActionType(const QString &actionTypeId) const { foreach (ActionType *actionType, m_actionTypes) { if (actionType->id() == actionTypeId) { @@ -68,7 +63,7 @@ QVariant ActionTypes::data(const QModelIndex &index, int role) const if (role == NameRole) { return actionType->name(); } else if (role == IdRole) { - return actionType->id().toString(); + return actionType->id(); } return QVariant(); } @@ -79,6 +74,7 @@ void ActionTypes::addActionType(ActionType *actionType) //qDebug() << "ActionTypes: loaded actionType" << actionType->name(); m_actionTypes.append(actionType); endInsertRows(); + emit countChanged(); } ActionType *ActionTypes::findByName(const QString &name) const @@ -96,6 +92,7 @@ void ActionTypes::clearModel() beginResetModel(); m_actionTypes.clear(); endResetModel(); + emit countChanged(); } QHash ActionTypes::roleNames() const diff --git a/libguh-common/types/actiontypes.h b/libguh-common/types/actiontypes.h index 884fda79..3c3a39ca 100644 --- a/libguh-common/types/actiontypes.h +++ b/libguh-common/types/actiontypes.h @@ -31,7 +31,7 @@ class ActionTypes : public QAbstractListModel { Q_OBJECT - + Q_PROPERTY(int count READ rowCount NOTIFY countChanged) public: enum ActionTypeRole { NameRole = Qt::DisplayRole, @@ -42,9 +42,8 @@ public: QList actionTypes(); - Q_INVOKABLE int count() const; Q_INVOKABLE ActionType *get(int index) const; - Q_INVOKABLE ActionType *getActionType(const QUuid &actionTypeId) const; + Q_INVOKABLE ActionType *getActionType(const QString &actionTypeId) const; int rowCount(const QModelIndex & parent = QModelIndex()) const; QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const; @@ -55,6 +54,9 @@ public: void clearModel(); +signals: + void countChanged(); + protected: QHash roleNames() const; diff --git a/libguh-common/types/deviceclass.cpp b/libguh-common/types/deviceclass.cpp index d1251a17..34473ec3 100644 --- a/libguh-common/types/deviceclass.cpp +++ b/libguh-common/types/deviceclass.cpp @@ -184,7 +184,7 @@ void DeviceClass::setActionTypes(ActionTypes *actionTypes) emit actionTypesChanged(); } -bool DeviceClass::hasActionType(const QUuid &actionTypeId) +bool DeviceClass::hasActionType(const QString &actionTypeId) { foreach (ActionType *actionType, m_actionTypes->actionTypes()) { if (actionType->id() == actionTypeId) { diff --git a/libguh-common/types/deviceclass.h b/libguh-common/types/deviceclass.h index c9a0a43a..716191ab 100644 --- a/libguh-common/types/deviceclass.h +++ b/libguh-common/types/deviceclass.h @@ -131,7 +131,7 @@ public: ActionTypes *actionTypes() const; void setActionTypes(ActionTypes *actionTypes); - Q_INVOKABLE bool hasActionType(const QUuid &actionTypeId); + Q_INVOKABLE bool hasActionType(const QString &actionTypeId); static QString basicTagToString(BasicTag basicTag); diff --git a/libguh-common/types/paramdescriptors.cpp b/libguh-common/types/paramdescriptors.cpp index 301519ac..5c60cf89 100644 --- a/libguh-common/types/paramdescriptors.cpp +++ b/libguh-common/types/paramdescriptors.cpp @@ -17,6 +17,11 @@ QVariant ParamDescriptors::data(const QModelIndex &index, int role) const return QVariant(); } +ParamDescriptor *ParamDescriptors::get(int index) const +{ + return m_list.at(index); +} + ParamDescriptor *ParamDescriptors::createNewParamDescriptor() const { return new ParamDescriptor(); diff --git a/libguh-common/types/paramdescriptors.h b/libguh-common/types/paramdescriptors.h index 5ccb70df..ec063ea5 100644 --- a/libguh-common/types/paramdescriptors.h +++ b/libguh-common/types/paramdescriptors.h @@ -25,6 +25,8 @@ public: int rowCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role) const override; + ParamDescriptor* get(int index) const; + ParamDescriptor* createNewParamDescriptor() const; void addParamDescriptor(ParamDescriptor* paramDescriptor); diff --git a/libguh-common/types/rule.h b/libguh-common/types/rule.h index 9dfacebc..86d1034d 100644 --- a/libguh-common/types/rule.h +++ b/libguh-common/types/rule.h @@ -12,7 +12,7 @@ class Rule : public QObject { Q_OBJECT Q_PROPERTY(QUuid id READ id CONSTANT) - Q_PROPERTY(QString name READ name NOTIFY nameChanged) + Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) Q_PROPERTY(bool enabled READ enabled NOTIFY enabledChanged) Q_PROPERTY(EventDescriptors* eventDescriptors READ eventDescriptors CONSTANT) Q_PROPERTY(StateEvaluator* stateEvaluator READ stateEvaluator CONSTANT) diff --git a/libguh-common/types/ruleaction.h b/libguh-common/types/ruleaction.h index 7a9c0656..31e44471 100644 --- a/libguh-common/types/ruleaction.h +++ b/libguh-common/types/ruleaction.h @@ -9,8 +9,8 @@ class RuleActionParams; class RuleAction : public QObject { Q_OBJECT - Q_PROPERTY(QUuid deviceId READ deviceId NOTIFY deviceIdChanged) - Q_PROPERTY(QUuid actionTypeId READ actionTypeId NOTIFY actionTypeIdChanged) + Q_PROPERTY(QUuid deviceId READ deviceId WRITE setDeviceId NOTIFY deviceIdChanged) + Q_PROPERTY(QUuid actionTypeId READ actionTypeId WRITE setActionTypeId NOTIFY actionTypeIdChanged) Q_PROPERTY(RuleActionParams* ruleActionParams READ ruleActionParams CONSTANT) public: diff --git a/libguh-common/types/ruleactionparams.cpp b/libguh-common/types/ruleactionparams.cpp index ff8df1e0..8fba61ff 100644 --- a/libguh-common/types/ruleactionparams.cpp +++ b/libguh-common/types/ruleactionparams.cpp @@ -26,6 +26,22 @@ void RuleActionParams::addRuleActionParam(RuleActionParam *ruleActionParam) endInsertRows(); } +void RuleActionParams::setRuleActionParam(const QString ¶mTypeId, const QVariant &value) +{ + foreach (RuleActionParam *rap, m_list) { + if (rap->paramTypeId() == paramTypeId) { + rap->setValue(value); + return; + } + } + + // Still here? Need to add it + RuleActionParam *rap = new RuleActionParam(this); + rap->setParamTypeId(paramTypeId); + rap->setValue(value); + addRuleActionParam(rap); +} + RuleActionParam *RuleActionParams::get(int index) const { return m_list.at(index); diff --git a/libguh-common/types/ruleactionparams.h b/libguh-common/types/ruleactionparams.h index ed2ea198..79fb5db4 100644 --- a/libguh-common/types/ruleactionparams.h +++ b/libguh-common/types/ruleactionparams.h @@ -17,6 +17,7 @@ public: void addRuleActionParam(RuleActionParam* ruleActionParam); + Q_INVOKABLE void setRuleActionParam(const QString ¶mTypeId, const QVariant &value); Q_INVOKABLE RuleActionParam* get(int index) const; signals: diff --git a/libguh-common/types/ruleactions.cpp b/libguh-common/types/ruleactions.cpp index e3c32182..54c18e84 100644 --- a/libguh-common/types/ruleactions.cpp +++ b/libguh-common/types/ruleactions.cpp @@ -28,3 +28,8 @@ RuleAction *RuleActions::get(int index) const { return m_list.at(index); } + +RuleAction *RuleActions::createNewRuleAction() const +{ + return new RuleAction(); +} diff --git a/libguh-common/types/ruleactions.h b/libguh-common/types/ruleactions.h index 4ac49f06..d6d7dda1 100644 --- a/libguh-common/types/ruleactions.h +++ b/libguh-common/types/ruleactions.h @@ -15,9 +15,10 @@ public: int rowCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role) const override; - void addRuleAction(RuleAction* ruleAction); + Q_INVOKABLE void addRuleAction(RuleAction* ruleAction); Q_INVOKABLE RuleAction* get(int index) const; + Q_INVOKABLE RuleAction* createNewRuleAction() const; signals: void countChanged(); diff --git a/libguh-common/types/rules.cpp b/libguh-common/types/rules.cpp index c270e00f..75f291d7 100644 --- a/libguh-common/types/rules.cpp +++ b/libguh-common/types/rules.cpp @@ -23,6 +23,8 @@ QVariant Rules::data(const QModelIndex &index, int role) const switch (role) { case RoleName: return m_list.at(index.row())->name(); + case RoleId: + return m_list.at(index.row())->id(); } return QVariant(); } @@ -31,6 +33,7 @@ QHash Rules::roleNames() const { QHash roles; roles.insert(RoleName, "name"); + roles.insert(RoleId, "id"); return roles; } diff --git a/libguh-common/types/rules.h b/libguh-common/types/rules.h index bbb54395..98d58f7b 100644 --- a/libguh-common/types/rules.h +++ b/libguh-common/types/rules.h @@ -10,7 +10,8 @@ class Rules : public QAbstractListModel Q_OBJECT public: enum Roles { - RoleName + RoleName, + RoleId }; explicit Rules(QObject *parent = nullptr);