mroe work on rules

This commit is contained in:
Michael Zanetti 2018-02-19 18:05:54 +01:00
parent 0592ee6133
commit 46ab4656b4
38 changed files with 612 additions and 123 deletions

View File

@ -157,7 +157,7 @@ StateType *JsonTypes::unpackStateType(const QVariantMap &stateTypeMap, QObject *
EventType *JsonTypes::unpackEventType(const QVariantMap &eventTypeMap, QObject *parent) EventType *JsonTypes::unpackEventType(const QVariantMap &eventTypeMap, QObject *parent)
{ {
EventType *eventType = new EventType(parent); EventType *eventType = new EventType(parent);
eventType->setId(eventTypeMap.value("id").toUuid()); eventType->setId(eventTypeMap.value("id").toString());
eventType->setName(eventTypeMap.value("name").toString()); eventType->setName(eventTypeMap.value("name").toString());
eventType->setDisplayName(eventTypeMap.value("displayName").toString()); eventType->setDisplayName(eventTypeMap.value("displayName").toString());
eventType->setIndex(eventTypeMap.value("index").toInt()); eventType->setIndex(eventTypeMap.value("index").toInt());
@ -217,7 +217,9 @@ Device *JsonTypes::unpackDevice(const QVariantMap &deviceMap, QObject *parent)
QVariantMap JsonTypes::packRule(Rule *rule) QVariantMap JsonTypes::packRule(Rule *rule)
{ {
QVariantMap ret; QVariantMap ret;
ret.insert("ruleId", rule->id()); if (!rule->id().isNull()) {
ret.insert("ruleId", rule->id());
}
ret.insert("name", rule->name()); ret.insert("name", rule->name());
ret.insert("enabled", true); ret.insert("enabled", true);
@ -254,6 +256,8 @@ QVariantMap JsonTypes::packRule(Rule *rule)
QVariantMap paramDescriptor; QVariantMap paramDescriptor;
paramDescriptor.insert("paramTypeId", rule->eventDescriptors()->get(i)->paramDescriptors()->get(j)->id()); paramDescriptor.insert("paramTypeId", rule->eventDescriptors()->get(i)->paramDescriptors()->get(j)->id());
paramDescriptor.insert("value", rule->eventDescriptors()->get(i)->paramDescriptors()->get(j)->value()); paramDescriptor.insert("value", rule->eventDescriptors()->get(i)->paramDescriptors()->get(j)->value());
QMetaEnum operatorEnum = QMetaEnum::fromType<ParamDescriptor::ValueOperator>();
paramDescriptor.insert("operator", operatorEnum.valueToKey(rule->eventDescriptors()->get(i)->paramDescriptors()->get(j)->operatorType()));
paramDescriptors.append(paramDescriptor); paramDescriptors.append(paramDescriptor);
} }
eventDescriptor.insert("paramDescriptors", paramDescriptors); eventDescriptor.insert("paramDescriptors", paramDescriptors);

View File

@ -105,7 +105,6 @@
<file>ui/EditDevicesPage.qml</file> <file>ui/EditDevicesPage.qml</file>
<file>ui/devicepages/ConfigureThingPage.qml</file> <file>ui/devicepages/ConfigureThingPage.qml</file>
<file>ui/magic/DeviceRulesPage.qml</file> <file>ui/magic/DeviceRulesPage.qml</file>
<file>ui/magic/SelectEventPage.qml</file>
<file>ui/magic/NewThingMagicPage.qml</file> <file>ui/magic/NewThingMagicPage.qml</file>
<file>ui/magic/EditRulePage.qml</file> <file>ui/magic/EditRulePage.qml</file>
<file>ui/magic/SelectThingPage.qml</file> <file>ui/magic/SelectThingPage.qml</file>
@ -115,5 +114,9 @@
<file>ui/magic/SelectRuleActionPage.qml</file> <file>ui/magic/SelectRuleActionPage.qml</file>
<file>ui/magic/SelectRuleActionParamsPage.qml</file> <file>ui/magic/SelectRuleActionParamsPage.qml</file>
<file>ui/images/tick.svg</file> <file>ui/images/tick.svg</file>
<file>ui/magic/SelectEventDescriptorParamsPage.qml</file>
<file>ui/magic/SelectEventDescriptorPage.qml</file>
<file>ui/paramdelegates/DoubleParamDelegate.qml</file>
<file>ui/paramdescriptordelegates/ParamDescriptorDelegateBase.qml</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@ -12,6 +12,8 @@
#include "types/stateevaluator.h" #include "types/stateevaluator.h"
#include "types/statedescriptor.h" #include "types/statedescriptor.h"
#include <QMetaEnum>
RuleManager::RuleManager(JsonRpcClient* jsonClient, QObject *parent) : RuleManager::RuleManager(JsonRpcClient* jsonClient, QObject *parent) :
JsonHandler(parent), JsonHandler(parent),
m_jsonClient(jsonClient), m_jsonClient(jsonClient),
@ -66,7 +68,7 @@ void RuleManager::removeRule(const QUuid &ruleId)
void RuleManager::editRule(Rule *rule) void RuleManager::editRule(Rule *rule)
{ {
QVariantMap params = JsonTypes::packRule(rule); QVariantMap params = JsonTypes::packRule(rule);
m_jsonClient->sendCommand("Rules.EditRule", params, this, "editRuleReply"); m_jsonClient->sendCommand("Rules.EditRule", params, this, "onEditRuleReply");
} }
@ -126,6 +128,7 @@ void RuleManager::getRuleDetailsReply(const QVariantMap &params)
// qDebug() << "got rule details for rule" << ruleMap; // qDebug() << "got rule details for rule" << ruleMap;
parseEventDescriptors(ruleMap.value("eventDescriptors").toList(), rule); parseEventDescriptors(ruleMap.value("eventDescriptors").toList(), rule);
parseRuleActions(ruleMap.value("actions").toList(), rule); parseRuleActions(ruleMap.value("actions").toList(), rule);
parseStateEvaluator(ruleMap.value("stateEvaluator").toMap());
} }
void RuleManager::addRuleReply(const QVariantMap &params) void RuleManager::addRuleReply(const QVariantMap &params)
@ -138,9 +141,10 @@ void RuleManager::removeRuleReply(const QVariantMap &params)
qDebug() << "Have remove rule reply" << params; qDebug() << "Have remove rule reply" << params;
} }
void RuleManager::editRuleReply(const QVariantMap &params) void RuleManager::onEditRuleReply(const QVariantMap &params)
{ {
qDebug() << "Edit rule reply:" << params; qDebug() << "Edit rule reply:" << params.value("params").toMap();
emit editRuleReply(params.value("params").toMap().value("ruleError").toString());
} }
void RuleManager::parseEventDescriptors(const QVariantList &eventDescriptorList, Rule *rule) void RuleManager::parseEventDescriptors(const QVariantList &eventDescriptorList, Rule *rule)
@ -149,7 +153,12 @@ void RuleManager::parseEventDescriptors(const QVariantList &eventDescriptorList,
EventDescriptor *eventDescriptor = new EventDescriptor(rule); EventDescriptor *eventDescriptor = new EventDescriptor(rule);
eventDescriptor->setDeviceId(eventDescriptorVariant.toMap().value("deviceId").toUuid()); eventDescriptor->setDeviceId(eventDescriptorVariant.toMap().value("deviceId").toUuid());
eventDescriptor->setEventTypeId(eventDescriptorVariant.toMap().value("eventTypeId").toUuid()); eventDescriptor->setEventTypeId(eventDescriptorVariant.toMap().value("eventTypeId").toUuid());
// eventDescriptor->setParamDescriptors(eventDescriptorVariant.toMap().value("deviceId").toUuid()); foreach (const QVariant &paramDescriptorVariant, eventDescriptorVariant.toMap().value("paramDescriptors").toList()) {
ParamDescriptor *paramDescriptor = new ParamDescriptor(paramDescriptorVariant.toMap().value("paramTypeId").toString(), paramDescriptorVariant.toMap().value("value"));
QMetaEnum operatorEnum = QMetaEnum::fromType<ParamDescriptor::ValueOperator>();
paramDescriptor->setOperatorType((ParamDescriptor::ValueOperator)operatorEnum.keyToValue(paramDescriptorVariant.toMap().value("operator").toString().toLocal8Bit()));
eventDescriptor->paramDescriptors()->addParamDescriptor(paramDescriptor);
}
rule->eventDescriptors()->addEventDescriptor(eventDescriptor); rule->eventDescriptors()->addEventDescriptor(eventDescriptor);
} }
} }

View File

@ -37,13 +37,16 @@ private slots:
void getRuleDetailsReply(const QVariantMap &params); void getRuleDetailsReply(const QVariantMap &params);
void addRuleReply(const QVariantMap &params); void addRuleReply(const QVariantMap &params);
void removeRuleReply(const QVariantMap &params); void removeRuleReply(const QVariantMap &params);
void editRuleReply(const QVariantMap &params); void onEditRuleReply(const QVariantMap &params);
private: private:
void parseEventDescriptors(const QVariantList &eventDescriptorList, Rule *rule); void parseEventDescriptors(const QVariantList &eventDescriptorList, Rule *rule);
StateEvaluator* parseStateEvaluator(const QVariantMap &stateEvaluatorMap); StateEvaluator* parseStateEvaluator(const QVariantMap &stateEvaluatorMap);
void parseRuleActions(const QVariantList &ruleActions, Rule *rule); void parseRuleActions(const QVariantList &ruleActions, Rule *rule);
signals:
void editRuleReply(const QString &ruleError);
private: private:
JsonRpcClient *m_jsonClient; JsonRpcClient *m_jsonClient;
Rules* m_rules; Rules* m_rules;

View File

@ -20,11 +20,21 @@ Page {
} }
} }
Connections {
target: Engine.ruleManager
onEditRuleReply: {
if (ruleError == "RuleErrorNoError") {
pageStack.pop();
}
}
}
ListView { ListView {
anchors.fill: parent anchors.fill: parent
model: Engine.ruleManager.rules model: Engine.ruleManager.rules
delegate: SwipeDelegate { delegate: SwipeDelegate {
id: ruleDelegate
width: parent.width width: parent.width
text: model.name text: model.name
@ -35,26 +45,18 @@ Page {
}) })
} }
// swipe.right: ColorIcon { swipe.right: Item {
// name: "delete.svg" height: ruleDelegate.height
// color: "red" width: height
// } anchors.right: parent.right
ColorIcon {
swipe.right: Label { anchors.fill: parent
id: deleteLabel anchors.margins: app.margins
text: qsTr("Delete") name: "../images/delete.svg"
color: "white" color: "red"
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"
}
} }
SwipeDelegate.onClicked: Engine.ruleManager.removeRule(model.id)
}
} }
} }
} }

View File

@ -68,6 +68,32 @@ Page {
height: parent.view.height height: parent.view.height
shownInterfaces: ["gateway", "button", "notifications"] shownInterfaces: ["gateway", "button", "notifications"]
} }
ListView {
width: parent.view.width
height: parent.view.height
model: Engine.deviceManager.devices
delegate: ItemDelegate {
width: parent.width
contentItem: RowLayout {
spacing: app.margins
ColorIcon {
height: app.iconSize
width: height
name: app.interfaceToIcon(model.interfaces[0])
color: app.guhAccent
}
Label {
Layout.fillWidth: true
text: model.name
}
}
onClicked: {
pageStack.push(Qt.resolvedUrl("devicepages/GenericDevicePage.qml"), {device: Engine.deviceManager.devices.get(index)})
}
}
}
} }
PageIndicator { PageIndicator {

View File

@ -11,6 +11,8 @@ Page {
signal accept(); signal accept();
onAccept: busyOverlay.opacity = 1
function addEventDescriptor() { function addEventDescriptor() {
var eventDescriptor = root.rule.eventDescriptors.createNewEventDescriptor(); var eventDescriptor = root.rule.eventDescriptors.createNewEventDescriptor();
var page = pageStack.push(Qt.resolvedUrl("SelectThingPage.qml")); var page = pageStack.push(Qt.resolvedUrl("SelectThingPage.qml"));
@ -26,7 +28,7 @@ Page {
} }
function selectEventDescriptorData(eventDescriptor) { function selectEventDescriptorData(eventDescriptor) {
var eventPage = pageStack.push(Qt.resolvedUrl("SelectEventPage.qml"), {text: "Select event", eventDescriptor: eventDescriptor}); var eventPage = pageStack.push(Qt.resolvedUrl("SelectEventDescriptorPage.qml"), {text: "Select event", eventDescriptor: eventDescriptor});
eventPage.onBackPressed.connect(function() {pageStack.pop()}) eventPage.onBackPressed.connect(function() {pageStack.pop()})
eventPage.onDone.connect(function() { eventPage.onDone.connect(function() {
root.rule.eventDescriptors.addEventDescriptor(eventPage.eventDescriptor); root.rule.eventDescriptors.addEventDescriptor(eventPage.eventDescriptor);
@ -64,107 +66,193 @@ Page {
onBackPressed: pageStack.pop() onBackPressed: pageStack.pop()
HeaderButton { HeaderButton {
imageSource: "../images/tick.svg" imageSource: "../images/tick.svg"
enabled: actionsRepeater.count > 0 && root.rule.name.length > 0
opacity: enabled ? 1 : .3
onClicked: { onClicked: {
root.accept() root.accept()
} }
} }
} }
ColumnLayout { Flickable {
anchors.fill: parent anchors.fill: parent
Label { contentHeight: contentColumn.implicitHeight + app.margins
text: "Rule name"
}
TextField {
Layout.fillWidth: true
text: root.rule.name
onTextChanged: {
root.rule.name = text;
} ColumnLayout {
} id: contentColumn
anchors { left: parent.left; top: parent.top; right: parent.right; topMargin: app.margins }
RowLayout { ColumnLayout {
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 Layout.fillWidth: true
text: "Add an event which should trigger the execution of the rule" Layout.margins: app.margins
} Label {
Button { Layout.fillWidth: true
text: "+" text: "Rule name"
onClicked: root.addEventDescriptor(); }
} TextField {
} Layout.fillWidth: true
text: root.rule.name
onTextChanged: {
root.rule.name = text;
Repeater {
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(root.rule.eventDescriptors.get(index).eventTypeId) : null
contentItem: ColumnLayout {
Label {
text: eventDelegate.device ? eventDelegate.device.name : "Unknown device" + root.rule.eventDescriptors.get(index).deviceId
Layout.fillWidth: true
}
Label {
text: eventDelegate.eventType ? eventDelegate.eventType.displayName : "Unknown event" + root.rule.eventDescriptors.get(index).eventTypeId
} }
} }
} }
}
Label { ThinDivider {}
text: "do the following:" + root.rule.ruleActions.count
}
RowLayout {
Layout.fillWidth: true
visible: actionsRepeater.count == 0
Label { Label {
Layout.fillWidth: true Layout.fillWidth: true
text: "Add action which should be executed when the rule is triggered" Layout.margins: app.margins
wrapMode: Text.WordWrap font.pixelSize: app.mediumFont
text: "Events triggering this rule"
} }
Repeater {
id: eventsRepeater
model: root.rule.eventDescriptors
delegate: SwipeDelegate {
id: eventDelegate
Layout.fillWidth: true
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(root.rule.eventDescriptors.get(index).eventTypeId) : null
contentItem: ColumnLayout {
Label {
text: qsTr("%1 - %2").arg(eventDelegate.device.name).arg(eventDelegate.eventType.displayName)
Layout.fillWidth: true
elide: Text.ElideRight
}
RowLayout {
Layout.fillWidth: true
spacing: app.margins
Repeater {
model: root.rule.eventDescriptors.get(index).paramDescriptors
Label {
text: {
var ret = eventDelegate.eventType.paramTypes.getParamType(model.id).displayName
switch (model.operator) {
case ParamDescriptor.ValueOperatorEquals:
ret += " = ";
break;
case ParamDescriptor.ValueOperatorNotEquals:
ret += " != ";
break;
case ParamDescriptor.ValueOperatorGreater:
ret += " > ";
break;
case ParamDescriptor.ValueOperatorGreaterOrEqual:
ret += " >= ";
break;
case ParamDescriptor.ValueOperatorLess:
ret += " < ";
break;
case ParamDescriptor.ValueOperatorLessOrEqual:
ret += " <= ";
break;
default:
ret += " ? ";
}
ret += model.value
return ret;
}
}
}
}
}
swipe.right: Item {
height: eventDelegate.height
width: height
anchors.right: parent.right
ColorIcon {
anchors.fill: parent
anchors.margins: app.margins
name: "../images/delete.svg"
color: "red"
}
SwipeDelegate.onClicked: root.rule.eventDescriptors.removeEventDescriptor(index)
}
}
}
Button { Button {
text: "+" Layout.fillWidth: true
Layout.margins: app.margins
text: eventsRepeater.count == 0 ? "Add an event..." : "Add another event..."
onClicked: root.addEventDescriptor();
}
ThinDivider {}
Label {
text: "Actions to execute"
font.pixelSize: app.mediumFont
Layout.fillWidth: true
Layout.margins: app.margins
}
Repeater {
id: actionsRepeater
model: root.rule.ruleActions
delegate: SwipeDelegate {
id: actionDelegate
Layout.fillWidth: true
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 {
Layout.fillWidth: true
text: qsTr("%1 - %2").arg(actionDelegate.device.name).arg(actionDelegate.actionType.displayName)
}
RowLayout {
Layout.fillWidth: true
spacing: app.margins
Repeater {
model: root.rule.ruleActions.get(index).ruleActionParams
Label {
text: actionType.paramTypes.getParamType(model.paramTypeId).displayName + " -> " + model.value
font.pixelSize: app.smallFont
}
}
}
}
swipe.right: Item {
height: actionDelegate.height
width: height
anchors.right: parent.right
ColorIcon {
anchors.fill: parent
anchors.margins: app.margins
name: "../images/delete.svg"
color: "red"
}
SwipeDelegate.onClicked: root.rule.ruleActions.removeRuleAction(index)
}
}
}
Button {
Layout.fillWidth: true
Layout.margins: app.margins
text: actionsRepeater.count == 0 ? "Add an action..." : "Add another action..."
onClicked: root.addRuleAction(); onClicked: root.addRuleAction();
} }
} }
}
Repeater { Rectangle {
id: actionsRepeater id: busyOverlay
model: root.rule.ruleActions anchors.fill: parent
delegate: ItemDelegate { color: "#55000000"
id: actionDelegate opacity: 0
property var device: Engine.deviceManager.devices.getDevice(root.rule.ruleActions.get(index).deviceId) Behavior on opacity { NumberAnimation {duration: 200 } }
property var deviceClass: device ? Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId) : null BusyIndicator {
property var actionType: deviceClass ? deviceClass.actionTypes.getActionType(root.rule.ruleActions.get(index).actionTypeId) : null anchors.centerIn: parent
contentItem: ColumnLayout { running: parent.opacity > 0
Label {
text: actionDelegate.device.name
}
Label {
text: actionDelegate.actionType.displayName
}
}
}
} }
} }
} }

View File

@ -62,10 +62,8 @@ Page {
} }
} else { } else {
if (root.device) { if (root.device) {
print("fdsfasdfdsafdas", deviceClass.eventTypes.count)
for (var i = 0; i < deviceClass.eventTypes.count; i++) { for (var i = 0; i < deviceClass.eventTypes.count; i++) {
print("bla", deviceClass.eventTypes.get(i).name, deviceClass.eventTypes.get(i).displayName) actualModel.append({text: deviceClass.eventTypes.get(i).displayName, eventTypeId: deviceClass.eventTypes.get(i).id})
actualModel.append({text: deviceClass.eventTypes.get(i).displayName})
} }
} }
} }
@ -73,6 +71,7 @@ Page {
ListModel { ListModel {
id: actualModel id: actualModel
ListElement { text: ""; eventTypeId: "" }
} }
ListView { ListView {
@ -97,7 +96,24 @@ Page {
} }
} }
} else { } else {
console.warn("FIXME: not implemented yet") if (root.device) {
var eventType = root.deviceClass.eventTypes.getEventType(model.eventTypeId);
root.eventDescriptor.eventTypeId = model.eventTypeId;
if (eventType.paramTypes.count > 0) {
var paramsPage = pageStack.push(Qt.resolvedUrl("SelectEventDescriptorParamsPage.qml"), {eventDescriptor: root.eventDescriptor})
paramsPage.onBackPressed.connect(function() {pageStack.pop()});
paramsPage.onCompleted.connect(function() {
pageStack.pop();
root.done();
})
} else {
root.done();
}
print("have type", eventType.id)
} else {
console.warn("FIXME: not implemented yet");
}
} }
} }
} }

View File

@ -0,0 +1,53 @@
import QtQuick 2.8
import QtQuick.Controls 2.1
import QtQuick.Layouts 1.2
import "../components"
import "../paramdescriptordelegates"
import Guh 1.0
Page {
id: root
// Needs to be set and filled in with deviceId and eventTypeId
property var eventDescriptor: null
readonly property var device: eventDescriptor && eventDescriptor.deviceId ? Engine.deviceManager.devices.getDevice(eventDescriptor.deviceId) : null
readonly property var eventType: device ? Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId).eventTypes.getEventType(eventDescriptor.eventTypeId) : null
signal backPressed();
signal completed();
header: GuhHeader {
text: "params"
onBackPressed: root.backPressed();
}
ColumnLayout {
anchors.fill: parent
Repeater {
id: delegateRepeater
model: root.eventType.paramTypes
delegate: ParamDescriptorDelegateBase {
Layout.fillWidth: true
paramType: root.eventType.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.eventDescriptor.paramDescriptors.setParamDescriptor(paramDelegate.paramType.id, paramDelegate.value, paramDelegate.operatorType)
}
root.completed()
}
}
}
}

View File

@ -107,6 +107,7 @@ Page {
root.ruleAction.actionTypeId = actionType.id; root.ruleAction.actionTypeId = actionType.id;
if (actionType.paramTypes.count > 0) { if (actionType.paramTypes.count > 0) {
var paramsPage = pageStack.push(Qt.resolvedUrl("SelectRuleActionParamsPage.qml"), {ruleAction: root.ruleAction}) var paramsPage = pageStack.push(Qt.resolvedUrl("SelectRuleActionParamsPage.qml"), {ruleAction: root.ruleAction})
paramsPage.onBackPressed.connect(function() { pageStack.pop(); });
paramsPage.onCompleted.connect(function() { paramsPage.onCompleted.connect(function() {
pageStack.pop(); pageStack.pop();
root.done(); root.done();

View File

@ -0,0 +1,24 @@
import QtQuick 2.8
import QtQuick.Layouts 1.2
import QtQuick.Controls 2.1
ParamDelegateBase {
id: root
contentItem: RowLayout {
width: parent.width
Label {
id: label
text: root.paramType.name
}
TextField {
id: textField
Layout.fillWidth: true
text: root.value ? root.value : root.paramType.defaultValue
onTextChanged: {
root.value = text;
}
}
}
}

View File

@ -19,6 +19,9 @@ Loader {
case "Int": case "Int":
comp = "Int"; comp = "Int";
break; break;
case "Double":
comp = "Double";
break;
default: default:
print("unhandled param type:", paramType.type) print("unhandled param type:", paramType.type)
} }

View File

@ -0,0 +1,107 @@
import QtQuick 2.4
import QtQuick.Controls 2.1
import QtQuick.Layouts 1.2
import Guh 1.0
ItemDelegate {
id: root
property var paramType: null
property var value: null
property int operatorType: ParamDescriptors.ValueOperatorEquals
RowLayout {
anchors.fill: parent
anchors.margins: app.margins
spacing: app.margins
Label {
text: paramType.displayName
}
ComboBox {
model: {
switch (paramType.type) {
case "Bool":
case "String":
return ["is", "is not"];
case "Int":
case "Double":
return ["is", "is not", "is greater", "is smaller", "is greater or equal", "is smaller or equal"]
}
}
onCurrentTextChanged: {
switch (currentText) {
case "is":
root.operatorType = ParamDescriptor.ValueOperatorEquals;
break;
case "is not":
root.operatorType = ParamDescriptor.ValueOperatorNotEquals;
break;
case "is greater":
root.operatorType = ParamDescriptor.ValueOperatorGreater;
break;
case "is smaller":
root.operatorType = ParamDescriptor.ValueOperatorLess;
break;
case "is greater of equal":
root.operatorType = ParamDescriptor.ValueOperatorGreaterOrEqual;
break;
case "is smaller or equal":
root.operatorType = ParamDescriptor.ValueOperatorLessOrEqual;
break;
}
}
}
Loader {
id: placeHolder
Layout.fillWidth: true
sourceComponent: {
print("Datatye is:", paramType.type, paramType.minValue, paramType.maxValue)
switch (paramType.type) {
case "Bool":
return boolComponent;
case "Int":
case "Double":
if (paramType.minValue !== undefined && paramType.maxValue !== undefined) {
return sliderComponent;
}
return textFieldComponent;
}
console.warn("ParamDescriptorDelegate: Type delegate not implemented", paramType.type)
return null;
}
}
}
Component {
id: textFieldComponent
TextField {
text: ""
}
}
Component {
id: sliderComponent
Slider {
from: paramType.minValue
to: paramType.maxValue
onMoved: {
root.value = value;
}
}
}
Component {
id: boolComponent
ComboBox {
model: ListModel {
ListElement { modelData: "true"; value: true }
ListElement { modelData: "false"; value: false }
}
onCurrentIndexChanged: {
root.value = model.get(currentIndex).value
}
}
}
}

View File

@ -58,3 +58,16 @@ ParamDescriptors *EventDescriptor::paramDescriptors() const
{ {
return m_paramDescriptors; return m_paramDescriptors;
} }
EventDescriptor *EventDescriptor::clone() const
{
EventDescriptor *ret = new EventDescriptor();
ret->setDeviceId(this->deviceId());
ret->setEventTypeId(this->eventTypeId());
ret->setInterfaceName(this->interfaceName());
ret->setInterfaceEvent(this->interfaceEvent());
for (int i = 0; i < this->paramDescriptors()->rowCount(); i++) {
ret->paramDescriptors()->addParamDescriptor(this->paramDescriptors()->get(i)->clone());
}
return ret;
}

View File

@ -34,6 +34,8 @@ public:
ParamDescriptors* paramDescriptors() const; ParamDescriptors* paramDescriptors() const;
EventDescriptor* clone() const;
signals: signals:
void deviceIdChanged(); void deviceIdChanged();
void eventTypeIdChanged(); void eventTypeIdChanged();

View File

@ -34,7 +34,10 @@ QHash<int, QByteArray> EventDescriptors::roleNames() const
EventDescriptor *EventDescriptors::get(int index) const EventDescriptor *EventDescriptors::get(int index) const
{ {
return m_list.at(index); if (index >= 0 && index < m_list.count()) {
return m_list.at(index);
}
return nullptr;
} }
EventDescriptor *EventDescriptors::createNewEventDescriptor() EventDescriptor *EventDescriptors::createNewEventDescriptor()
@ -50,3 +53,11 @@ void EventDescriptors::addEventDescriptor(EventDescriptor *eventDescriptor)
endInsertRows(); endInsertRows();
emit countChanged(); emit countChanged();
} }
void EventDescriptors::removeEventDescriptor(int index)
{
beginRemoveRows(QModelIndex(), index, index);
m_list.takeAt(index)->deleteLater();
endRemoveRows();
emit countChanged();
}

View File

@ -24,6 +24,7 @@ public:
Q_INVOKABLE EventDescriptor* createNewEventDescriptor(); Q_INVOKABLE EventDescriptor* createNewEventDescriptor();
Q_INVOKABLE void addEventDescriptor(EventDescriptor *eventDescriptor); Q_INVOKABLE void addEventDescriptor(EventDescriptor *eventDescriptor);
Q_INVOKABLE void removeEventDescriptor(int index);
signals: signals:
void countChanged(); void countChanged();

View File

@ -27,12 +27,12 @@ EventType::EventType(QObject *parent) :
{ {
} }
QUuid EventType::id() const QString EventType::id() const
{ {
return m_id; return m_id;
} }
void EventType::setId(const QUuid &id) void EventType::setId(const QString &id)
{ {
m_id = id; m_id = id;
} }

View File

@ -31,7 +31,7 @@
class EventType : public QObject class EventType : public QObject
{ {
Q_OBJECT 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 name READ name CONSTANT)
Q_PROPERTY(QString displayName READ displayName CONSTANT) Q_PROPERTY(QString displayName READ displayName CONSTANT)
Q_PROPERTY(int index READ index CONSTANT) Q_PROPERTY(int index READ index CONSTANT)
@ -40,8 +40,8 @@ class EventType : public QObject
public: public:
explicit EventType(QObject *parent = 0); explicit EventType(QObject *parent = 0);
QUuid id() const; QString id() const;
void setId(const QUuid &id); void setId(const QString &id);
QString name() const; QString name() const;
void setName(const QString &name); void setName(const QString &name);
@ -56,7 +56,7 @@ public:
void setParamTypes(ParamTypes *paramTypes); void setParamTypes(ParamTypes *paramTypes);
private: private:
QUuid m_id; QString m_id;
QString m_name; QString m_name;
QString m_displayName; QString m_displayName;
int m_index; int m_index;

View File

@ -39,7 +39,7 @@ EventType *EventTypes::get(int index) const
return m_eventTypes.at(index); return m_eventTypes.at(index);
} }
EventType *EventTypes::getEventType(const QUuid &eventTypeId) const EventType *EventTypes::getEventType(const QString &eventTypeId) const
{ {
foreach (EventType *eventType, m_eventTypes) { foreach (EventType *eventType, m_eventTypes) {
if (eventType->id() == eventTypeId) { if (eventType->id() == eventTypeId) {
@ -64,7 +64,7 @@ QVariant EventTypes::data(const QModelIndex &index, int role) const
if (role == NameRole) { if (role == NameRole) {
return eventType->name(); return eventType->name();
} else if (role == IdRole) { } else if (role == IdRole) {
return eventType->id().toString(); return eventType->id();
} }
return QVariant(); return QVariant();
} }

View File

@ -44,7 +44,7 @@ public:
QList<EventType *> eventTypes(); QList<EventType *> eventTypes();
Q_INVOKABLE EventType *get(int index) const; Q_INVOKABLE EventType *get(int index) const;
Q_INVOKABLE EventType *getEventType(const QUuid &eventTypeId) const; Q_INVOKABLE EventType *getEventType(const QString &eventTypeId) const;
int rowCount(const QModelIndex & parent = QModelIndex()) const; int rowCount(const QModelIndex & parent = QModelIndex()) const;
QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const; QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;

View File

@ -17,3 +17,10 @@ void ParamDescriptor::setOperatorType(ParamDescriptor::ValueOperator operatorTyp
emit operatorTypeChanged(); emit operatorTypeChanged();
} }
} }
ParamDescriptor *ParamDescriptor::clone() const
{
ParamDescriptor *ret = new ParamDescriptor(this->id(), this->value());
ret->setOperatorType(this->operatorType());
return ret;
}

View File

@ -23,6 +23,7 @@ public:
ValueOperator operatorType() const; ValueOperator operatorType() const;
void setOperatorType(ValueOperator operatorType); void setOperatorType(ValueOperator operatorType);
ParamDescriptor* clone() const;
signals: signals:
void operatorTypeChanged(); void operatorTypeChanged();

View File

@ -14,9 +14,26 @@ int ParamDescriptors::rowCount(const QModelIndex &parent) const
QVariant ParamDescriptors::data(const QModelIndex &index, int role) const QVariant ParamDescriptors::data(const QModelIndex &index, int role) const
{ {
switch (role) {
case RoleId:
return m_list.at(index.row())->id();
case RoleValue:
return m_list.at(index.row())->value();
case RoleOperator:
return m_list.at(index.row())->operatorType();
}
return QVariant(); return QVariant();
} }
QHash<int, QByteArray> ParamDescriptors::roleNames() const
{
QHash<int, QByteArray> roles;
roles.insert(RoleId, "id");
roles.insert(RoleValue, "value");
roles.insert(RoleOperator, "operator");
return roles;
}
ParamDescriptor *ParamDescriptors::get(int index) const ParamDescriptor *ParamDescriptors::get(int index) const
{ {
return m_list.at(index); return m_list.at(index);

View File

@ -20,10 +20,18 @@ public:
}; };
Q_ENUM(ValueOperator) Q_ENUM(ValueOperator)
enum Roles {
RoleId,
RoleValue,
RoleOperator
};
Q_ENUM(Roles)
explicit ParamDescriptors(QObject *parent = nullptr); explicit ParamDescriptors(QObject *parent = nullptr);
int rowCount(const QModelIndex &parent = QModelIndex()) const override; int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role) const override; QVariant data(const QModelIndex &index, int role) const override;
QHash<int, QByteArray> roleNames() const override;
ParamDescriptor* get(int index) const; ParamDescriptor* get(int index) const;

View File

@ -1,8 +1,11 @@
#include "rule.h" #include "rule.h"
#include "eventdescriptor.h"
#include "eventdescriptors.h" #include "eventdescriptors.h"
#include "ruleactions.h"
#include "stateevaluator.h" #include "stateevaluator.h"
#include "stateevaluators.h"
#include "ruleaction.h"
#include "ruleactions.h"
Rule::Rule(const QUuid &id, QObject *parent) : Rule::Rule(const QUuid &id, QObject *parent) :
QObject(parent), QObject(parent),
@ -59,3 +62,22 @@ RuleActions *Rule::ruleActions() const
{ {
return m_ruleActions; return m_ruleActions;
} }
Rule *Rule::clone() const
{
Rule *ret = new Rule(this->id());
ret->setName(this->name());
ret->setEnabled(this->enabled());
for (int i = 0; i < this->eventDescriptors()->rowCount(); i++) {
ret->eventDescriptors()->addEventDescriptor(this->eventDescriptors()->get(i)->clone());
}
// ret->stateEvaluator()->setStateDescriptor(this->stateEvaluator()->stateDescriptor()->clone());
// ret->stateEvaluator()->setStateOperator(this->stateEvaluator()->stateOperator());
// for (int i = 0; i < this->stateEvaluator()->childEvaluators()->rowCount(); i++) {
// ret->stateEvaluator()->childEvaluators()->
// }
for (int i = 0; i < this->ruleActions()->rowCount(); i++) {
ret->ruleActions()->addRuleAction(this->ruleActions()->get(i)->clone());
}
return ret;
}

View File

@ -32,6 +32,8 @@ public:
StateEvaluator *stateEvaluator() const; StateEvaluator *stateEvaluator() const;
RuleActions* ruleActions() const; RuleActions* ruleActions() const;
Rule *clone() const;
signals: signals:
void nameChanged(); void nameChanged();
void enabledChanged(); void enabledChanged();

View File

@ -1,5 +1,6 @@
#include "ruleaction.h" #include "ruleaction.h"
#include "ruleactionparam.h"
#include "ruleactionparams.h" #include "ruleactionparams.h"
RuleAction::RuleAction(QObject *parent) : QObject(parent) RuleAction::RuleAction(QObject *parent) : QObject(parent)
@ -37,3 +38,14 @@ RuleActionParams *RuleAction::ruleActionParams() const
{ {
return m_ruleActionParams; return m_ruleActionParams;
} }
RuleAction *RuleAction::clone() const
{
RuleAction *ret = new RuleAction();
ret->setActionTypeId(actionTypeId());
ret->setDeviceId(deviceId());
for (int i = 0; i < ruleActionParams()->rowCount(); i++) {
ret->ruleActionParams()->addRuleActionParam(ruleActionParams()->get(i)->clone());
}
return ret;
}

View File

@ -24,6 +24,8 @@ public:
RuleActionParams* ruleActionParams() const; RuleActionParams* ruleActionParams() const;
RuleAction *clone() const;
signals: signals:
void deviceIdChanged(); void deviceIdChanged();
void actionTypeIdChanged(); void actionTypeIdChanged();

View File

@ -28,5 +28,13 @@ void RuleActionParam::setValue(const QVariant &value)
if (m_value != value) { if (m_value != value) {
m_value = value; m_value = value;
emit valueChanged(); emit valueChanged();
} }
}
RuleActionParam *RuleActionParam::clone() const
{
RuleActionParam *ret = new RuleActionParam();
ret->setParamTypeId(paramTypeId());
ret->setValue(value());
return ret;
} }

View File

@ -19,6 +19,7 @@ public:
QVariant value() const; QVariant value() const;
void setValue(const QVariant &value); void setValue(const QVariant &value);
RuleActionParam* clone() const;
signals: signals:
void paramTypeIdChanged(); void paramTypeIdChanged();
void valueChanged(); void valueChanged();

View File

@ -15,9 +15,23 @@ int RuleActionParams::rowCount(const QModelIndex &parent) const
QVariant RuleActionParams::data(const QModelIndex &index, int role) const QVariant RuleActionParams::data(const QModelIndex &index, int role) const
{ {
switch (role) {
case RoleParamTypeId:
return m_list.at(index.row())->paramTypeId();
case RoleValue:
return m_list.at(index.row())->value();
}
return QVariant(); return QVariant();
} }
QHash<int, QByteArray> RuleActionParams::roleNames() const
{
QHash<int, QByteArray> roles;
roles.insert(RoleParamTypeId, "paramTypeId");
roles.insert(RoleValue, "value");
return roles;
}
void RuleActionParams::addRuleActionParam(RuleActionParam *ruleActionParam) void RuleActionParams::addRuleActionParam(RuleActionParam *ruleActionParam)
{ {
ruleActionParam->setParent(this); ruleActionParam->setParent(this);

View File

@ -10,10 +10,17 @@ class RuleActionParams : public QAbstractListModel
Q_OBJECT Q_OBJECT
Q_PROPERTY(int count READ rowCount NOTIFY countChanged) Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
public: public:
enum Roles {
RoleParamTypeId,
RoleValue
};
Q_ENUM(Roles)
explicit RuleActionParams(QObject *parent = nullptr); explicit RuleActionParams(QObject *parent = nullptr);
int rowCount(const QModelIndex &parent = QModelIndex()) const override; int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role) const override; QVariant data(const QModelIndex &index, int role) const override;
QHash<int, QByteArray> roleNames() const override;
void addRuleActionParam(RuleActionParam* ruleActionParam); void addRuleActionParam(RuleActionParam* ruleActionParam);

View File

@ -8,6 +8,7 @@ RuleActions::RuleActions(QObject *parent) : QAbstractListModel(parent)
int RuleActions::rowCount(const QModelIndex &parent) const int RuleActions::rowCount(const QModelIndex &parent) const
{ {
Q_UNUSED(parent)
return m_list.count(); return m_list.count();
} }
@ -22,11 +23,23 @@ void RuleActions::addRuleAction(RuleAction *ruleAction)
beginInsertRows(QModelIndex(), m_list.count(), m_list.count()); beginInsertRows(QModelIndex(), m_list.count(), m_list.count());
m_list.append(ruleAction); m_list.append(ruleAction);
endInsertRows(); endInsertRows();
emit countChanged();
}
void RuleActions::removeRuleAction(int index)
{
beginRemoveRows(QModelIndex(), index, index);
m_list.takeAt(index)->deleteLater();
endRemoveRows();
emit countChanged();
} }
RuleAction *RuleActions::get(int index) const RuleAction *RuleActions::get(int index) const
{ {
return m_list.at(index); if (index >= 0 && index < m_list.count()) {
return m_list.at(index);
}
return nullptr;
} }
RuleAction *RuleActions::createNewRuleAction() const RuleAction *RuleActions::createNewRuleAction() const

View File

@ -16,6 +16,7 @@ public:
QVariant data(const QModelIndex &index, int role) const override; QVariant data(const QModelIndex &index, int role) const override;
Q_INVOKABLE void addRuleAction(RuleAction* ruleAction); Q_INVOKABLE void addRuleAction(RuleAction* ruleAction);
Q_INVOKABLE void removeRuleAction(int index);
Q_INVOKABLE RuleAction* get(int index) const; Q_INVOKABLE RuleAction* get(int index) const;
Q_INVOKABLE RuleAction* createNewRuleAction() const; Q_INVOKABLE RuleAction* createNewRuleAction() const;

View File

@ -29,3 +29,9 @@ QVariant StateDescriptor::value() const
{ {
return m_value; return m_value;
} }
StateDescriptor *StateDescriptor::clone() const
{
StateDescriptor *ret = new StateDescriptor(deviceId(), valueOperator(), stateTypeId(), value());
return ret;
}

View File

@ -31,6 +31,7 @@ public:
QUuid stateTypeId() const; QUuid stateTypeId() const;
QVariant value() const; QVariant value() const;
StateDescriptor* clone() const;
private: private:
QUuid m_deviceId; QUuid m_deviceId;
ValueOperator m_operator = ValueOperatorEquals; ValueOperator m_operator = ValueOperatorEquals;

View File

@ -7,6 +7,7 @@ StateEvaluators::StateEvaluators(QObject *parent) : QAbstractListModel(parent)
int StateEvaluators::rowCount(const QModelIndex &parent) const int StateEvaluators::rowCount(const QModelIndex &parent) const
{ {
Q_UNUSED(parent)
return m_list.count(); return m_list.count();
} }