rework lights pages

This commit is contained in:
Michael Zanetti 2018-09-28 20:08:58 +02:00
parent 3c6d00c646
commit e9ec00b56f
8 changed files with 356 additions and 234 deletions

View File

@ -28,8 +28,6 @@ SOURCES += main.cpp \
platformhelper.cpp \
platformintegration/generic/platformhelpergeneric.cpp \
OTHER_FILES += $$files(*.qml, true)
RESOURCES += resources.qrc \
ruletemplates.qrc
equals(STYLES_PATH, "") {
@ -125,4 +123,5 @@ DISTFILES += \
ui/components/BusyOverlay.qml \
ui/devicepages/NotificationsDevicePage.qml \
ruletemplates/buttontemplates.json \
ruletemplates/notificationtemplates.json
ruletemplates/notificationtemplates.json \
ui/devicepages/LightDevicePage.qml

View File

@ -62,7 +62,6 @@
<file>ui/images/weathericons/humidity.svg</file>
<file>ui/images/weathericons/wind.svg</file>
<file>ui/devicepages/WeatherDevicePage.qml</file>
<file>ui/devicepages/ColorLightDevicePage.qml</file>
<file>ui/components/ThrottledSlider.qml</file>
<file>ui/components/ColorPickerCt.qml</file>
<file>ui/images/navigation-menu.svg</file>
@ -249,5 +248,7 @@
<file>ui/appsettings/DeveloperOptionsPage.qml</file>
<file>ui/appsettings/CloudLoginPage.qml</file>
<file>ui/devicepages/NotificationsDevicePage.qml</file>
<file>ui/components/BrightnessSlider.qml</file>
<file>ui/devicepages/LightDevicePage.qml</file>
</qresource>
</RCC>

View File

@ -0,0 +1,86 @@
import QtQuick 2.3
Item {
id: root
property int brightness: min
property int min: 0
property int max: 100
property Component touchDelegate: Rectangle { height: root.height; width: 5; color: app.foregroundColor }
property bool active: true
property bool pressed: mouseArea.pressed
signal moved(real brightness);
Rectangle {
height: parent.width
width: parent.height
anchors.centerIn: parent
rotation: -90
border.width: 1
border.color: app.foregroundColor
gradient: Gradient {
GradientStop { position: 0.0; color: Qt.rgba(0, 0, 0, .5) }
GradientStop { position: 1.0; color: Qt.rgba(1, 1, 1, .5) }
}
}
Loader {
id: touchDelegateLoader
// 0 : width = min : max
// x = (width * (brightness - min) / (max-min))
property int position: (root.width * (root.brightness - root.min) / (root.max - root.min));
x: item ? Math.max(0, Math.min(position - width * .5, parent.width - item.width)) : 0
sourceComponent: root.touchDelegate
visible: !mouseArea.pressed && root.active
Behavior on x {
enabled: !mouseArea.pressed
NumberAnimation {}
}
}
MouseArea {
id: mouseArea
anchors.fill: parent
preventStealing: true
drag.minimumX: 0
drag.maximumX: width - dndItem.width
drag.minimumY: 0
drag.maximumY: height - dndItem.height
property var lastSentTime: new Date()
onPressed: {
dndItem.x = Math.min(width - dndItem.width, Math.max(0, mouseX - dndItem.width / 2))
dndItem.y = 0;
mouseArea.drag.target = dndItem;
}
onPositionChanged: {
root.brightness = Math.min(root.max, Math.max(root.min, (mouseX * (root.max - root.min) / width) + root.min))
var currentTime = new Date();
if (pressed && currentTime - lastSentTime > 200) {
root.moved(root.brightness)
lastSentTime = currentTime
}
}
onReleased: {
root.brightness = Math.min(root.max, Math.max(root.min, (mouseX * (root.max - root.min) / width) + root.min))
root.moved(root.brightness)
mouseArea.drag.target = undefined;
}
}
Loader {
id: dndItem
sourceComponent: root.touchDelegate
visible: mouseArea.pressed && root.active
}
}

View File

@ -131,6 +131,8 @@ Item {
Rectangle {
anchors.fill: parent
border.color: app.foregroundColor
border.width: 1
gradient: Gradient {
GradientStop { position: 0.0; color: "transparent" }
GradientStop { position: 1.0; color: "white" }

View File

@ -15,6 +15,8 @@ Item {
width: parent.height
anchors.centerIn: parent
rotation: -90
border.width: 1
border.color: app.foregroundColor
gradient: Gradient {
GradientStop { position: 0.0; color: "#efffff" }

View File

@ -9,56 +9,89 @@ Page {
header: GuhHeader {
text: qsTr("Lights")
onBackPressed: pageStack.pop()
}
ColumnLayout {
anchors.fill: parent
RowLayout {
Layout.fillWidth: true
Layout.margins: 10
Label {
text: qsTr("All")
Layout.fillWidth: true
}
Button {
text: qsTr("off")
onClicked: {
for (var i = 0; i < devicesProxy.count; i++) {
var device = devicesProxy.get(i);
var deviceClass = Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId);
var actionType = deviceClass.actionTypes.findByName("power");
var params = [];
var param1 = {};
param1["paramTypeId"] = actionType.paramTypes.get(0).id;
param1["value"] = false;
params.push(param1)
Engine.deviceManager.executeAction(device.id, actionType.id, params)
}
HeaderButton {
imageSource: "../images/system-shutdown.svg"
onClicked: {
for (var i = 0; i < devicesProxy.count; i++) {
var device = devicesProxy.get(i);
var deviceClass = Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId);
var actionType = deviceClass.actionTypes.findByName("power");
var params = [];
var param1 = {};
param1["paramTypeId"] = actionType.paramTypes.get(0).id;
param1["value"] = false;
params.push(param1)
Engine.deviceManager.executeAction(device.id, actionType.id, params)
}
}
}
}
ListView {
Layout.fillHeight: true
Layout.fillWidth: true
clip: true
model: DevicesProxy {
id: devicesProxy
devices: Engine.deviceManager.devices
}
ListView {
anchors.fill: parent
model: DevicesProxy {
id: devicesProxy
devices: Engine.deviceManager.devices
}
delegate: ItemDelegate {
id: itemDelegate
width: parent.width
height: childrenRect.height
property var device: devicesProxy.get(index);
property var deviceClass: Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId);
delegate: ItemDelegate {
id: itemDelegate
width: parent.width
property bool inline: width > 500
property var device: devicesProxy.get(index);
property var deviceClass: Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId);
property var connectedStateType: deviceClass.stateTypes.findByName("connected");
property var connectedState: device.states.getState(connectedStateType.id)
property var powerStateType: deviceClass.stateTypes.findByName("power");
property var powerActionType: deviceClass.actionTypes.findByName("power");
property var powerState: device.states.getState(powerStateType.id)
property var brightnessStateType: deviceClass.stateTypes.findByName("brightness");
property var brightnessActionType: deviceClass.actionTypes.findByName("brightness");
property var brightnessState: brightnessStateType ? device.states.getState(brightnessStateType.id) : null
property var colorStateType: deviceClass.stateTypes.findByName("color");
property var colorState: colorStateType ? device.states.getState(colorStateType.id) : null
topPadding: 0
bottomPadding: 0
leftPadding: 0
rightPadding: 0
contentItem: Rectangle {
id: contentItem
implicitHeight: itemDelegate.brightnessStateType && !itemDelegate.inline && enabled ? nameRow.implicitHeight + sliderRow.implicitHeight : nameRow.implicitHeight
gradient: Gradient {
GradientStop { position: 0.0; color: "transparent" }
GradientStop { position: 1.0; color: Qt.rgba(app.foregroundColor.r, app.foregroundColor.g, app.foregroundColor.b, 0.05) }
}
enabled: itemDelegate.connectedState === null || itemDelegate.connectedState.value === true
ColumnLayout {
anchors { left: parent.left; right: parent.right; top: parent.top }
anchors { left: parent.left; right: parent.right; margins: app.margins }
spacing: 0
RowLayout {
Layout.fillWidth: true
Layout.margins: 10
id: nameRow
z: 2 // make sure the switch in here is on top of the slider, given we cheated a bit and made them overlap
spacing: app.margins
ColorIcon {
Layout.preferredHeight: app.iconSize
Layout.preferredWidth: height
Layout.alignment: Qt.AlignVCenter
color: itemDelegate.connectedState !== null && itemDelegate.connectedState.value === false ?
"red"
: itemDelegate.colorStateType ? itemDelegate.colorState.value : "#00000000"
name: itemDelegate.connectedState !== null && itemDelegate.connectedState.value === false ?
"../images/dialog-warning-symbolic.svg"
: itemDelegate.powerState.value === true ? "../images/light-on.svg" : "../images/light-off.svg"
}
Label {
Layout.fillWidth: true
text: model.name
@ -67,42 +100,59 @@ Page {
}
ThrottledSlider {
id: inlineSlider
visible: model.interfaces.indexOf("dimmablelight") >= 0 && parent.width > 350
property var stateType: itemDelegate.deviceClass.stateTypes.findByName("brightness");
property var actionType: itemDelegate.deviceClass.actionTypes.findByName("brightness");
property var actionState: itemDelegate.device.states.getState(stateType.id)
visible: contentItem.enabled && itemDelegate.brightnessStateType && itemDelegate.inline
from: 0; to: 100
value: actionState.value
value: itemDelegate.brightnessState ? itemDelegate.brightnessState.value : 0
onMoved: {
var params = [];
var param1 = {};
param1["paramTypeId"] = actionType.paramTypes.get(0).id;
param1["paramTypeId"] = itemDelegate.brightnessActionType.paramTypes.get(0).id;
param1["value"] = value;
params.push(param1)
Engine.deviceManager.executeAction(device.id, actionType.id, params)
Engine.deviceManager.executeAction(itemDelegate.device.id, itemDelegate.brightnessActionType.id, params)
}
}
Switch {
property var stateType: itemDelegate.deviceClass.stateTypes.findByName("power");
property var actionType: itemDelegate.deviceClass.actionTypes.findByName("power");
property var actionState: itemDelegate.device.states.getState(stateType.id)
checked: actionState.value === true
checked: itemDelegate.powerState.value === true
onClicked: {
var params = [];
var param1 = {};
param1["paramTypeId"] = actionType.paramTypes.get(0).id;
param1["paramTypeId"] = itemDelegate.powerActionType.paramTypes.get(0).id;
param1["value"] = checked;
params.push(param1)
Engine.deviceManager.executeAction(device.id, actionType.id, params)
Engine.deviceManager.executeAction(device.id, itemDelegate.powerActionType.id, params)
}
}
}
Item {
id: sliderRow
Layout.fillWidth: true
implicitHeight: outlineSlider.implicitHeight * .6
Layout.preferredHeight: implicitHeight
ThrottledSlider {
id: outlineSlider
anchors { left: parent.left; right: parent.right; verticalCenter: parent.verticalCenter }
visible: contentItem.enabled && itemDelegate.brightnessStateType && !inlineSlider.visible
from: 0; to: 100
value: itemDelegate.brightnessState ? itemDelegate.brightnessState.value : 0
onMoved: {
var params = [];
var param1 = {};
param1["paramTypeId"] = itemDelegate.brightnessActionType.paramTypes.get(0).id;
param1["value"] = value;
params.push(param1)
Engine.deviceManager.executeAction(itemDelegate.device.id, itemDelegate.brightnessActionType.id, params)
}
}
}
}
}
onClicked: {
pageStack.push(Qt.resolvedUrl("../devicepages/ColorLightDevicePage.qml"), {device: devicesProxy.get(index)})
}
onClicked: {
var device = devicesProxy.get(index);
var deviceClass = Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId)
pageStack.push(Qt.resolvedUrl("../devicepages/LightDevicePage.qml"), {device: devicesProxy.get(index)})
}
}
}

View File

@ -1,173 +0,0 @@
import QtQuick 2.5
import QtQuick.Controls 2.1
import QtQuick.Layouts 1.1
import QtQuick.Controls.Material 2.1
import Nymea 1.0
import "../components"
DevicePageBase {
id: root
ColumnLayout {
anchors.fill: parent
RowLayout {
id: powerRow
Layout.fillWidth: true
Layout.margins: app.margins
spacing: app.margins
property var powerStateType: root.deviceClass.stateTypes.findByName("power")
property var powerState: root.device.states.getState(powerStateType.id)
property var brightnessStateType: root.deviceClass.stateTypes.findByName("brightness")
property var brightnessState: root.device.states.getState(brightnessStateType.id)
AbstractButton {
width: app.iconSize * 2
height: width
ColorIcon {
anchors.fill: parent
name: "../images/light-off.svg"
color: powerRow.powerState.value === true ? keyColor : app.accentColor
}
onClicked: {
var actionType = root.deviceClass.actionTypes.findByName("power");
var params = []
var param = {}
param["paramTypeId"] = actionType.paramTypes.get(0).id;
param["value"] = false;
params.push(param)
Engine.deviceManager.executeAction(root.device.id, powerRow.powerStateType.id, params);
}
}
ThrottledSlider {
id: brightnessSlider
Layout.fillWidth: true
value: powerRow.brightnessState.value
onMoved: {
var actionType = root.deviceClass.actionTypes.findByName("brightness");
var params = []
var param = {}
param["paramTypeId"] = actionType.paramTypes.get(0).id;
param["value"] = value;
params.push(param)
Engine.deviceManager.executeAction(root.device.id, powerRow.brightnessStateType.id, params);
}
}
AbstractButton {
width: app.iconSize * 2
height: width
ColorIcon {
anchors.fill: parent
name: "../images/light-on.svg"
color: powerRow.powerState.value === true ? app.accentColor : keyColor
}
onClicked: {
var actionType = root.deviceClass.actionTypes.findByName("power");
var params = []
var param = {}
param["paramTypeId"] = actionType.paramTypes.get(0).id;
param["value"] = true;
params.push(param)
Engine.deviceManager.executeAction(root.device.id, powerRow.powerStateType.id, params);
}
}
}
ColorPickerCt {
id: pickerCt
Layout.fillWidth: true
Layout.margins: app.margins
property var actionType: root.deviceClass.actionTypes.findByName("colorTemperature")
property var stateType: root.deviceClass.stateTypes.findByName("colorTemperature")
property var ctState: actionType ? root.device.states.getState(actionType.id) : null
ct: ctState ? ctState.value : 0
visible: root.deviceClass.interfaces.indexOf("colorlight") >= 0
minCt: actionType.paramTypes.findByName("colorTemperature").minValue
maxCt: actionType.paramTypes.findByName("colorTemperature").maxValue
height: 80
touchDelegate: Rectangle {
height: pickerCt.height
width: 5
color: "black"
}
property var lastSentTime: new Date()
onCtChanged: {
var currentTime = new Date();
if (pressed && currentTime - lastSentTime > 200) {
setColorTemp(ct)
lastSentTime = currentTime
}
}
function setColorTemp(ct) {
var actionType = root.deviceClass.actionTypes.findByName("colorTemperature");
var params = []
var param = {}
param["paramTypeId"] = actionType.paramTypes.get(0).id;
param["value"] = ct;
params.push(param)
Engine.deviceManager.executeAction(root.device.id, actionType.id, params);
}
}
ColorPicker {
id: colorPicker
Layout.fillWidth: true
Layout.fillHeight: true
Layout.margins: app.margins
property var actionType: root.deviceClass.actionTypes.findByName("color")
property var actionState: actionType ? root.device.states.getState(actionType.id).value : null
visible: root.deviceClass.interfaces.indexOf("colorlight") >= 0
color: actionState ? actionState : "white"
touchDelegate: Rectangle {
height: 15
width: height
radius: height / 2
color: Material.accent
Rectangle {
color: colorPicker.hovered || colorPicker.pressed ? "#11000000" : "transparent"
anchors.centerIn: parent
height: 30
width: height
radius: width / 2
Behavior on color {
ColorAnimation {
duration: 200
}
}
}
}
property var lastSentTime: new Date()
onColorChanged: {
var currentTime = new Date();
if (pressed && currentTime - lastSentTime > 200) {
var params = [];
var param1 = new Object();
param1["paramTypeId"] = actionType.paramTypes.get(0).id;
param1["value"] = color;
params.push(param1)
Engine.deviceManager.executeAction(root.device.id, actionType.id, params)
lastSentTime = currentTime
}
}
}
Item {
Layout.fillWidth: true
Layout.fillHeight: true
Layout.preferredHeight: 0
}
}
}

View File

@ -0,0 +1,155 @@
import QtQuick 2.5
import QtQuick.Controls 2.1
import QtQuick.Layouts 1.1
import QtQuick.Controls.Material 2.1
import Nymea 1.0
import "../components"
DevicePageBase {
id: root
readonly property var powerStateType: deviceClass.stateTypes.findByName("power")
readonly property var powerState: device.states.getState(powerStateType.id)
readonly property var powerActionType: deviceClass.actionTypes.findByName("power");
readonly property var brightnessStateType: deviceClass.stateTypes.findByName("brightness")
readonly property var brightnessState: brightnessStateType ? device.states.getState(brightnessStateType.id) : null
readonly property var brightnessActionType: deviceClass.actionTypes.findByName("brightness");
readonly property var colorStateType: deviceClass.stateTypes.findByName("color")
readonly property var colorState: colorStateType ? device.states.getState(colorStateType.id) : null
readonly property var colorActionType: deviceClass.actionTypes.findByName("color")
readonly property var ctStateType: deviceClass.stateTypes.findByName("colorTemperature")
readonly property var ctState: ctStateType ? device.states.getState(ctStateType.id) : null
readonly property var ctActionType: deviceClass.actionTypes.findByName("colorTemperature")
GridLayout {
anchors.fill: parent
columns: app.landscape ? 2 : 1
AbstractButton {
Layout.preferredWidth: app.iconSize * 4
Layout.preferredHeight: width
Layout.leftMargin: app.margins
Layout.rightMargin: app.landscape ? 0 : app.margins
Layout.topMargin: app.margins
Layout.bottomMargin: app.landscape ? app.margins : 0
Layout.alignment: Qt.AlignCenter
ColorIcon {
anchors.fill: parent
name: root.powerState.value === true ? "../images/light-on.svg" : "../images/light-off.svg"
color: root.powerState.value === true ? app.accentColor : keyColor
}
onClicked: {
var params = []
var param = {}
param["paramTypeId"] = root.powerActionType.paramTypes.get(0).id;
param["value"] = !root.powerState.value;
params.push(param)
Engine.deviceManager.executeAction(root.device.id, root.powerStateType.id, params);
}
}
ColumnLayout {
Layout.fillWidth: true
visible: root.brightnessStateType
BrightnessSlider {
Layout.fillWidth: true
Layout.margins: app.margins
Layout.preferredHeight: 40
brightness: root.brightnessState ? root.brightnessState.value : 0
visible: root.brightnessStateType
onMoved: {
var params = []
var param = {}
param["paramTypeId"] = root.brightnessActionType.paramTypes.get(0).id;
param["value"] = brightness;
params.push(param)
Engine.deviceManager.executeAction(root.device.id, root.brightnessActionType.id, params);
}
}
ColorPickerCt {
id: pickerCt
Layout.fillWidth: true
Layout.preferredHeight: 40
Layout.margins: app.margins
ct: root.ctState ? root.ctState.value : 0
visible: root.ctStateType
minCt: root.ctActionType ? root.ctActionType.paramTypes.findByName("colorTemperature").minValue : 0
maxCt: root.ctActionType ? root.ctActionType.paramTypes.findByName("colorTemperature").maxValue : 0
touchDelegate: Rectangle {
height: pickerCt.height
width: 5
color: app.foregroundColor
}
property var lastSentTime: new Date()
onCtChanged: {
var currentTime = new Date();
if (pressed && currentTime - lastSentTime > 200) {
setColorTemp(ct)
lastSentTime = currentTime
}
}
function setColorTemp(ct) {
var params = []
var param = {}
param["paramTypeId"] = root.ctActionType.paramTypes.get(0).id;
param["value"] = ct;
params.push(param)
Engine.deviceManager.executeAction(root.device.id, root.ctActionType.id, params);
}
}
ColorPicker {
id: colorPicker
Layout.fillWidth: true
Layout.preferredHeight: 80
Layout.margins: app.margins
visible: root.colorStateType
color: root.colorState ? root.colorState.value : "white"
touchDelegate: Rectangle {
height: 15
width: height
radius: height / 2
color: app.foregroundColor
Rectangle {
color: colorPicker.hovered || colorPicker.pressed ? "#11000000" : "transparent"
anchors.centerIn: parent
height: 30
width: height
radius: width / 2
Behavior on color {
ColorAnimation {
duration: 200
}
}
}
}
property var lastSentTime: new Date()
onColorChanged: {
var currentTime = new Date();
if (pressed && currentTime - lastSentTime > 200) {
var params = [];
var param1 = {};
param1["paramTypeId"] = root.colorActionType.paramTypes.get(0).id;
param1["value"] = color;
params.push(param1)
Engine.deviceManager.executeAction(root.device.id, root.colorActionType.id, params)
lastSentTime = currentTime
}
}
}
}
}
}