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 *eventType = new EventType(parent);
eventType->setId(eventTypeMap.value("id").toUuid());
eventType->setId(eventTypeMap.value("id").toString());
eventType->setName(eventTypeMap.value("name").toString());
eventType->setDisplayName(eventTypeMap.value("displayName").toString());
eventType->setIndex(eventTypeMap.value("index").toInt());
@ -217,7 +217,9 @@ Device *JsonTypes::unpackDevice(const QVariantMap &deviceMap, QObject *parent)
QVariantMap JsonTypes::packRule(Rule *rule)
{
QVariantMap ret;
ret.insert("ruleId", rule->id());
if (!rule->id().isNull()) {
ret.insert("ruleId", rule->id());
}
ret.insert("name", rule->name());
ret.insert("enabled", true);
@ -254,6 +256,8 @@ QVariantMap JsonTypes::packRule(Rule *rule)
QVariantMap paramDescriptor;
paramDescriptor.insert("paramTypeId", rule->eventDescriptors()->get(i)->paramDescriptors()->get(j)->id());
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);
}
eventDescriptor.insert("paramDescriptors", paramDescriptors);

View File

@ -105,7 +105,6 @@
<file>ui/EditDevicesPage.qml</file>
<file>ui/devicepages/ConfigureThingPage.qml</file>
<file>ui/magic/DeviceRulesPage.qml</file>
<file>ui/magic/SelectEventPage.qml</file>
<file>ui/magic/NewThingMagicPage.qml</file>
<file>ui/magic/EditRulePage.qml</file>
<file>ui/magic/SelectThingPage.qml</file>
@ -115,5 +114,9 @@
<file>ui/magic/SelectRuleActionPage.qml</file>
<file>ui/magic/SelectRuleActionParamsPage.qml</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>
</RCC>

View File

@ -12,6 +12,8 @@
#include "types/stateevaluator.h"
#include "types/statedescriptor.h"
#include <QMetaEnum>
RuleManager::RuleManager(JsonRpcClient* jsonClient, QObject *parent) :
JsonHandler(parent),
m_jsonClient(jsonClient),
@ -66,7 +68,7 @@ void RuleManager::removeRule(const QUuid &ruleId)
void RuleManager::editRule(Rule *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;
parseEventDescriptors(ruleMap.value("eventDescriptors").toList(), rule);
parseRuleActions(ruleMap.value("actions").toList(), rule);
parseStateEvaluator(ruleMap.value("stateEvaluator").toMap());
}
void RuleManager::addRuleReply(const QVariantMap &params)
@ -138,9 +141,10 @@ void RuleManager::removeRuleReply(const QVariantMap &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)
@ -149,7 +153,12 @@ void RuleManager::parseEventDescriptors(const QVariantList &eventDescriptorList,
EventDescriptor *eventDescriptor = new EventDescriptor(rule);
eventDescriptor->setDeviceId(eventDescriptorVariant.toMap().value("deviceId").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);
}
}

View File

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

View File

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

View File

@ -68,6 +68,32 @@ Page {
height: parent.view.height
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 {

View File

@ -11,6 +11,8 @@ Page {
signal accept();
onAccept: busyOverlay.opacity = 1
function addEventDescriptor() {
var eventDescriptor = root.rule.eventDescriptors.createNewEventDescriptor();
var page = pageStack.push(Qt.resolvedUrl("SelectThingPage.qml"));
@ -26,7 +28,7 @@ Page {
}
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.onDone.connect(function() {
root.rule.eventDescriptors.addEventDescriptor(eventPage.eventDescriptor);
@ -64,107 +66,193 @@ Page {
onBackPressed: pageStack.pop()
HeaderButton {
imageSource: "../images/tick.svg"
enabled: actionsRepeater.count > 0 && root.rule.name.length > 0
opacity: enabled ? 1 : .3
onClicked: {
root.accept()
}
}
}
ColumnLayout {
Flickable {
anchors.fill: parent
Label {
text: "Rule name"
}
TextField {
Layout.fillWidth: true
text: root.rule.name
onTextChanged: {
root.rule.name = text;
contentHeight: contentColumn.implicitHeight + app.margins
}
}
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 {
ColumnLayout {
id: contentColumn
anchors { left: parent.left; top: parent.top; right: parent.right; topMargin: app.margins }
ColumnLayout {
Layout.fillWidth: true
text: "Add an event which should trigger the execution of the rule"
}
Button {
text: "+"
onClicked: root.addEventDescriptor();
}
}
Layout.margins: app.margins
Label {
Layout.fillWidth: true
text: "Rule name"
}
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 {
text: "do the following:" + root.rule.ruleActions.count
}
ThinDivider {}
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
Layout.margins: app.margins
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 {
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();
}
}
}
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
}
}
}
Rectangle {
id: busyOverlay
anchors.fill: parent
color: "#55000000"
opacity: 0
Behavior on opacity { NumberAnimation {duration: 200 } }
BusyIndicator {
anchors.centerIn: parent
running: parent.opacity > 0
}
}
}

View File

@ -62,10 +62,8 @@ Page {
}
} else {
if (root.device) {
print("fdsfasdfdsafdas", deviceClass.eventTypes.count)
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})
actualModel.append({text: deviceClass.eventTypes.get(i).displayName, eventTypeId: deviceClass.eventTypes.get(i).id})
}
}
}
@ -73,6 +71,7 @@ Page {
ListModel {
id: actualModel
ListElement { text: ""; eventTypeId: "" }
}
ListView {
@ -97,7 +96,24 @@ Page {
}
}
} 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;
if (actionType.paramTypes.count > 0) {
var paramsPage = pageStack.push(Qt.resolvedUrl("SelectRuleActionParamsPage.qml"), {ruleAction: root.ruleAction})
paramsPage.onBackPressed.connect(function() { pageStack.pop(); });
paramsPage.onCompleted.connect(function() {
pageStack.pop();
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":
comp = "Int";
break;
case "Double":
comp = "Double";
break;
default:
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;
}
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;
EventDescriptor* clone() const;
signals:
void deviceIdChanged();
void eventTypeIdChanged();

View File

@ -34,7 +34,10 @@ QHash<int, QByteArray> EventDescriptors::roleNames() 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()
@ -50,3 +53,11 @@ void EventDescriptors::addEventDescriptor(EventDescriptor *eventDescriptor)
endInsertRows();
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 void addEventDescriptor(EventDescriptor *eventDescriptor);
Q_INVOKABLE void removeEventDescriptor(int index);
signals:
void countChanged();

View File

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

View File

@ -31,7 +31,7 @@
class EventType : 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 EventType : public QObject
public:
explicit EventType(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;

View File

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

View File

@ -44,7 +44,7 @@ public:
QList<EventType *> eventTypes();
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;
QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;

View File

@ -17,3 +17,10 @@ void ParamDescriptor::setOperatorType(ParamDescriptor::ValueOperator operatorTyp
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;
void setOperatorType(ValueOperator operatorType);
ParamDescriptor* clone() const;
signals:
void operatorTypeChanged();

View File

@ -14,9 +14,26 @@ int ParamDescriptors::rowCount(const QModelIndex &parent) 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();
}
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
{
return m_list.at(index);

View File

@ -20,10 +20,18 @@ public:
};
Q_ENUM(ValueOperator)
enum Roles {
RoleId,
RoleValue,
RoleOperator
};
Q_ENUM(Roles)
explicit ParamDescriptors(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;
ParamDescriptor* get(int index) const;

View File

@ -1,8 +1,11 @@
#include "rule.h"
#include "eventdescriptor.h"
#include "eventdescriptors.h"
#include "ruleactions.h"
#include "stateevaluator.h"
#include "stateevaluators.h"
#include "ruleaction.h"
#include "ruleactions.h"
Rule::Rule(const QUuid &id, QObject *parent) :
QObject(parent),
@ -59,3 +62,22 @@ RuleActions *Rule::ruleActions() const
{
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;
RuleActions* ruleActions() const;
Rule *clone() const;
signals:
void nameChanged();
void enabledChanged();

View File

@ -1,5 +1,6 @@
#include "ruleaction.h"
#include "ruleactionparam.h"
#include "ruleactionparams.h"
RuleAction::RuleAction(QObject *parent) : QObject(parent)
@ -37,3 +38,14 @@ RuleActionParams *RuleAction::ruleActionParams() const
{
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;
RuleAction *clone() const;
signals:
void deviceIdChanged();
void actionTypeIdChanged();

View File

@ -28,5 +28,13 @@ void RuleActionParam::setValue(const QVariant &value)
if (m_value != value) {
m_value = value;
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;
void setValue(const QVariant &value);
RuleActionParam* clone() const;
signals:
void paramTypeIdChanged();
void valueChanged();

View File

@ -15,9 +15,23 @@ int RuleActionParams::rowCount(const QModelIndex &parent) 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();
}
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)
{
ruleActionParam->setParent(this);

View File

@ -10,10 +10,17 @@ class RuleActionParams : public QAbstractListModel
Q_OBJECT
Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
public:
enum Roles {
RoleParamTypeId,
RoleValue
};
Q_ENUM(Roles)
explicit RuleActionParams(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 addRuleActionParam(RuleActionParam* ruleActionParam);

View File

@ -8,6 +8,7 @@ RuleActions::RuleActions(QObject *parent) : QAbstractListModel(parent)
int RuleActions::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent)
return m_list.count();
}
@ -22,11 +23,23 @@ void RuleActions::addRuleAction(RuleAction *ruleAction)
beginInsertRows(QModelIndex(), m_list.count(), m_list.count());
m_list.append(ruleAction);
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
{
return m_list.at(index);
if (index >= 0 && index < m_list.count()) {
return m_list.at(index);
}
return nullptr;
}
RuleAction *RuleActions::createNewRuleAction() const

View File

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

View File

@ -29,3 +29,9 @@ QVariant StateDescriptor::value() const
{
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;
QVariant value() const;
StateDescriptor* clone() const;
private:
QUuid m_deviceId;
ValueOperator m_operator = ValueOperatorEquals;

View File

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