Merge remote-tracking branch 'origin/tuning' into landing-silo

This commit is contained in:
Jenkins 2018-07-26 13:47:06 +02:00
commit 84dc119675
11 changed files with 713 additions and 364 deletions

View File

@ -234,5 +234,7 @@
<file>ui/images/sensors/moisture.svg</file>
<file>ui/images/sensors/pressure.svg</file>
<file>ui/images/sensors/temperature.svg</file>
<file>ui/components/MainPageTile.qml</file>
<file>ui/images/configure.svg</file>
</qresource>
</RCC>

View File

@ -10,4 +10,9 @@ ApplicationWindow {
Material.theme: Material.Dark
Material.accent: guhAccent
Material.primary: Material.background
function interfaceToColor(name) {
return "khaki"
}
}

View File

@ -81,6 +81,7 @@ Page {
id: favoritesViewComponent
FavoritesView {
id: favoritesView
objectName: "favorites"
width: swipeView.width
height: swipeView.height
property string title: qsTr("My favorites")
@ -201,6 +202,7 @@ Page {
id: tabEntryComponent
MainPageTabButton {
property int pageIndex: 0
// height: tabBar.height
onClicked: settings.currentMainViewIndex = pageIndex
alignment: app.landscape ? Qt.Horizontal : Qt.Vertical
}

View File

@ -32,7 +32,7 @@ ToolBar {
verticalAlignment: Text.AlignVCenter
font.pixelSize: app.mediumFont
elide: Text.ElideRight
text: root.title.toLowerCase();
text: root.title
}
HeaderButton {

View File

@ -40,7 +40,7 @@ ToolBar {
verticalAlignment: Text.AlignVCenter
font.pixelSize: app.mediumFont
elide: Text.ElideRight
text: root.text.toLowerCase();
text: root.text
}
}
}

View File

@ -8,6 +8,12 @@ TabButton {
property string iconSource
property var alignment: Qt.Vertical
Rectangle {
anchors.fill: parent
color: Material.foreground
opacity: 0.05
}
contentItem: GridLayout {
columns: root.alignment === Qt.Vertical ? 1 : 2
ColorIcon {

View File

@ -0,0 +1,108 @@
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Controls.Material 2.2
import QtQuick.Layouts 1.3
Item {
id: root
property alias iconName: colorIcon.name
property alias fallbackIconName: fallbackIcon.name
property alias iconColor: colorIcon.color
property string text
property bool disconnected: false
property bool batteryCritical: false
property alias contentItem: innerContent.children
signal clicked();
signal pressAndHold();
Pane {
anchors.fill: parent
anchors.margins: app.margins / 2
Material.elevation: 1
padding: 0
contentItem: ItemDelegate {
padding: 0; topPadding: 0; bottomPadding: 0
onClicked: root.clicked()
onPressAndHold: root.pressAndHold()
contentItem: ColumnLayout {
spacing: 0
ColumnLayout {
Layout.fillHeight: true
Layout.margins: app.margins
Item {
Layout.fillWidth: true
Layout.fillHeight: true
ColorIcon {
id: colorIcon
anchors.centerIn: parent
height: app.iconSize * 1.3
width: height
ColorIcon {
id: fallbackIcon
anchors.fill: parent
color: root.iconColor
visible: parent.status === Image.Error
}
}
}
Item {
Layout.fillWidth: true
Layout.fillHeight: true
Label {
id: label
anchors.centerIn: parent
width: parent.width
text: root.text.toUpperCase()
font.pixelSize: app.smallFont
font.letterSpacing: 1
wrapMode: Text.WordWrap
horizontalAlignment: Text.AlignHCenter
maximumLineCount: 2
elide: Text.ElideRight
}
}
}
MouseArea {
id: innerContent
Layout.fillWidth: true
Layout.preferredHeight: app.iconSize + app.margins * 2
visible: root.contentItem.length > 1
Rectangle {
anchors.fill: parent
color: Material.foreground
opacity: 0.05
}
}
}
}
}
Row {
id: quickAlertPane
anchors { top: parent.top; right: parent.right; margins: app.margins }
ColorIcon {
height: app.iconSize / 2
width: height
name: "../images/dialog-warning-symbolic.svg"
color: "red"
visible: root.disconnected
}
ColorIcon {
height: app.iconSize / 2
width: height
name: "../images/battery/battery-010.svg"
visible: root.batteryCritical
}
}
}

View File

@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<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"
id="svg4874"
width="96"
height="96"
version="1.1"
viewBox="0 0 96 96"
sodipodi:docname="configure.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)">
<defs
id="defs917" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="2880"
inkscape:window-height="1698"
id="namedview915"
showgrid="true"
inkscape:zoom="4.9460646"
inkscape:cx="-36.820629"
inkscape:cy="67.664461"
inkscape:window-x="0"
inkscape:window-y="44"
inkscape:window-maximized="1"
inkscape:current-layer="svg4874">
<inkscape:grid
type="xygrid"
id="grid922" />
</sodipodi:namedview>
<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
style="color:#000000;fill:none"
height="96"
width="96"
y="-96"
x="-2.7465819e-06"
transform="rotate(90)"
id="rect4782" />
<path
inkscape:connector-curvature="0"
style="fill:#808080;enable-background:new"
d="M 53.224853,20.293258 C 49.111288,24.40688 47.784374,30.257807 49.222134,35.5394 L 18.249429,66.512077 c -3.251992,3.252118 -3.363566,8.376104 -0.250528,11.489002 3.113108,3.11311 8.237157,3.0016 11.489141,-0.25039 L 60.46067,46.777936 c 5.281451,1.438184 11.133255,0.111723 15.246495,-4.002366 4.480632,-4.480533 5.647733,-11.037159 3.544302,-16.659153 l -8.249122,8.249094 -9.367678,-9.367823 8.249114,-8.249101 C 64.262353,14.644874 57.705564,15.812236 53.224699,20.29296 Z M 21.436868,70.171864 a 3.1053,3.0703 45 0 1 4.366879,0.02454 3.1053,3.0703 45 0 1 0.02475,4.367092 3.1053,3.0703 45 0 1 -4.367091,-0.02475 3.1053,3.0703 45 0 1 -0.02454,-4.366879 z"
id="path4328" />
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -5,257 +5,134 @@ import QtQuick.Controls.Material 2.2
import Nymea 1.0
import "../components"
Item {
MainPageTile {
id: root
Pane {
anchors.fill: parent
anchors.margins: app.margins / 2
Material.elevation: 1
text: interfaceToString(model.name).toUpperCase()
iconName: interfaceToIcon(model.name)
iconColor: app.guhAccent
disconnected: devicesSubProxyConnectables.count > 0
batteryCritical: devicesSubProxyBattery.count > 0
Column {
width: parent.width
anchors.centerIn: parent
anchors.verticalCenterOffset: -app.iconSize
spacing: app.margins
ColorIcon {
height: app.iconSize * 1.3
width: height
color: app.guhAccent
anchors.horizontalCenter: parent.horizontalCenter
name: interfaceToIcon(model.name)
}
Label {
text: interfaceToString(model.name).toUpperCase()
font.pixelSize: app.extraSmallFont
font.bold: true
font.letterSpacing: 1
width: parent.width
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
}
onClicked: {
var page;
switch (model.name) {
case "light":
page = "LightsDeviceListPage.qml"
break;
default:
page = "GenericDeviceListPage.qml"
}
MouseArea {
anchors.fill: parent
onClicked: {
var page;
switch (model.name) {
case "light":
page = "LightsDeviceListPage.qml"
break;
default:
page = "GenericDeviceListPage.qml"
}
if (model.name === "uncategorized") {
pageStack.push(Qt.resolvedUrl("../devicelistpages/" + page), {hiddenInterfaces: app.supportedInterfaces})
} else {
pageStack.push(Qt.resolvedUrl("../devicelistpages/" + page), {shownInterfaces: [model.name]})
}
}
}
DevicesProxy {
id: devicesProxy
devices: Engine.deviceManager.devices
shownInterfaces: [model.name]
if (model.name === "uncategorized") {
pageStack.push(Qt.resolvedUrl("../devicelistpages/" + page), {hiddenInterfaces: app.supportedInterfaces})
} else {
pageStack.push(Qt.resolvedUrl("../devicelistpages/" + page), {shownInterfaces: [model.name]})
}
}
Row {
id: quickAlertPane
anchors { top: parent.top; right: parent.right; margins: app.margins }
DevicesProxy {
id: devicesSubProxyConnectables
devices: devicesProxy
filterDisconnected: true
}
ColorIcon {
height: app.iconSize / 2
width: height
name: "../images/dialog-warning-symbolic.svg"
color: "red"
visible: devicesSubProxyConnectables.count > 0
}
DevicesProxy {
id: devicesSubProxyBattery
devices: devicesProxy
filterBatteryCritical: true
}
ColorIcon {
height: app.iconSize / 2
width: height
name: "../images/battery/battery-010.svg"
visible: devicesSubProxyBattery.count > 0
}
DevicesProxy {
id: devicesProxy
devices: Engine.deviceManager.devices
shownInterfaces: [model.name]
}
DevicesProxy {
id: devicesSubProxyConnectables
devices: devicesProxy
filterDisconnected: true
}
DevicesProxy {
id: devicesSubProxyBattery
devices: devicesProxy
filterBatteryCritical: true
}
Item {
id: inlineControlPane
anchors { left: parent.left; bottom: parent.bottom; right: parent.right; margins: app.margins / 2 }
height: app.iconSize + app.margins * 2
Rectangle {
anchors.fill: parent
// color: app.guhAccent
color: "black"
opacity: .05
contentItem: Loader {
id: inlineControlLoader
anchors {
fill: parent
leftMargin: app.margins / 2
rightMargin: app.margins / 2
}
Loader {
id: inlineControlLoader
anchors {
fill: parent
leftMargin: app.margins
rightMargin: app.margins
topMargin: app.margins / 2
bottomMargin: app.margins / 2
}
sourceComponent: {
switch (model.name) {
case "sensor":
case "weather":
return labelComponent;
sourceComponent: {
switch (model.name) {
case "sensor":
case "weather":
return labelComponent;
case "light":
case "media":
case "garagegate":
case "blind":
case "extendedblind":
case "shutter":
case "extendedshutter":
case "awning":
case "extendedawning":
return buttonComponent
default:
console.warn("DevicesPageDelegate, inlineControl: Unhandled interface", model.name)
}
case "light":
case "media":
case "garagegate":
case "blind":
case "extendedblind":
case "shutter":
case "extendedshutter":
case "awning":
case "extendedawning":
return buttonComponent
default:
console.warn("DevicesPageDelegate, inlineControl: Unhandled interface", model.name)
}
}
}
Component {
id: buttonComponent
MouseArea {
onClicked: {
switch (model.name) {
case "light":
if (devicesProxy.count == 1) {
var device = devicesProxy.get(0);
var deviceClass = Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId);
var stateType = deviceClass.stateTypes.findByName("power")
var actionType = deviceClass.actionTypes.findByName("power")
var params = [];
var param1 = {};
param1["paramTypeId"] = actionType.paramTypes.get(0).id;
param1["value"] = !device.states.getState(stateType.id).value;
params.push(param1)
Engine.deviceManager.executeAction(device.id, actionType.id, params)
} else {
ColumnLayout {
spacing: 0
Label {
id: label
Layout.fillWidth: true
text: {
switch (model.name) {
case "media":
return devicesProxy.get(0).name;
case "light":
var count = 0;
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)
var stateType = deviceClass.stateTypes.findByName("power")
if (device.states.getState(stateType.id).value === true) {
count++;
}
}
return count === 0 ? qsTr("All off") : qsTr("%1 on").arg(count)
case "garagegate":
var count = 0;
for (var i = 0; i < devicesProxy.count; i++) {
var device = devicesProxy.get(i);
var deviceClass = Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId);
var stateType = deviceClass.stateTypes.findByName("state");
if (device.states.getState(stateType.id).value !== "closed") {
count++;
}
}
return count === 0 ? qsTr("All closed") : qsTr("%1 open").arg(count)
case "blind":
case "extendedblind":
case "awning":
case "extendedawning":
case "shutter":
case "extendedshutter":
return qsTr("%1 installed").arg(devicesProxy.count)
}
break;
case "media":
var device = devicesProxy.get(0)
var deviceClass = Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId);
var stateType = deviceClass.stateTypes.findByName("playbackStatus");
var state = device.states.getState(stateType.id)
var actionName
switch (state.value) {
case "Playing":
actionName = "pause";
break;
case "Paused":
actionName = "play";
break;
}
var actionTypeId = deviceClass.actionTypes.findByName(actionName).id;
print("executing", device, device.id, actionTypeId, actionName, deviceClass.actionTypes)
Engine.deviceManager.executeAction(device.id, actionTypeId)
case "garagegate":
case "shutter":
case "extendedshutter":
case "blind":
case "extendedblind":
case "awning":
case "extendedawning":
case "simpleclosable":
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("close");
Engine.deviceManager.executeAction(device.id, actionType.id)
}
default:
console.warn("DevicesPageDelegate, inlineButtonControl clicked: Unhandled interface", model.name)
console.warn("DevicesPageDelegate, inlineButtonControl: Unhandled interface", model.name)
}
font.pixelSize: app.smallFont
elide: Text.ElideRight
}
ItemDelegate {
Layout.preferredHeight: app.iconSize
Layout.preferredWidth: height
Layout.alignment: Qt.AlignRight
ColumnLayout {
anchors.fill: parent
Label {
id: label
Layout.fillWidth: true
text: {
switch (model.name) {
case "media":
return devicesProxy.get(0).name;
case "light":
var count = 0;
for (var i = 0; i < devicesProxy.count; i++) {
var device = devicesProxy.get(i);
var deviceClass = Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId);
var stateType = deviceClass.stateTypes.findByName("power")
if (device.states.getState(stateType.id).value === true) {
count++;
}
}
return count === 0 ? qsTr("All off") : qsTr("%1 on").arg(count)
case "garagegate":
var count = 0;
for (var i = 0; i < devicesProxy.count; i++) {
var device = devicesProxy.get(i);
var deviceClass = Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId);
var stateType = deviceClass.stateTypes.findByName("state");
if (device.states.getState(stateType.id).value !== "closed") {
count++;
}
}
return count === 0 ? qsTr("All closed") : qsTr("%1 open").arg(count)
case "blind":
case "extendedblind":
case "awning":
case "extendedawning":
case "shutter":
case "extendedshutter":
return qsTr("%1 installed").arg(devicesProxy.count)
}
console.warn("DevicesPageDelegate, inlineButtonControl: Unhandled interface", model.name)
}
font.pixelSize: app.smallFont
elide: Text.ElideRight
}
ColorIcon {
id: icon
width: app.largeFont
width: app.iconSize
height: width
color: app.guhAccent
Layout.alignment: Qt.AlignRight
name: {
switch (model.name) {
case "media":
@ -281,13 +158,86 @@ Item {
}
}
}
onClicked: {
switch (model.name) {
case "light":
if (devicesProxy.count == 1) {
var device = devicesProxy.get(0);
var deviceClass = Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId);
var stateType = deviceClass.stateTypes.findByName("power")
var actionType = deviceClass.actionTypes.findByName("power")
var params = [];
var param1 = {};
param1["paramTypeId"] = actionType.paramTypes.get(0).id;
param1["value"] = !device.states.getState(stateType.id).value;
params.push(param1)
Engine.deviceManager.executeAction(device.id, actionType.id, params)
} else {
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)
}
}
break;
case "media":
var device = devicesProxy.get(0)
var deviceClass = Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId);
var stateType = deviceClass.stateTypes.findByName("playbackStatus");
var state = device.states.getState(stateType.id)
var actionName
switch (state.value) {
case "Playing":
actionName = "pause";
break;
case "Paused":
actionName = "play";
break;
}
var actionTypeId = deviceClass.actionTypes.findByName(actionName).id;
print("executing", device, device.id, actionTypeId, actionName, deviceClass.actionTypes)
Engine.deviceManager.executeAction(device.id, actionTypeId)
case "garagegate":
case "shutter":
case "extendedshutter":
case "blind":
case "extendedblind":
case "awning":
case "extendedawning":
case "simpleclosable":
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("close");
Engine.deviceManager.executeAction(device.id, actionType.id)
}
default:
console.warn("DevicesPageDelegate, inlineButtonControl clicked: Unhandled interface", model.name)
}
}
}
}
}
Component {
id: labelComponent
ColumnLayout {
spacing: 0
property var device: devicesProxy.get(0)
property var deviceClass: device ? Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId) : null
property var state: deviceClass ? device.states.getState(deviceClass.stateTypes.findByName("temperature").id) : null

View File

@ -8,6 +8,7 @@ import "../components"
Item {
id: root
property bool editMode: false
readonly property int count: tagsProxy.count
TagsProxyModel {
@ -22,48 +23,123 @@ Item {
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: favoritesDelegateComponent
delegate: MainPageTile {
id: delegateRoot
width: gridView.cellWidth
height: gridView.cellHeight
text: device.name.toUpperCase()
iconName: app.interfacesToIcon(deviceClass.interfaces)
iconColor: app.guhAccent
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: dndArea
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
property int index: gridView.indexAt(mouseX, mouseY) // Item underneath cursor
property var dndDelegate: null
property int dx
property int dy
onPressAndHold: {
//currentId = icons.get(newIndex = index).gridId
preventStealing = true;
onEntered: {
var index = gridView.indexAt(drag.x + dragArea.dragOffset.x, drag.y + dragArea.dragOffset.y);
from = index;
print("pressandHold on", index)
var tag = tagsProxy.get(index);
var originalDelegate = gridView.itemAt(mouseX, mouseY)
dndDelegate = favoritesDelegateComponent.createObject(dndArea, {deviceId: tag.deviceId, ruleId: tag.ruleId, x: originalDelegate.x, y: originalDelegate.y})
dx = mouseX - originalDelegate.x;
dy = mouseY - originalDelegate.y;
}
onReleased: {
preventStealing = false;
from = -1;
dndDelegate.destroy();
to = index;
}
onPositionChanged: {
if (dndDelegate) {
dndDelegate.x = mouseX - dx
dndDelegate.y = mouseY - dy
}
if (dndArea.from >= 0 && to != index && from != index) {
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++) {
@ -88,80 +164,248 @@ Item {
}
from = index;
}
// tagsProxy.move(newIndex, newIndex = index, 1)
}
}
}
Component {
id: favoritesDelegateComponent
Item {
id: delegateRoot
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
id: lightsComponent
RowLayout {
property var device: null
property var deviceClass: null
visible: index !== undefined && index !== dndArea.from
width: gridView.cellWidth
height: gridView.cellHeight
Pane {
id: pane
anchors.fill: parent
anchors.margins: app.margins / 2
Material.elevation: 1
ColumnLayout {
anchors.centerIn: parent
width: parent.width - app.margins * 2
spacing: app.margins
ColorIcon {
Layout.preferredWidth: app.iconSize * 1.3
Layout.preferredHeight: width
name: app.interfacesToIcon(delegateRoot.deviceClass.interfaces)
color: app.guhAccent
Layout.alignment: Qt.AlignHCenter
}
Label {
Layout.fillWidth: true
text: delegateRoot.device.name.toUpperCase()
font.pixelSize: app.extraSmallFont
font.bold: true
font.letterSpacing: 1
wrapMode: Text.WordWrap
horizontalAlignment: Text.AlignHCenter
}
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.guhAccent
}
}
Row {
id: quickAlertPane
anchors { top: parent.top; right: parent.right; margins: app.margins }
ColorIcon {
height: app.iconSize / 2
width: height
name: "../images/dialog-warning-symbolic.svg"
color: "red"
property var connectedState: delegateRoot.deviceClass.interfaces.indexOf("connectable") >= 0 ? delegateRoot.device.states.getState(delegateRoot.deviceClass.stateTypes.findByName("connected").id) : null
visible: connectedState !== null && connectedState.value === false
}
ColorIcon {
height: app.iconSize / 2
width: height
name: "../images/battery/battery-010.svg"
property var batteryCriticalState: delegateRoot.deviceClass.interfaces.indexOf("battery") >= 0 ? delegateRoot.device.states.getState(delegateRoot.deviceClass.stateTypes.findByName("batteryCritical").id) : null
visible: batteryCriticalState !== null && batteryCriticalState.value === true
}
}
MouseArea {
anchors.fill: parent
onClicked: {
pageStack.push(Qt.resolvedUrl("../devicepages/" + app.interfaceListToDevicePage(delegateRoot.deviceClass.interfaces)), {device: delegateRoot.device})
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.guhAccent
}
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("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.guhAccent
}
Label {
Layout.fillWidth: true
horizontalAlignment: Text.AlignRight
text: sensorsRoot.currentState.value// + " " + sensorsRoot.currentStateType.unitString
color: app.guhAccent
}
}
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.guhAccent
}
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.guhAccent
}
onClicked: {
var deviceClass = Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId);
var actionType = deviceClass.actionTypes.findByName("close");
Engine.deviceManager.executeAction(device.id, actionType.id);
}
}
}

View File

@ -25,13 +25,20 @@ Item {
}
cellWidth: width / tilesPerRow
cellHeight: cellWidth
delegate: Item {
id: scenesDelegate
delegate: MainPageTile {
width: interfacesGridView.cellWidth
height: interfacesGridView.cellHeight
iconName: iconTag ? "../images/" + iconTag.value + ".svg" : "../images/slideshow.svg";
fallbackIconName: "../images/slideshow.svg"
iconColor: colorTag ? colorTag.value : app.guhAccent;
text: model.name.toUpperCase()
property var colorTag: Engine.tagsManager.tags.findRuleTag(model.id, "color")
property var iconTag: Engine.tagsManager.tags.findRuleTag(model.id, "icon")
onClicked: Engine.ruleManager.executeActions(model.id)
Connections {
target: Engine.tagsManager.tags
onCountChanged: {
@ -39,51 +46,6 @@ Item {
iconTag = Engine.tagsManager.tags.findRuleTag(model.id, "icon")
}
}
Pane {
anchors.fill: parent
anchors.margins: app.margins / 2
Material.elevation: 1
padding: 0
ItemDelegate {
anchors.fill: parent
onClicked: {
Engine.ruleManager.executeActions(model.id)
}
contentItem: ColumnLayout {
width: parent.width
anchors.centerIn: parent
spacing: app.margins
ColorIcon {
Layout.preferredHeight: app.iconSize * 1.3
Layout.preferredWidth: height
Layout.alignment: Qt.AlignHCenter
name: scenesDelegate.iconTag ? "../images/" + scenesDelegate.iconTag.value + ".svg" : "../images/slideshow.svg";
color: scenesDelegate.colorTag ? scenesDelegate.colorTag.value : app.guhAccent;
ColorIcon {
anchors.fill: parent
name: "../images/slideshow.svg"
color: app.guhAccent
visible: parent.status === Image.Error
}
}
Label {
Layout.fillWidth: true
text: model.name.toUpperCase()
font.pixelSize: app.extraSmallFont
font.bold: true
font.letterSpacing: 1
wrapMode: Text.WordWrap
horizontalAlignment: Text.AlignHCenter
maximumLineCount: 2
elide: Text.ElideRight
}
}
}
}
}
}
}