diff --git a/libnymea-common/types/ruleactionparam.cpp b/libnymea-common/types/ruleactionparam.cpp index e9c6bd92..289a7fe9 100644 --- a/libnymea-common/types/ruleactionparam.cpp +++ b/libnymea-common/types/ruleactionparam.cpp @@ -53,6 +53,32 @@ void RuleActionParam::setEventParamTypeId(const QString &eventParamTypeId) } } +QString RuleActionParam::stateDeviceId() const +{ + return m_stateDeviceId; +} + +void RuleActionParam::setStateDeviceId(const QString &stateDeviceId) +{ + if (m_stateDeviceId != stateDeviceId) { + m_stateDeviceId = stateDeviceId; + emit stateDeviceIdChanged(); + } +} + +QString RuleActionParam::stateTypeId() const +{ + return m_stateTypeId; +} + +void RuleActionParam::setStateTypeId(const QString &stateTypeId) +{ + if (m_stateTypeId != stateTypeId) { + m_stateTypeId = stateTypeId; + emit stateTypeIdChanged(); + } +} + RuleActionParam *RuleActionParam::clone() const { RuleActionParam *ret = new RuleActionParam(); @@ -61,6 +87,8 @@ RuleActionParam *RuleActionParam::clone() const ret->setValue(value()); ret->setEventTypeId(eventTypeId()); ret->setEventParamTypeId(eventParamTypeId()); + ret->setStateDeviceId(stateDeviceId()); + ret->setStateTypeId(stateTypeId()); return ret; } @@ -72,6 +100,8 @@ bool RuleActionParam::operator==(RuleActionParam *other) const COMPARE(m_paramName, other->paramName()); COMPARE(m_eventTypeId, other->eventTypeId()); COMPARE(m_eventParamTypeId, other->eventParamTypeId()); + COMPARE(m_stateDeviceId, other->stateDeviceId()); + COMPARE(m_stateTypeId, other->stateTypeId()); COMPARE(m_value, other->value()); return true; } diff --git a/libnymea-common/types/ruleactionparam.h b/libnymea-common/types/ruleactionparam.h index 6d79bc9a..a0f161bd 100644 --- a/libnymea-common/types/ruleactionparam.h +++ b/libnymea-common/types/ruleactionparam.h @@ -13,6 +13,8 @@ class RuleActionParam : public Param Q_PROPERTY(QString paramName READ paramName WRITE setParamName NOTIFY paramNameChanged) Q_PROPERTY(QString eventTypeId READ eventTypeId WRITE setEventTypeId NOTIFY eventTypeIdChanged) Q_PROPERTY(QString eventParamTypeId READ eventParamTypeId WRITE setEventParamTypeId NOTIFY eventParamTypeIdChanged) + Q_PROPERTY(QString stateDeviceId READ stateDeviceId WRITE setStateDeviceId NOTIFY stateDeviceIdChanged) + Q_PROPERTY(QString stateTypeId READ stateTypeId WRITE setStateTypeId NOTIFY stateTypeIdChanged) public: explicit RuleActionParam(const QString ¶mName, const QVariant &value, QObject *parent = nullptr); explicit RuleActionParam(QObject *parent = nullptr); @@ -26,17 +28,27 @@ public: QString eventParamTypeId() const; void setEventParamTypeId(const QString &eventParamTypeId); + QString stateDeviceId() const; + void setStateDeviceId(const QString &stateDeviceId); + + QString stateTypeId() const; + void setStateTypeId(const QString &stateTypeId); + RuleActionParam* clone() const; bool operator==(RuleActionParam *other) const; signals: void paramNameChanged(); void eventTypeIdChanged(); void eventParamTypeIdChanged(); + void stateDeviceIdChanged(); + void stateTypeIdChanged(); protected: QString m_paramName; QString m_eventTypeId; QString m_eventParamTypeId; + QString m_stateDeviceId; + QString m_stateTypeId; }; #endif // RULEACTIONPARAM_H diff --git a/libnymea-common/types/ruleactionparams.cpp b/libnymea-common/types/ruleactionparams.cpp index 0e40495e..c4f4ae48 100644 --- a/libnymea-common/types/ruleactionparams.cpp +++ b/libnymea-common/types/ruleactionparams.cpp @@ -94,6 +94,22 @@ void RuleActionParams::setRuleActionParamEvent(const QString ¶mTypeId, const addRuleActionParam(rap); } +void RuleActionParams::setRuleActionParamState(const QString ¶mTypeId, const QString &stateDeviceId, const QString &stateTypeId) +{ + foreach (RuleActionParam *rap, m_list) { + if (rap->paramTypeId() == paramTypeId) { + rap->setStateDeviceId(stateDeviceId); + rap->setStateTypeId(stateTypeId); + return; + } + } + RuleActionParam *rap = new RuleActionParam(this); + rap->setParamTypeId(paramTypeId); + rap->setStateDeviceId(stateDeviceId); + rap->setStateTypeId(stateTypeId); + addRuleActionParam(rap); +} + RuleActionParam *RuleActionParams::get(int index) const { return m_list.at(index); diff --git a/libnymea-common/types/ruleactionparams.h b/libnymea-common/types/ruleactionparams.h index 89444ecd..846e3263 100644 --- a/libnymea-common/types/ruleactionparams.h +++ b/libnymea-common/types/ruleactionparams.h @@ -29,6 +29,8 @@ public: Q_INVOKABLE void setRuleActionParam(const QString ¶mTypeId, const QVariant &value); Q_INVOKABLE void setRuleActionParamByName(const QString ¶mName, const QVariant &value); Q_INVOKABLE void setRuleActionParamEvent(const QString ¶mTypeId, const QString &eventTypeId, const QString &eventParamTypeId); + Q_INVOKABLE void setRuleActionParamState(const QString ¶mTypeId, const QString &stateDeviceId, const QString &stateTypeId); + Q_INVOKABLE RuleActionParam* get(int index) const; bool operator==(RuleActionParams *other) const; diff --git a/nymea-app/resources.qrc b/nymea-app/resources.qrc index e08babd0..a2a18a9b 100644 --- a/nymea-app/resources.qrc +++ b/nymea-app/resources.qrc @@ -179,5 +179,6 @@ ui/components/Imprint.qml ui/appsettings/LookAndFeelSettingsPage.qml ui/appsettings/AppLogPage.qml + ui/magic/SelectStatePage.qml diff --git a/nymea-app/ui/components/RemoveDeviceMethodDialog.qml b/nymea-app/ui/components/RemoveDeviceMethodDialog.qml index d7fe0eb4..08f894ee 100644 --- a/nymea-app/ui/components/RemoveDeviceMethodDialog.qml +++ b/nymea-app/ui/components/RemoveDeviceMethodDialog.qml @@ -38,27 +38,32 @@ Dialog { } ThinDivider {} - Button { - text: qsTr("Remove all those rules") + MeaListItemDelegate { Layout.fillWidth: true + text: qsTr("Remove all those rules") + progressive: false onClicked: { engine.deviceManager.removeDevice(root.device.id, DeviceManager.RemovePolicyCascade) root.close() root.destroy(); } } - Button { + + MeaListItemDelegate { text: qsTr("Update rules, removing this thing") Layout.fillWidth: true + progressive: false onClicked: { engine.deviceManager.removeDevice(root.device.id, DeviceManager.RemovePolicyUpdate) root.close() root.destroy(); } } - Button { + + MeaListItemDelegate { text: qsTr("Don't remove this thing") Layout.fillWidth: true + progressive: false onClicked: { root.close() root.destroy(); diff --git a/nymea-app/ui/delegates/ParamDelegate.qml b/nymea-app/ui/delegates/ParamDelegate.qml index 674a82cd..a7c3f43f 100644 --- a/nymea-app/ui/delegates/ParamDelegate.qml +++ b/nymea-app/ui/delegates/ParamDelegate.qml @@ -16,6 +16,8 @@ ItemDelegate { value: paramType.defaultValue } property bool writable: true + property alias nameVisible: nameLabel.visible + property string placeholderText: "" topPadding: 0 bottomPadding: 0 @@ -23,6 +25,7 @@ ItemDelegate { id: contentItemColumn RowLayout { Label { + id: nameLabel Layout.fillWidth: true Layout.minimumWidth: parent.width / 2 text: root.paramType.displayName @@ -90,7 +93,6 @@ ItemDelegate { } return root.param.value; } - } } Component { @@ -188,6 +190,7 @@ ItemDelegate { root.param.value = text; } } + placeholderText: root.placeholderText } } diff --git a/nymea-app/ui/magic/SelectRuleActionParamsPage.qml b/nymea-app/ui/magic/SelectRuleActionParamsPage.qml index 8fd4e543..fd4383d2 100644 --- a/nymea-app/ui/magic/SelectRuleActionParamsPage.qml +++ b/nymea-app/ui/magic/SelectRuleActionParamsPage.qml @@ -22,7 +22,7 @@ Page { signal completed(); header: GuhHeader { - text: "params" + text: actionType.displayName onBackPressed: root.backPressed(); } @@ -46,6 +46,9 @@ Page { if (eventParamRadioButton.checked) { return "event" } + if (stateValueRadioButton.checked) { + return "state" + } return "" } @@ -53,54 +56,115 @@ Page { property alias value: paramDelegate.value property alias eventType: eventParamsComboBox.eventType property alias eventParamTypeId: eventParamsComboBox.currentParamTypeId + property alias stateDeviceId: statePickerDelegate.deviceId + property alias stateTypeId: statePickerDelegate.stateTypeId - RadioButton { - id: staticParamRadioButton - text: qsTr("Use static value as parameter") - checked: true - } - ParamDelegate { - id: paramDelegate - Layout.fillWidth: true - paramType: root.actionType.paramTypes.get(index) - enabled: staticParamRadioButton.checked - } - - RadioButton { - id: eventParamRadioButton - text: qsTr("Use event parameter") - visible: eventParamsComboBox.count > 0 - } - ComboBox { - id: eventParamsComboBox + GroupBox { Layout.fillWidth: true Layout.margins: app.margins - enabled: eventParamRadioButton.checked - visible: count > 0 - Component.onCompleted: currentIndex = 0; - property var eventDescriptor: root.rule.eventDescriptors.count === 1 ? root.rule.eventDescriptors.get(0) : null - property var device: eventDescriptor ? engine.deviceManager.devices.getDevice(eventDescriptor.deviceId) : null - property var deviceClass: device ? engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId) : null - property var eventType: deviceClass ? deviceClass.eventTypes.getEventType(eventDescriptor.eventTypeId) : null - - property var currentParamDescriptor: eventType.paramTypes.get(eventParamsComboBox.currentIndex) - property var currentParamTypeId: currentParamDescriptor.id - - model: eventType.paramTypes - delegate: ItemDelegate { - width: parent.width - text: eventParamsComboBox.device.name + " - " + eventParamsComboBox.eventType.displayName + " - " + eventParamsComboBox.eventType.paramTypes.getParamType(model.id).displayName - } - contentItem: Label { - id: eventParamsComboBoxContentItem + title: paramType.displayName + ColumnLayout { anchors.fill: parent - anchors.margins: app.margins - text: eventParamsComboBox.device.name + " - " + eventParamsComboBox.eventType.displayName + " - " + eventParamsComboBox.currentParamDescriptor.displayName - elide: Text.ElideRight + RadioButton { + id: staticParamRadioButton + text: qsTr("Use static value as parameter") + checked: true + font.pixelSize: app.smallFont + } + RadioButton { + id: eventParamRadioButton + text: qsTr("Use event parameter") + visible: eventParamsComboBox.count > 0 + font.pixelSize: app.smallFont + } + RadioButton { + id: stateValueRadioButton + text: qsTr("Use a thing's state value") + font.pixelSize: app.smallFont + } + + ThinDivider {} + + ParamDelegate { + id: paramDelegate + Layout.fillWidth: true + paramType: root.actionType.paramTypes.get(index) + enabled: staticParamRadioButton.checked + nameVisible: false + visible: staticParamRadioButton.checked + placeholderText: qsTr("Insert value here") + } + + ComboBox { + id: eventParamsComboBox + Layout.fillWidth: true + visible: eventParamRadioButton.checked && count > 0 + Component.onCompleted: currentIndex = 0; + property var eventDescriptor: root.rule.eventDescriptors.count === 1 ? root.rule.eventDescriptors.get(0) : null + property var device: eventDescriptor ? engine.deviceManager.devices.getDevice(eventDescriptor.deviceId) : null + property var deviceClass: device ? engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId) : null + property var eventType: deviceClass ? deviceClass.eventTypes.getEventType(eventDescriptor.eventTypeId) : null + + property var currentParamDescriptor: eventType.paramTypes.get(eventParamsComboBox.currentIndex) + property var currentParamTypeId: currentParamDescriptor.id + + model: eventType.paramTypes + delegate: ItemDelegate { + width: parent.width + text: eventParamsComboBox.device.name + " - " + eventParamsComboBox.eventType.displayName + " - " + eventParamsComboBox.eventType.paramTypes.getParamType(model.id).displayName + } + contentItem: Label { + id: eventParamsComboBoxContentItem + anchors.fill: parent + anchors.margins: app.margins + text: eventParamsComboBox.device.name + " - " + eventParamsComboBox.eventType.displayName + " - " + eventParamsComboBox.currentParamDescriptor.displayName + elide: Text.ElideRight + } + } + + MeaListItemDelegate { + id: statePickerDelegate + Layout.fillWidth: true + text: deviceId === null || stateTypeId === null + ? qsTr("Select a state") + : dev.name + " - " + dev.deviceClass.stateTypes.getStateType(stateTypeId).displayName + visible: stateValueRadioButton.checked + + property var deviceId: null + property var stateTypeId: null + + readonly property Device dev: engine.deviceManager.devices.getDevice(deviceId) + + onClicked: { + var page = pageStack.push(Qt.resolvedUrl("SelectThingPage.qml"), {showStates: true, showEvents: false, showActions: false }); + page.thingSelected.connect(function(device) { + print("Thing selected", device.name); + statePickerDelegate.deviceId = device.id + var selectStatePage = pageStack.replace(Qt.resolvedUrl("SelectStatePage.qml"), {device: device}) + selectStatePage.stateSelected.connect(function(stateTypeId) { + print("State selected", stateTypeId) + pageStack.pop(); + statePickerDelegate.stateTypeId = stateTypeId; + }) + }) + } + } } } - ThinDivider {} +// Label { +// id: paramNameLabel +// Layout.fillWidth: true +// Layout.leftMargin: app.margins +// Layout.rightMargin: app.margins +// Layout.topMargin: app.margins +// elide: Text.ElideRight +// text: paramType.displayName +// font.pixelSize: app.largeFont +// } + + +// ThinDivider {} } } Item { @@ -124,6 +188,9 @@ Page { } else if (paramDelegate.type === "event") { print("adding event based rule action param", paramDelegate.paramType.id, paramDelegate.eventType.id, paramDelegate.eventParamTypeId) root.ruleAction.ruleActionParams.setRuleActionParamEvent(paramDelegate.paramType.id, paramDelegate.eventType.id, paramDelegate.eventParamTypeId) + } else if (paramDelegate.type === "state") { + print("adding state value based rule action param", paramDelegate.paramType.id, paramDelegate.stateDeviceId, paramDelegate.stateTypeId) + root.ruleAction.ruleActionParams.setRuleActionParamState(paramDelegate.paramType.id, paramDelegate.stateDeviceId, paramDelegate.stateTypeId) } } root.completed() diff --git a/nymea-app/ui/magic/SelectStatePage.qml b/nymea-app/ui/magic/SelectStatePage.qml new file mode 100644 index 00000000..8cf605bf --- /dev/null +++ b/nymea-app/ui/magic/SelectStatePage.qml @@ -0,0 +1,35 @@ +import QtQuick 2.8 +import QtQuick.Controls 2.1 +import QtQuick.Layouts 1.2 +import "../components" +import "../delegates" +import Nymea 1.0 + +Page { + id: root + header: GuhHeader { + text: qsTr("Select state") + onBackPressed: pageStack.pop() + } + + property Device device: null + + signal stateSelected(var stateTypeId); + + ListView { + anchors.fill: parent + + model: device.deviceClass.stateTypes + + delegate: MeaListItemDelegate { + width: parent.width + iconName: "../images/state.svg" + text: model.displayName + subText: root.device.states.getState(model.id).value + prominentSubText: false + onClicked: { + root.stateSelected(model.id) + } + } + } +}