Merge PR #114: Add a custom power socket view

This commit is contained in:
Jenkins 2019-01-08 02:21:28 +01:00
commit ee2dad9e74
8 changed files with 300 additions and 1 deletions

View File

@ -127,6 +127,9 @@ QVariant Devices::data(const QModelIndex &index, int role) const
if (interfaces.contains("evcharger")) {
return "evcharger";
}
if (interfaces.contains("powersocket")) {
return "powersocket";
}
return "uncategorized";
}

View File

@ -168,5 +168,6 @@
<file>ui/images/stock_music.svg</file>
<file>ui/images/stock_video.svg</file>
<file>ui/images/sensors/presence.svg</file>
<file>ui/images/powersocket.svg</file>
</qresource>
</RCC>

View File

@ -145,5 +145,7 @@
<file>ui/system/ServerConfigurationDialog.qml</file>
<file>ui/system/MqttPolicyPage.qml</file>
<file>ui/devicepages/BoolSensorDevicePage.qml</file>
<file>ui/devicepages/PowersocketDevicePage.qml</file>
<file>ui/devicelistpages/PowerSocketsDeviceListPage.qml</file>
</qresource>
</RCC>

View File

@ -52,7 +52,7 @@ ApplicationWindow {
rootItem.handleCloseEvent(close)
}
property var supportedInterfaces: ["light", "weather", "sensor", "media", "garagegate", "awning", "shutter", "blind", "heating", "smartmeter", "evcharger", "accesscontrol", "button", "notifications", "inputtrigger", "outputtrigger", "gateway"]
property var supportedInterfaces: ["light", "weather", "media", "garagegate", "awning", "shutter", "blind", "heating", "powersocket", "sensor", "smartmeter", "evcharger", "accesscontrol", "button", "notifications", "inputtrigger", "outputtrigger", "gateway"]
function interfaceToString(name) {
switch(name) {
case "light":
@ -106,6 +106,8 @@ ApplicationWindow {
return qsTr("Heatings");
case "evcharger":
return qsTr("EV-chargers");
case "powersocket":
return qsTr("Power sockets")
case "uncategorized":
return qsTr("Uncategorized")
default:
@ -155,6 +157,8 @@ ApplicationWindow {
case "media":
case "mediacontroller":
return Qt.resolvedUrl("images/mediaplayer-app-symbolic.svg")
case "powersocket":
return Qt.resolvedUrl("images/powersocket.svg")
case "button":
case "longpressbutton":
case "simplemultibutton":
@ -284,6 +288,8 @@ ApplicationWindow {
page = "FingerprintReaderDevicePage.qml";
} else if (interfaceList.indexOf("smartmeter") >= 0) {
page = "SmartMeterDevicePage.qml"
} else if (interfaceList.indexOf("powersocket") >= 0) {
page = "PowersocketDevicePage.qml";
} else {
page = "GenericDevicePage.qml";
}

View File

@ -0,0 +1,98 @@
import QtQuick 2.5
import QtQuick.Controls 2.1
import QtQuick.Layouts 1.1
import Nymea 1.0
import "../components"
import "../delegates"
import QtQuick.Controls.Material 2.1
DeviceListPageBase {
id: root
header: GuhHeader {
text: qsTr("My %1").arg(app.interfaceToString("powersocket"))
onBackPressed: {
pageStack.pop()
}
}
ListView {
anchors.fill: parent
model: devicesProxy
spacing: app.margins
delegate: Pane {
id: itemDelegate
width: parent.width
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: connectedStateType ? device.states.getState(connectedStateType.id) : null
property var powerStateType: deviceClass.stateTypes.findByName("power");
property var powerActionType: deviceClass.actionTypes.findByName("power");
property var powerState: device.states.getState(powerStateType.id)
Material.elevation: 1
topPadding: 0
bottomPadding: 0
leftPadding: 0
rightPadding: 0
contentItem: ItemDelegate {
id: contentItem
implicitHeight: nameRow.implicitHeight
topPadding: 0
contentItem: ColumnLayout {
spacing: 0
RowLayout {
enabled: itemDelegate.connectedState === null || itemDelegate.connectedState.value === true
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
Item {
Layout.preferredHeight: app.iconSize
Layout.preferredWidth: height
Layout.alignment: Qt.AlignVCenter
ColorIcon {
id: icon
anchors.fill: parent
color: itemDelegate.connectedState !== null && itemDelegate.connectedState.value === false
? "red"
: itemDelegate.powerState.value === true ? app.accentColor : keyColor
name: itemDelegate.connectedState !== null && itemDelegate.connectedState.value === false ?
"../images/dialog-warning-symbolic.svg"
: app.interfaceToIcon("powersocket")
}
}
Label {
Layout.fillWidth: true
text: model.name
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
}
Switch {
checked: itemDelegate.powerState.value === true
onClicked: {
var params = [];
var param1 = {};
param1["paramTypeId"] = itemDelegate.powerActionType.paramTypes.get(0).id;
param1["value"] = checked;
params.push(param1)
engine.deviceManager.executeAction(device.id, itemDelegate.powerActionType.id, params)
}
}
}
}
onClicked: {
enterPage(index, false)
}
}
}
}
}

View File

@ -0,0 +1,62 @@
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");
GridLayout {
anchors.fill: parent
anchors.margins: app.margins
columns: app.landscape ? 2 : 1
rowSpacing: app.margins
columnSpacing: app.margins
Layout.alignment: Qt.AlignCenter
Item {
Layout.preferredWidth: Math.max(app.iconSize * 4, parent.width / 5)
Layout.preferredHeight: width
Layout.topMargin: app.margins
Layout.bottomMargin: app.landscape ? app.margins : 0
Layout.alignment: Qt.AlignCenter
Layout.rowSpan: app.landscape ? 4 : 1
Layout.fillHeight: true
AbstractButton {
height: Math.min(parent.height, parent.width)
width: height
anchors.centerIn: parent
Rectangle {
anchors.fill: parent
color: "white"
border.color: root.powerState.value === true ? app.accentColor : bulbIcon.keyColor
border.width: 4
radius: width / 2
}
ColorIcon {
id: bulbIcon
anchors.fill: parent
anchors.margins: app.margins * 1.5
name: "../images/powersocket.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);
}
}
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
viewBox="0 0 96 96.000001"
version="1.1"
id="svg4874"
height="96"
width="96"
sodipodi:docname="powersocket.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)">
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="2792"
inkscape:window-height="1698"
id="namedview29"
showgrid="false"
inkscape:zoom="4.9166667"
inkscape:cx="-46.727922"
inkscape:cy="64.085507"
inkscape:window-x="88"
inkscape:window-y="44"
inkscape:window-maximized="1"
inkscape:current-layer="svg4874">
<inkscape:grid
type="xygrid"
id="grid922" />
</sodipodi:namedview>
<defs
id="defs4876" />
<metadata
id="metadata4879">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<rect
transform="rotate(90)"
y="-95.999985"
x="8.5593265e-06"
height="96"
width="96"
id="rect4782"
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:none;stroke:none;stroke-width:3.99920893;marker:none;enable-background:accumulate" />
<g
id="g4672"
transform="matrix(0.69491525,0,0,0.69491525,14.644068,14.644068)">
<path
sodipodi:nodetypes="ssssssscccscccssscccscccss"
inkscape:connector-curvature="0"
id="path833"
d="M 48,6 C 24.82773,5.9999998 6,24.82773 6,48 6,71.17227 24.82773,90 48,90 71.17227,90 90,71.17227 90,48 90,24.82773 71.17227,6 48,6 Z m 0,4 c 10.505255,0 20.005255,4.247373 26.878941,11.121059 1.718422,1.718421 4.637502,5.622369 4.637502,5.622369 L 79.458236,44 c 0,0 2.541764,0 6.345835,0.110817 C 85.933635,45.389393 86,46.686843 86,48 c 0,1.313157 -0.06637,2.610607 -0.195929,3.889183 -3.383454,0.110817 -6.363812,-0.0712 -6.363812,-0.0712 l 0.07618,17.438585 c 0,0 -2.91908,3.903948 -4.637502,5.622369 C 68.005255,81.752627 58.505255,86 48,86 37.494745,86 27.994745,81.752627 21.121059,74.878941 19.402637,73.16052 16.483557,69.256572 16.483557,69.256572 l 0.0043,-17.492517 c 0,0 -2.487832,0.05541 -6.291903,0.125128 C 10.066365,50.610607 10,49.313157 10,48 c 0,-1.313157 0.06819,-2.721423 0.19775,-4 2.595072,0 4.042709,0 6.322237,0 -0.04759,-10.80225 -0.03643,-17.256572 -0.03643,-17.256572 0,0 2.91908,-3.903948 4.637502,-5.622369 C 27.994745,14.247372 37.494745,9.9999999 48,10 Z"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.99999976;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<g
transform="translate(0.32623959)"
id="g965">
<circle
style="opacity:1;fill:#808080;fill-opacity:1;stroke:none;stroke-width:0.37795275;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path957"
cx="30.419512"
cy="48"
r="5" />
<circle
r="5"
cy="48"
cx="64.928009"
id="circle959"
style="opacity:1;fill:#808080;fill-opacity:1;stroke:none;stroke-width:0.37795275;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
<rect
y="11"
x="45"
height="10"
width="6"
id="rect961"
style="opacity:1;fill:#808080;fill-opacity:1;stroke:none;stroke-width:0.37795275;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
style="opacity:1;fill:#808080;fill-opacity:1;stroke:none;stroke-width:0.37795275;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect967"
width="6"
height="10"
x="45"
y="75" />
</g>
<g
transform="translate(67.857,-78.504997)"
id="layer1">
<rect
x="78.504997"
y="-28.143"
width="96"
height="96"
transform="rotate(90)"
style="color:#000000;fill:none"
id="rect4782-7" />
<path
d="m -43.869,86.504 -0.01172,0.002 c -5.0328,0.05818 -8.7136,-0.12027 -11.725,1.541 -1.5055,0.83064 -2.6968,2.2356 -3.3555,3.9902 -0.65866,1.7547 -0.89648,3.8364 -0.89648,6.4668 v 56.002 c 0,2.6304 0.23782,4.7121 0.89648,6.4668 0.65866,1.7546 1.85,3.1596 3.3555,3.9902 3.011,1.6613 6.6918,1.4848 11.725,1.543 H -43.869 4.154 4.165719 c 5.0328,-0.0582 8.7136,0.11832 11.725,-1.543 1.5055,-0.83064 2.6968,-2.2356 3.3555,-3.9902 0.65866,-1.7547 0.89648,-3.8364 0.89648,-6.4668 V 98.504 c 0,-2.6304 -0.23782,-4.7121 -0.89648,-6.4668 -0.66,-1.759 -1.851,-3.163 -3.356,-3.994 -3.011,-1.661 -6.6922,-1.483 -11.725,-1.541 L 4.1535,86.5002 h -48.023 z m 0.01172,4 h 48 c 5.0383,0.05877 8.3519,0.23688 9.8164,1.0449 0.73364,0.40478 1.1527,0.85491 1.543,1.8945 0.39025,1.0396 0.64062,2.691 0.64062,5.0605 v 56.002 c 0,2.3696 -0.25037,4.0209 -0.64062,5.0606 -0.39025,1.0396 -0.80933,1.4898 -1.543,1.8945 -1.4645,0.80804 -4.7782,0.98616 -9.8164,1.0449 h -47.977 -0.02344 c -5.0383,-0.0588 -8.3519,-0.23688 -9.8164,-1.0449 -0.73364,-0.40478 -1.1508,-0.85491 -1.541,-1.8945 -0.39025,-1.0396 -0.64258,-2.691 -0.64258,-5.0606 v -56.002 c 0,-2.3696 0.25232,-4.0209 0.64258,-5.0605 0.39025,-1.0396 0.80738,-1.4898 1.541,-1.8945 1.4645,-0.80804 4.7782,-0.98616 9.8164,-1.0449 z"
style="color:#000000;font-variant-ligatures:none;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;text-transform:none;white-space:normal;shape-padding:0;isolation:auto;mix-blend-mode:normal;solid-color:#000000;fill:#808080;color-rendering:auto;image-rendering:auto;shape-rendering:auto"
id="path4643"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

@ -43,6 +43,9 @@ MainPageTile {
case "extendedShutter":
page = "ShutterDeviceListPage.qml";
break;
case "powersocket":
page = "PowerSocketsDeviceListPage.qml";
break;
default:
page = "GenericDeviceListPage.qml"
}
@ -98,6 +101,7 @@ MainPageTile {
case "extendedshutter":
case "awning":
case "extendedawning":
case "powersocket":
return buttonComponent
default:
console.warn("DevicesPageDelegate, inlineControl: Unhandled interface", model.name)
@ -119,6 +123,7 @@ MainPageTile {
case "media":
return devicesProxy.get(0).name;
case "light":
case "powersocket":
var count = 0;
for (var i = 0; i < devicesProxy.count; i++) {
var device = devicesProxy.get(i);
@ -289,6 +294,7 @@ MainPageTile {
state.value === "Paused" ? "../images/media-playback-start.svg" :
""
case "light":
case "powersocket":
return "../images/system-shutdown.svg"
case "garagegate":
case "blind":
@ -307,6 +313,7 @@ MainPageTile {
onClicked: {
switch (model.name) {
case "light":
case "powersocket":
if (devicesProxy.count == 1) {
var device = devicesProxy.get(0);
var deviceClass = engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId);