diff --git a/libnymea-common/types/interfaces.cpp b/libnymea-common/types/interfaces.cpp index 9693dbed..f23d5384 100644 --- a/libnymea-common/types/interfaces.cpp +++ b/libnymea-common/types/interfaces.cpp @@ -157,6 +157,12 @@ Interfaces::Interfaces(QObject *parent) : QAbstractListModel(parent) addActionType("mediacontroller", "pause", tr("Pause playback"), new ParamTypes()); addActionType("mediacontroller", "skipBack", tr("Skip back"), new ParamTypes()); addActionType("mediacontroller", "skipNext", tr("Skip next"), new ParamTypes()); + + addInterface("powersocket", tr("Power sockets")); + addStateType("powersocket", "power", QVariant::Bool, true, + tr("Powered"), + tr("Turned on/off"), + tr("Turn on/off")); } int Interfaces::rowCount(const QModelIndex &parent) const diff --git a/nymea-app/ui/grouping/GroupPage.qml b/nymea-app/ui/grouping/GroupPage.qml index ab252f45..b5ea065c 100644 --- a/nymea-app/ui/grouping/GroupPage.qml +++ b/nymea-app/ui/grouping/GroupPage.qml @@ -58,29 +58,82 @@ Page { showStates: true } - GridView { - id: gridView + DevicesProxy { + id: lightsInGroup + engine: _engine + sourceModel: devicesInGroup + filterTagId: root.groupTag + shownInterfaces: "light" + } + DevicesProxy { + id: dimmableLightsInGroup + engine: _engine + sourceModel: devicesInGroup + filterTagId: root.groupTag + shownInterfaces: "dimmablelight" + } + DevicesProxy { + id: colorLightsInGroup + engine: _engine + sourceModel: devicesInGroup + filterTagId: root.groupTag + shownInterfaces: "colorlight" + } + DevicesProxy { + id: socketsInGroup + engine: _engine + sourceModel: devicesInGroup + filterTagId: root.groupTag + shownInterfaces: "powersocket" + } + + ColumnLayout { anchors.fill: parent - anchors.margins: app.margins / 2 - model: devicesInGroup + Pane { + Layout.fillWidth: true + Material.elevation: 1 + RowLayout { + HeaderButton { + imageSource: "../images/powersocket.svg" + visible: socketsInGroup.count > 0 + } + HeaderButton { + imageSource: "../images/light-on.svg" + visible: lightsInGroup.count > 0 + } + HeaderButton { + imageSource: "../images/radiator.svg" + } + } + } - readonly property int minTileWidth: 180 - readonly property int minTileHeight: 240 - readonly property int tilesPerRow: root.width / minTileWidth + GridView { + id: gridView + Layout.fillWidth: true + Layout.fillHeight: true + clip: true - cellWidth: gridView.width / tilesPerRow - cellHeight: cellWidth + model: devicesInGroup - delegate: ThingTile { - width: gridView.cellWidth - height: gridView.cellHeight + readonly property int minTileWidth: 180 + readonly property int minTileHeight: 240 + readonly property int tilesPerRow: root.width / minTileWidth - device: devicesInGroup.get(index) + cellWidth: gridView.width / tilesPerRow + cellHeight: cellWidth - onClicked: pageStack.push(Qt.resolvedUrl("../devicepages/" + app.interfaceListToDevicePage(deviceClass.interfaces)), {device: device}) + delegate: ThingTile { + width: gridView.cellWidth + height: gridView.cellHeight + device: devicesInGroup.get(index) + + onClicked: pageStack.push(Qt.resolvedUrl("../devicepages/" + app.interfaceListToDevicePage(deviceClass.interfaces)), {device: device}) + + } } } + } diff --git a/nymea-app/ui/mainviews/GroupsView.qml b/nymea-app/ui/mainviews/GroupsView.qml index b2b99853..ad20dfc0 100644 --- a/nymea-app/ui/mainviews/GroupsView.qml +++ b/nymea-app/ui/mainviews/GroupsView.qml @@ -80,7 +80,7 @@ MouseArea { InterfacesProxy { id: controlsInGroup - shownInterfaces: ["light", "simpleclosable", "mediacontroller"] + shownInterfaces: ["light", "simpleclosable", "mediacontroller", "powersocket"] devicesProxyFilter: devicesInGroup showStates: true showActions: true @@ -132,7 +132,8 @@ MouseArea { anchors.fill: parent Repeater { - model: Math.min(controlsInGroup.count, parent.height / 50) +// model: Math.min(controlsInGroup.count, parent.height / 50) + model: controlsInGroup.count delegate: Loader { id: controlLoader Layout.fillWidth: true @@ -147,6 +148,8 @@ MouseArea { return lightDelegate case "mediacontroller": return mediaControllerDelegate + case "powersocket": + return powerSocketDelegate } } Binding { @@ -243,6 +246,51 @@ MouseArea { } } + Component { + id: powerSocketDelegate + RowLayout { + property var devices + + Layout.alignment: Layout.Right + + DevicesProxy { + id: sockets + engine: _engine + parentProxy: devices + shownInterfaces: ["powersocket"] + } + + ColorIcon { + Layout.preferredHeight: app.iconSize + Layout.preferredWidth: app.iconSize + name: "../images/powersocket.svg" + color: isOn ? app.accentColor : keyColor + + property bool isOn: { + for (var i = 0; i < sockets.count; i++) { + var device = sockets.get(i) + var powerId = device.deviceClass.stateTypes.findByName("power").id + if (device.states.getState(powerId).value === true) { + return true + } + } + return false; + } + + MouseArea { + anchors.fill: parent + onClicked: { + for (var i = 0; i < sockets.count; i++) { + var device = sockets.get(i) + var powerId = device.deviceClass.stateTypes.findByName("power").id + engine.deviceManager.executeAction(device.id, powerId, [{paramTypeId: powerId, value: !parent.isOn}]) + } + } + } + } + } + } + Component { id: lightDelegate RowLayout {