mroe work on rules
This commit is contained in:
parent
0592ee6133
commit
46ab4656b4
@ -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);
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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 ¶ms)
|
||||
// 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 ¶ms)
|
||||
@ -138,9 +141,10 @@ void RuleManager::removeRuleReply(const QVariantMap ¶ms)
|
||||
qDebug() << "Have remove rule reply" << params;
|
||||
}
|
||||
|
||||
void RuleManager::editRuleReply(const QVariantMap ¶ms)
|
||||
void RuleManager::onEditRuleReply(const QVariantMap ¶ms)
|
||||
{
|
||||
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 ¶mDescriptorVariant, 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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,13 +37,16 @@ private slots:
|
||||
void getRuleDetailsReply(const QVariantMap ¶ms);
|
||||
void addRuleReply(const QVariantMap ¶ms);
|
||||
void removeRuleReply(const QVariantMap ¶ms);
|
||||
void editRuleReply(const QVariantMap ¶ms);
|
||||
void onEditRuleReply(const QVariantMap ¶ms);
|
||||
|
||||
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;
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
53
guh-control/ui/magic/SelectEventDescriptorParamsPage.qml
Normal file
53
guh-control/ui/magic/SelectEventDescriptorParamsPage.qml
Normal 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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
|
||||
24
guh-control/ui/paramdelegates/DoubleParamDelegate.qml
Normal file
24
guh-control/ui/paramdelegates/DoubleParamDelegate.qml
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -19,6 +19,9 @@ Loader {
|
||||
case "Int":
|
||||
comp = "Int";
|
||||
break;
|
||||
case "Double":
|
||||
comp = "Double";
|
||||
break;
|
||||
default:
|
||||
print("unhandled param type:", paramType.type)
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -34,6 +34,8 @@ public:
|
||||
|
||||
ParamDescriptors* paramDescriptors() const;
|
||||
|
||||
EventDescriptor* clone() const;
|
||||
|
||||
signals:
|
||||
void deviceIdChanged();
|
||||
void eventTypeIdChanged();
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -24,6 +24,7 @@ public:
|
||||
|
||||
Q_INVOKABLE EventDescriptor* createNewEventDescriptor();
|
||||
Q_INVOKABLE void addEventDescriptor(EventDescriptor *eventDescriptor);
|
||||
Q_INVOKABLE void removeEventDescriptor(int index);
|
||||
|
||||
signals:
|
||||
void countChanged();
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -23,6 +23,7 @@ public:
|
||||
ValueOperator operatorType() const;
|
||||
void setOperatorType(ValueOperator operatorType);
|
||||
|
||||
ParamDescriptor* clone() const;
|
||||
signals:
|
||||
void operatorTypeChanged();
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -32,6 +32,8 @@ public:
|
||||
StateEvaluator *stateEvaluator() const;
|
||||
RuleActions* ruleActions() const;
|
||||
|
||||
Rule *clone() const;
|
||||
|
||||
signals:
|
||||
void nameChanged();
|
||||
void enabledChanged();
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -24,6 +24,8 @@ public:
|
||||
|
||||
RuleActionParams* ruleActionParams() const;
|
||||
|
||||
RuleAction *clone() const;
|
||||
|
||||
signals:
|
||||
void deviceIdChanged();
|
||||
void actionTypeIdChanged();
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -19,6 +19,7 @@ public:
|
||||
QVariant value() const;
|
||||
void setValue(const QVariant &value);
|
||||
|
||||
RuleActionParam* clone() const;
|
||||
signals:
|
||||
void paramTypeIdChanged();
|
||||
void valueChanged();
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -31,6 +31,7 @@ public:
|
||||
QUuid stateTypeId() const;
|
||||
QVariant value() const;
|
||||
|
||||
StateDescriptor* clone() const;
|
||||
private:
|
||||
QUuid m_deviceId;
|
||||
ValueOperator m_operator = ValueOperatorEquals;
|
||||
|
||||
@ -7,6 +7,7 @@ StateEvaluators::StateEvaluators(QObject *parent) : QAbstractListModel(parent)
|
||||
|
||||
int StateEvaluators::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
return m_list.count();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user