This repository has been archived on 2026-05-31. You can view files and clone it, but cannot push or open issues or pull requests.
powersync-app/nymea-app/ui/mainviews/FavoritesView.qml
2018-11-30 17:34:25 +01:00

421 lines
17 KiB
QML

import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
import QtQuick.Controls.Material 2.2
import Nymea 1.0
import "../components"
Item {
id: root
property bool editMode: false
readonly property int count: tagsProxy.count
TagsProxyModel {
id: tagsProxy
tags: engine.tagsManager.tags
filterTagId: "favorites"
}
GridView {
id: gridView
anchors.fill: parent
anchors.margins: app.margins / 2
readonly property int minTileWidth: 180
readonly property int minTileHeight: 240
readonly property int tilesPerRow: root.width / minTileWidth
cellWidth: gridView.width / tilesPerRow
cellHeight: cellWidth
model: tagsProxy
delegate: MainPageTile {
id: delegateRoot
width: gridView.cellWidth
height: gridView.cellHeight
text: device.name.toUpperCase()
iconName: app.interfacesToIcon(deviceClass.interfaces)
iconColor: app.accentColor
visible: !fakeDragItem.visible || fakeDragItem.deviceId !== device.id
batteryCritical: batteryCriticalState && batteryCriticalState.value === true
disconnected: connectedState && connectedState.value === false
property var modelIndex: index
property string deviceId: model.deviceId
property string ruleId: model.ruleId
readonly property var device: engine.deviceManager.devices.getDevice(deviceId)
readonly property var deviceClass: device ? engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId) : null
readonly property var connectedState: deviceClass.interfaces.indexOf("connectable") >= 0 ? device.states.getState(deviceClass.stateTypes.findByName("connected").id) : null
readonly property var batteryCriticalState: deviceClass.interfaces.indexOf("battery") >= 0 ? device.states.getState(deviceClass.stateTypes.findByName("batteryCritical").id) : null
onClicked: pageStack.push(Qt.resolvedUrl("../devicepages/" + app.interfaceListToDevicePage(deviceClass.interfaces)), {device: device})
onPressAndHold: root.editMode = true
contentItem: Loader {
id: loader
anchors.fill: parent
sourceComponent: {
if (delegateRoot.deviceClass.interfaces.indexOf("closable") >= 0) {
return closableComponent;
}
if (delegateRoot.deviceClass.interfaces.indexOf("light") >= 0) {
return lightsComponent;
}
if (delegateRoot.deviceClass.interfaces.indexOf("sensor") >= 0) {
return sensorsComponent;
}
if (delegateRoot.deviceClass.interfaces.indexOf("weather") >= 0) {
return sensorsComponent;
}
}
Binding { target: loader.item ? loader.item : null; property: "deviceClass"; value: delegateRoot.deviceClass }
Binding { target: loader.item ? loader.item : null; property: "device"; value: delegateRoot.device }
}
SequentialAnimation {
loops: Animation.Infinite
running: root.editMode
alwaysRunToEnd: true
NumberAnimation { from: 0; to: 3; target: delegateRoot; duration: 75; property: "rotation" }
NumberAnimation { from: 3; to: -3; target: delegateRoot; duration: 150; property: "rotation" }
NumberAnimation { from: -3; to: 0; target: delegateRoot; duration: 75; property: "rotation" }
}
}
MouseArea {
id: dragArea
anchors.fill: parent
enabled: root.editMode
propagateComposedEvents: true
property var dragOffset: ({})
property var draggedItem: null
onPressed: {
var item = gridView.itemAt(mouseX, mouseY)
draggedItem = item;
dragOffset = mapToItem(item, mouseX, mouseY)
fakeDragItem.x = mouseX - dragOffset.x;
fakeDragItem.y = mouseY - dragOffset.y;
fakeDragItem.text = item.text
fakeDragItem.iconName = item.iconName
fakeDragItem.iconColor = item.iconColor;
fakeDragItem.deviceId = item.device.id
fakeDragItem.batteryCritical = item.batteryCritical
fakeDragItem.disconnected = item.disconnected
drag.target = fakeDragItem
}
onReleased: {
drag.target = null
draggedItem = null
}
onClicked: {
root.editMode = false
}
}
MainPageTile {
id: fakeDragItem
width: gridView.cellWidth
height: gridView.cellHeight
Drag.active: dragArea.drag.active
visible: Drag.active
property var deviceId
}
DropArea {
id: dropArea
anchors.fill: gridView
property int from: -1
property int to: -1
onEntered: {
var index = gridView.indexAt(drag.x + dragArea.dragOffset.x, drag.y + dragArea.dragOffset.y);
from = index;
to = index;
}
onPositionChanged: {
var index = gridView.indexAt(drag.x + dragArea.dragOffset.x, drag.y + dragArea.dragOffset.y);
if (to !== index && from !== index && index >= 0 && index <= tagsProxy.count) {
to = index;
print("should move", from, "to", to)
for (var i = 0; i < tagsProxy.count; i++) {
if (i < Math.min(from, to) || i > Math.max(from, to)) {
// outside the range... don't touch
continue;
}
var newIdx;
if (i == from) {
newIdx = to;
} else {
if (from < to) {
// item is moved down the list
newIdx = i - 1;
} else {
newIdx = i + 1;
}
}
var tag = tagsProxy.get(i);
engine.tagsManager.tagDevice(tag.deviceId, tag.tagId, newIdx);
}
from = index;
}
}
}
}
Component {
id: lightsComponent
RowLayout {
property var device: null
property var deviceClass: null
ItemDelegate {
Layout.preferredWidth: app.iconSize
Layout.preferredHeight: app.iconSize
Layout.leftMargin: app.margins / 2
Layout.alignment: Qt.AlignVCenter
padding: 0; topPadding: 0; bottomPadding: 0
contentItem: ColorIcon {
name: "../images/light-off.svg"
color: app.accentColor
}
onClicked: {
var deviceClass = engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId);
var actionType = deviceClass.actionTypes.findByName("power");
var params = [];
var powerParam = {}
powerParam["paramTypeId"] = actionType.paramTypes.get(0).id;
powerParam["value"] = false;
params.push(powerParam)
engine.deviceManager.executeAction(device.id, actionType.id, params);
}
}
ThrottledSlider {
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter
visible: deviceClass.interfaces.indexOf("dimmablelight") >= 0
readonly property var brightnessStateType: deviceClass.stateTypes.findByName("brightness");
readonly property var brightnessState: device.states.getState(brightnessStateType.id)
from: 0
to: 100
value: brightnessState.value
onMoved: {
var deviceClass = engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId);
var actionType = deviceClass.actionTypes.findByName("brightness");
var params = [];
var powerParam = {}
powerParam["paramTypeId"] = actionType.paramTypes.get(0).id;
powerParam["value"] = value;
params.push(powerParam)
engine.deviceManager.executeAction(device.id, actionType.id, params);
}
}
ItemDelegate {
Layout.preferredWidth: app.iconSize
Layout.preferredHeight: width
Layout.rightMargin: app.margins / 2
Layout.alignment: Qt.AlignVCenter
padding: 0; topPadding: 0; bottomPadding: 0
contentItem: ColorIcon {
name: "../images/light-on.svg"
color: app.accentColor
}
onClicked: {
var deviceClass = engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId);
var actionType = deviceClass.actionTypes.findByName("power");
var params = [];
var powerParam = {}
powerParam["paramTypeId"] = actionType.paramTypes.get(0).id;
powerParam["value"] = true;
params.push(powerParam)
engine.deviceManager.executeAction(device.id, actionType.id, params);
}
}
}
}
Component {
id: sensorsComponent
RowLayout {
id: sensorsRoot
property var device: null
property var deviceClass: null
spacing: 0
property var shownInterfaces: []
property int currentStateIndex: -1
property var currentStateType: deviceClass ? deviceClass.stateTypes.findByName(shownInterfaces[currentStateIndex].state) : null
property var currentState: currentStateType ? device.states.getState(currentStateType.id) : null
onDeviceClassChanged: {
if (deviceClass == null) {
return;
}
var tmp = []
if (deviceClass.interfaces.indexOf("temperaturesensor") >= 0) {
tmp.push({iface: "temperaturesensor", state: "temperature"});
}
if (deviceClass.interfaces.indexOf("humiditysensor") >= 0) {
tmp.push({iface: "humiditysensor", state: "humidity"});
}
if (deviceClass.interfaces.indexOf("moisturesensor") >= 0) {
tmp.push({iface: "moisturesensor", state: "moisture"});
}
if (deviceClass.interfaces.indexOf("pressuresensor") >= 0) {
tmp.push({iface: "pressuresensor", state: "pressure"});
}
if (deviceClass.interfaces.indexOf("lightsensor") >= 0) {
tmp.push({iface: "lightsensor", state: "lightIntensity"});
}
if (deviceClass.interfaces.indexOf("conductivitysensor") >= 0) {
tmp.push({iface: "conductivitysensor", state: "conductivity"});
}
if (deviceClass.interfaces.indexOf("noisesensor") >= 0) {
tmp.push({iface: "noisesensor", state: "noise"});
}
if (deviceClass.interfaces.indexOf("co2sensor") >= 0) {
tmp.push({iface: "co2sensor", state: "co2"});
}
if (deviceClass.interfaces.indexOf("weather") >= 0) {
tmp.push({iface: "temperaturesensor", state: "temperature"});
tmp.push({iface: "humiditysensor", state: "humidity"});
tmp.push({iface: "pressuresensor", state: "pressure"});
}
shownInterfaces = tmp
currentStateIndex = 0
}
ItemDelegate {
Layout.preferredWidth: app.iconSize
Layout.preferredHeight: width
Layout.leftMargin: app.margins / 2
Layout.alignment: Qt.AlignVCenter
padding: 0; topPadding: 0; bottomPadding: 0
visible: sensorsRoot.shownInterfaces.length > 1
contentItem: ColorIcon {
name: "../images/back.svg"
}
onClicked: {
var newIndex = sensorsRoot.currentStateIndex - 1;
if (newIndex < 0) newIndex = sensorsRoot.shownInterfaces.length - 1
sensorsRoot.currentStateIndex = newIndex;
}
}
ColorIcon {
Layout.preferredWidth: app.iconSize
Layout.preferredHeight: width
Layout.alignment: Qt.AlignVCenter
color: app.interfaceToColor(sensorsRoot.shownInterfaces[sensorsRoot.currentStateIndex].iface)
name: app.interfaceToIcon(sensorsRoot.shownInterfaces[sensorsRoot.currentStateIndex].iface)
}
ColumnLayout {
Layout.fillWidth: true
spacing: 0
Label {
Layout.fillWidth: true
horizontalAlignment: Text.AlignRight
text: sensorsRoot.currentStateType.unitString
font.pixelSize: app.smallFont
color: app.accentColor
}
Label {
Layout.fillWidth: true
horizontalAlignment: Text.AlignRight
text: sensorsRoot.currentState.value// + " " + sensorsRoot.currentStateType.unitString
color: app.accentColor
}
}
ItemDelegate {
Layout.preferredWidth: app.iconSize
Layout.preferredHeight: width
Layout.rightMargin: app.margins / 2
Layout.alignment: Qt.AlignVCenter
padding: 0; topPadding: 0; bottomPadding: 0
visible: sensorsRoot.shownInterfaces.length > 1
contentItem: ColorIcon {
name: "../images/next.svg"
}
onClicked: {
var newIndex = sensorsRoot.currentStateIndex + 1;
if (newIndex >= sensorsRoot.shownInterfaces.length) newIndex = 0;
sensorsRoot.currentStateIndex = newIndex;
}
}
}
}
Component {
id: closableComponent
RowLayout {
property var device: null
property var deviceClass: null
ItemDelegate {
Layout.preferredWidth: app.iconSize
Layout.preferredHeight: width
Layout.leftMargin: app.margins / 2
Layout.alignment: Qt.AlignVCenter
padding: 0; topPadding: 0; bottomPadding: 0
contentItem: ColorIcon {
name: "../images/up.svg"
color: app.accentColor
}
onClicked: {
var deviceClass = engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId);
var actionType = deviceClass.actionTypes.findByName("open");
engine.deviceManager.executeAction(device.id, actionType.id);
}
}
Slider {
id: closableSlider
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter
visible: deviceClass.interfaces.indexOf("extendedclosable") >= 0
readonly property var percentageStateType: deviceClass.stateTypes.findByName("percentage");
readonly property var percentateState: device.states.getState(percentageStateType.id)
from: 0
to: 100
value: percentateState.value
}
Item {
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter
visible: !closableSlider.visible
}
ItemDelegate {
Layout.preferredWidth: app.iconSize
Layout.preferredHeight: width
Layout.rightMargin: app.margins / 2
Layout.alignment: Qt.AlignVCenter
padding: 0; topPadding: 0; bottomPadding: 0
contentItem: ColorIcon {
name: "../images/down.svg"
color: app.accentColor
}
onClicked: {
var deviceClass = engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId);
var actionType = deviceClass.actionTypes.findByName("close");
engine.deviceManager.executeAction(device.id, actionType.id);
}
}
}
}
}