more work on interface based rules

This commit is contained in:
Michael Zanetti 2018-02-26 00:51:23 +01:00
parent b910166d91
commit af2e2fcda8
11 changed files with 116 additions and 88 deletions

View File

@ -23,7 +23,6 @@ GridView {
Pane { Pane {
anchors.fill: parent anchors.fill: parent
anchors.margins: app.margins anchors.margins: app.margins
// color: "#22000000"
Material.elevation: 1 Material.elevation: 1
Column { Column {
anchors.centerIn: parent anchors.centerIn: parent

View File

@ -50,14 +50,13 @@ Page {
ColumnLayout { ColumnLayout {
anchors.fill: parent anchors.fill: parent
anchors.margins: app.margins
SwipeView { SwipeView {
id: swipeView id: swipeView
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
currentIndex: pageIndicator.currentIndex currentIndex: pageIndicator.currentIndex
// clip: true clip: true
DevicesPage { DevicesPage {
width: parent.view.width width: parent.view.width

View File

@ -142,10 +142,9 @@ Page {
Layout.fillWidth: true Layout.fillWidth: true
spacing: app.margins spacing: app.margins
Repeater { Repeater {
model: root.rule.eventDescriptors.get(index).paramDescriptors model: eventDelegate.eventDescriptor.paramDescriptors
Label { Label {
text: { text: {
print("***", eventDelegate.iface, eventDelegate.eventDescriptor.interfaceName, Interfaces.findByName(eventDelegate.eventDescriptor.interfaceName), eventDescriptor.interfaceName ? Interfaces.findByName(eventDescriptor.interfaceName) : null)
var ret = eventDelegate.eventType.paramTypes.getParamType(model.id).displayName var ret = eventDelegate.eventType.paramTypes.getParamType(model.id).displayName
switch (model.operator) { switch (model.operator) {
case ParamDescriptor.ValueOperatorEquals: case ParamDescriptor.ValueOperatorEquals:
@ -216,22 +215,25 @@ Page {
delegate: SwipeDelegate { delegate: SwipeDelegate {
id: actionDelegate id: actionDelegate
Layout.fillWidth: true Layout.fillWidth: true
property var device: Engine.deviceManager.devices.getDevice(root.rule.ruleActions.get(index).deviceId) property var ruleAction: root.rule.ruleActions.get(index)
property var device: ruleAction.deviceId ? Engine.deviceManager.devices.getDevice(ruleAction.deviceId) : null
property var iface: ruleAction.interfaceName ? Interfaces.findByName(ruleAction.interfaceName) : null
property var deviceClass: device ? Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId) : null 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 property var actionType: deviceClass ? deviceClass.actionTypes.getActionType(ruleAction.actionTypeId)
: iface ? iface.actionTypes.findByName(ruleAction.interfaceAction) : null
contentItem: ColumnLayout { contentItem: ColumnLayout {
Label { Label {
Layout.fillWidth: true Layout.fillWidth: true
text: qsTr("%1 - %2").arg(actionDelegate.device.name).arg(actionDelegate.actionType.displayName) text: qsTr("%1 - %2").arg(actionDelegate.device ? actionDelegate.device.name : actionDelegate.iface.displayName).arg(actionDelegate.actionType.displayName)
} }
RowLayout { RowLayout {
Layout.fillWidth: true Layout.fillWidth: true
spacing: app.margins spacing: app.margins
Repeater { Repeater {
model: root.rule.ruleActions.get(index).ruleActionParams model: actionDelegate.ruleAction.ruleActionParams
Label { Label {
text: actionType.paramTypes.getParamType(model.paramTypeId).displayName + " -> " + model.value text: actionDelegate.actionType.paramTypes.getParamType(model.paramTypeId).displayName + " -> " + model.value
font.pixelSize: app.smallFont font.pixelSize: app.smallFont
} }
} }

View File

@ -43,9 +43,7 @@ Page {
function buildInterface() { function buildInterface() {
if (header.interfacesMode) { if (header.interfacesMode) {
if (root.device) { if (root.device) {
print("device supports interfaces", deviceClass.interfaces)
for (var i = 0; i < Interfaces.count; i++) { for (var i = 0; i < Interfaces.count; i++) {
print("event is for interface", Interfaces.get(i).name)
if (deviceClass.interfaces.indexOf(Interfaces.get(i).name) >= 0) { if (deviceClass.interfaces.indexOf(Interfaces.get(i).name) >= 0) {
actualModel.append(Interfaces.get(i)) actualModel.append(Interfaces.get(i))
} }

View File

@ -23,71 +23,55 @@ Page {
id: header id: header
onBackPressed: root.backPressed(); onBackPressed: root.backPressed();
property bool interfacesMode: false property bool interfacesMode: root.ruleAction.interfaceName !== ""
onInterfacesModeChanged: root.buildInterface() onInterfacesModeChanged: root.buildInterface()
HeaderButton { HeaderButton {
imageSource: header.interfacesMode ? "../images/view-expand.svg" : "../images/view-collapse.svg" imageSource: header.interfacesMode ? "../images/view-expand.svg" : "../images/view-collapse.svg"
visible: root.ruleAction.interfaceName === ""
onClicked: header.interfacesMode = !header.interfacesMode onClicked: header.interfacesMode = !header.interfacesMode
} }
} }
ListModel { // ListModel {
id: actionTemplateModel // id: actionTemplateModel
ListElement { interfaceName: "light"; text: "Switch light"; identifier: "switchLight"} // ListElement { interfaceName: "light"; text: "Switch light"; identifier: "switchLight"}
ListElement { interfaceName: "dimmablelight"; text: "Dim light"; identifier: "dimLight"} // ListElement { interfaceName: "dimmablelight"; text: "Dim light"; identifier: "dimLight"}
ListElement { interfaceName: "colorlight"; text: "Set light color"; identifier: "colorLight" } // ListElement { interfaceName: "colorlight"; text: "Set light color"; identifier: "colorLight" }
ListElement { interfaceName: "mediacontroller"; text: "Pause playback"; identifier: "pausePlayback" } // ListElement { interfaceName: "mediacontroller"; text: "Pause playback"; identifier: "pausePlayback" }
ListElement { interfaceName: "mediacontroller"; text: "Resume playback"; identifier: "resumePlayback" } // ListElement { interfaceName: "mediacontroller"; text: "Resume playback"; identifier: "resumePlayback" }
ListElement { interfaceName: "extendedvolumecontroller"; text: "Set volume"; identifier: "setVolume" } // ListElement { interfaceName: "extendedvolumecontroller"; text: "Set volume"; identifier: "setVolume" }
ListElement { interfaceName: "extendedvolumecontroller"; text: "Mute"; identifier: "mute" } // ListElement { interfaceName: "extendedvolumecontroller"; text: "Mute"; identifier: "mute" }
ListElement { interfaceName: "extendedvolumecontroller"; text: "Unmute"; identifier: "unmute" } // ListElement { interfaceName: "extendedvolumecontroller"; text: "Unmute"; identifier: "unmute" }
ListElement { interfaceName: "notifications"; text: "Notify me"; identifier: "notify" } // ListElement { interfaceName: "notifications"; text: "Notify me"; identifier: "notify" }
} // }
function buildInterface() { function buildInterface() {
actualModel.clear()
if (header.interfacesMode) { if (header.interfacesMode) {
if (root.device) { if (root.device) {
print("device supports interfaces", deviceClass.interfaces) for (var i = 0; i < Interfaces.count; i++) {
for (var i = 0; i < actionTemplateModel.count; i++) {
print("action is for interface", actionTemplateModel.get(i).interfaceName)
if (deviceClass.interfaces.indexOf(actionTemplateModel.get(i).interfaceName) >= 0) { if (deviceClass.interfaces.indexOf(actionTemplateModel.get(i).interfaceName) >= 0) {
actualModel.append(actionTemplateModel.get(i)) actualModel.append(actionTemplateModel.get(i))
} }
} }
} else if (root.ruleAction.interfaceName !== "") { } else if (root.ruleAction.interfaceName !== "") {
for (var i = 0; i < actionTemplateModel.count; i++) { listView.model = Interfaces.findByName(root.ruleAction.interfaceName).actionTypes
if (actionTemplateModel.get(i).interfaceName === root.ruleAction.interfaceName) {
actualModel.append(actionTemplateModel.get(i))
}
}
} else { } else {
console.warn("You need to set device or interfaceName"); console.warn("You need to set device or interfaceName");
} }
} else { } else {
if (root.device) { if (root.device) {
print("fdsfasdfdsafdas", deviceClass.actionTypes.count) listView.model = deviceClass.actionTypes
for (var i = 0; i < deviceClass.actionTypes.count; i++) {
print("bla", deviceClass.actionTypes.get(i).name, deviceClass.actionTypes.get(i).displayName, deviceClass.actionTypes.get(i).id)
actualModel.append({text: deviceClass.actionTypes.get(i).displayName, actionTypeId: deviceClass.actionTypes.get(i).id})
}
} }
} }
} }
ListModel {
id: actualModel
ListElement { text: ""; actionTypeId: "" }
}
ListView { ListView {
id: listView
anchors.fill: parent anchors.fill: parent
model: actualModel
delegate: ItemDelegate { delegate: ItemDelegate {
text: model.text text: model.displayName
width: parent.width width: parent.width
onClicked: { onClicked: {
if (header.interfacesMode) { if (header.interfacesMode) {
@ -100,10 +84,24 @@ Page {
default: default:
console.warn("FIXME: Unhandled interface action"); console.warn("FIXME: Unhandled interface action");
} }
} else if (root.ruleAction.interfaceName != "") {
root.ruleAction.interfaceAction = model.name;
if (listView.model.get(index).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();
})
} else {
root.done();
}
} else {
console.warn("Neither deviceId not interfaceName set. Cannot continue...");
} }
} else { } else {
if (root.device) { if (root.device) {
var actionType = root.deviceClass.actionTypes.getActionType(model.actionTypeId); var actionType = root.deviceClass.actionTypes.getActionType(model.id);
console.log("ActionType", actionType.id, "selected. Has", actionType.paramTypes.count, "params"); console.log("ActionType", actionType.id, "selected. Has", actionType.paramTypes.count, "params");
root.ruleAction.actionTypeId = actionType.id; root.ruleAction.actionTypeId = actionType.id;
if (actionType.paramTypes.count > 0) { if (actionType.paramTypes.count > 0) {

View File

@ -11,7 +11,9 @@ Page {
property var ruleAction property var ruleAction
readonly property var device: ruleAction && ruleAction.deviceId ? Engine.deviceManager.devices.getDevice(ruleAction.deviceId) : null readonly property var device: ruleAction && ruleAction.deviceId ? Engine.deviceManager.devices.getDevice(ruleAction.deviceId) : null
readonly property var actionType: device ? Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId).actionTypes.getActionType(ruleAction.actionTypeId) : null readonly property var iface: ruleAction && ruleAction.interfaceName ? Interfaces.findByName(ruleAction.interfaceName) : null
readonly property var actionType: device ? Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId).actionTypes.getActionType(ruleAction.actionTypeId)
: iface ? iface.actionTypes.findByName(ruleAction.interfaceAction) : null
signal backPressed(); signal backPressed();
signal completed(); signal completed();

View File

@ -32,17 +32,18 @@ ItemDelegate {
return stringComponent; return stringComponent;
} }
switch (root.paramType.type) { switch (root.paramType.type.toLowerCase()) {
case "Bool": case "bool":
return boolComponent; return boolComponent;
case "Int": case "int":
return stringComponent; return stringComponent;
case "String": case "string":
case "qstring":
if (root.paramType.allowedValues.length > 0) { if (root.paramType.allowedValues.length > 0) {
return comboBoxComponent; return comboBoxComponent;
} }
return textFieldComponent; return textFieldComponent;
case "Color": case "color":
return colorPreviewComponent; return colorPreviewComponent;
} }
console.warn("Param Delegate: Fallback to stringComponent", root.paramType.name, root.paramType.type) console.warn("Param Delegate: Fallback to stringComponent", root.paramType.name, root.paramType.type)
@ -53,14 +54,14 @@ ItemDelegate {
Loader { Loader {
Layout.fillWidth: true Layout.fillWidth: true
sourceComponent: { sourceComponent: {
switch (root.paramType.type) { switch (root.paramType.type.toLowerCase()) {
case "Int": case "int":
case "Double": case "double":
if (root.paramType.minValue != undefined && root.paramType.maxValue != undefined) { if (root.paramType.minValue != undefined && root.paramType.maxValue != undefined) {
return sliderComponent return sliderComponent
} }
break; break;
case "Color": case "color":
return colorPickerComponent return colorPickerComponent
} }
return null; return null;
@ -72,8 +73,8 @@ ItemDelegate {
id: stringComponent id: stringComponent
Label { Label {
text: { text: {
switch (root.paramType.type) { switch (root.paramType.type.toLowerCase()) {
case "Int": case "int":
return Math.round(root.param.value); return Math.round(root.param.value);
} }
return root.param.value; return root.param.value;

View File

@ -23,6 +23,7 @@ ItemDelegate {
switch (paramType.type.toLowerCase()) { switch (paramType.type.toLowerCase()) {
case "bool": case "bool":
case "string": case "string":
case "qstring":
return ["is", "is not"]; return ["is", "is not"];
case "int": case "int":
case "double": case "double":
@ -71,6 +72,7 @@ ItemDelegate {
} }
return textFieldComponent; return textFieldComponent;
case "string": case "string":
case "qstring":
if (paramType.allowedValues.length > 0) { if (paramType.allowedValues.length > 0) {
return comboBoxComponent return comboBoxComponent
} }
@ -85,9 +87,9 @@ ItemDelegate {
Loader { Loader {
Layout.fillWidth: true Layout.fillWidth: true
sourceComponent: { sourceComponent: {
switch (paramType.type) { switch (paramType.type.toLowerCase()) {
case "Int": case "int":
case "Double": case "double":
if (paramType.minValue !== undefined && paramType.maxValue !== undefined) { if (paramType.minValue !== undefined && paramType.maxValue !== undefined) {
return sliderComponent return sliderComponent
} }
@ -102,8 +104,8 @@ ItemDelegate {
id: labelComponent id: labelComponent
Label { Label {
text: { text: {
switch (root.paramType.type) { switch (root.paramType.type.toLowerCase()) {
case "Int": case "int":
return Math.round(root.value) return Math.round(root.value)
} }
return root.value return root.value

View File

@ -60,10 +60,13 @@ QVariant ActionTypes::data(const QModelIndex &index, int role) const
return QVariant(); return QVariant();
ActionType *actionType = m_actionTypes.at(index.row()); ActionType *actionType = m_actionTypes.at(index.row());
if (role == NameRole) { switch (role) {
return actionType->name(); case RoleId:
} else if (role == IdRole) {
return actionType->id(); return actionType->id();
case RoleName:
return actionType->name();
case RoleDisplayName:
return actionType->displayName();
} }
return QVariant(); return QVariant();
} }
@ -98,7 +101,8 @@ void ActionTypes::clearModel()
QHash<int, QByteArray> ActionTypes::roleNames() const QHash<int, QByteArray> ActionTypes::roleNames() const
{ {
QHash<int, QByteArray> roles; QHash<int, QByteArray> roles;
roles[NameRole] = "name"; roles.insert(RoleId, "id");
roles[IdRole] = "id"; roles.insert(RoleName, "name");
roles.insert(RoleDisplayName, "displayName");
return roles; return roles;
} }

View File

@ -33,9 +33,10 @@ class ActionTypes : 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 ActionTypeRole { enum Roles {
NameRole = Qt::DisplayRole, RoleId,
IdRole RoleName,
RoleDisplayName
}; };
ActionTypes(QObject *parent = 0); ActionTypes(QObject *parent = 0);

View File

@ -3,41 +3,63 @@
#include "eventtypes.h" #include "eventtypes.h"
#include "eventtype.h" #include "eventtype.h"
#include "actiontypes.h"
#include "actiontype.h"
Interfaces::Interfaces(QObject *parent) : QAbstractListModel(parent) Interfaces::Interfaces(QObject *parent) : QAbstractListModel(parent)
{ {
Interface* iface = nullptr; Interface* iface = nullptr;
EventType* ev = nullptr; EventType* et = nullptr;
ActionType* at = nullptr;
ParamType* pt = nullptr; ParamType* pt = nullptr;
ParamTypes *pts = nullptr; ParamTypes *pts = nullptr;
iface = new Interface("battery", "Battery powered devices"); iface = new Interface("battery", "Battery powered devices");
ev = new EventType(); et = new EventType();
pts = new ParamTypes(ev); pts = new ParamTypes(et);
ev->setParamTypes(pts); et->setParamTypes(pts);
ev->setName("batteryLevel"); et->setName("batteryLevel");
ev->setDisplayName("Battery level changed"); et->setDisplayName("Battery level changed");
pt = new ParamType("batteryLevel", QVariant::Int, 50); pt = new ParamType("batteryLevel", QVariant::Int, 50);
pt->setDisplayName("Battery Level"); pt->setDisplayName("Battery Level");
qDebug() << "added param" << pt->type(); qDebug() << "added param" << pt->type();
pt->setMinValue(0); pt->setMinValue(0);
pt->setMaxValue(100); pt->setMaxValue(100);
ev->paramTypes()->addParamType(pt); et->paramTypes()->addParamType(pt);
iface->eventTypes()->addEventType(ev); iface->eventTypes()->addEventType(et);
ev = new EventType(); et = new EventType();
pts = new ParamTypes(ev); pts = new ParamTypes(et);
ev->setParamTypes(pts); et->setParamTypes(pts);
ev->setName("batteryCritical"); et->setName("batteryCritical");
ev->setDisplayName("Battery level critical"); et->setDisplayName("Battery level critical");
pt = new ParamType("batteryCritical", QVariant::Bool, true); pt = new ParamType("batteryCritical", QVariant::Bool, true);
pt->setDisplayName("Battery critical"); pt->setDisplayName("Battery critical");
ev->paramTypes()->addParamType(pt); et->paramTypes()->addParamType(pt);
iface->eventTypes()->addEventType(ev); iface->eventTypes()->addEventType(et);
m_list.append(iface); m_list.append(iface);
iface = new Interface("notification", "Notification services");
at = new ActionType();
pts = new ParamTypes(at);
at->setParamTypes(pts);
at->setName("notify");
at->setDisplayName("Send notification");
pt = new ParamType("title", QVariant::String);
pt->setDisplayName("Title");
at->paramTypes()->addParamType(pt);
pt = new ParamType("body", QVariant::String);
pt->setDisplayName("Message body");
at->paramTypes()->addParamType(pt);
iface->actionTypes()->addActionType(at);
m_list.append(iface);
} }
int Interfaces::rowCount(const QModelIndex &parent) const int Interfaces::rowCount(const QModelIndex &parent) const