Merge PR #471: Fixes and improvements for lights

This commit is contained in:
Jenkins nymea 2020-12-04 13:48:22 +01:00
commit cdfc63973c
19 changed files with 855 additions and 756 deletions

View File

@ -21,7 +21,7 @@
<file>ui/connection/wifisetup/BoxInfoPage.qml</file> <file>ui/connection/wifisetup/BoxInfoPage.qml</file>
<file>ui/components/NymeaHeader.qml</file> <file>ui/components/NymeaHeader.qml</file>
<file>ui/components/HeaderButton.qml</file> <file>ui/components/HeaderButton.qml</file>
<file>ui/components/ColorPicker.qml</file> <file>ui/components/ColorPickerPre510.qml</file>
<file>ui/components/ColorIcon.qml</file> <file>ui/components/ColorIcon.qml</file>
<file>ui/components/ThinDivider.qml</file> <file>ui/components/ThinDivider.qml</file>
<file>ui/components/ThrottledSlider.qml</file> <file>ui/components/ThrottledSlider.qml</file>
@ -232,5 +232,8 @@
<file>ui/components/NymeaItemDelegate.qml</file> <file>ui/components/NymeaItemDelegate.qml</file>
<file>ui/components/NymeaSwipeDelegate.qml</file> <file>ui/components/NymeaSwipeDelegate.qml</file>
<file>ui/customviews/GarageController.qml</file> <file>ui/customviews/GarageController.qml</file>
<file>ui/components/ColorPicker.qml</file>
<file>ui/utils/ActionQueue.qml</file>
<file>ui/components/ColorTemperaturePicker.qml</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@ -55,6 +55,9 @@ ApplicationWindow {
property int margins: 16 property int margins: 16
property int bigMargins: 20 property int bigMargins: 20
property int radius: 6
property int extraSmallFont: 10 property int extraSmallFont: 10
property int smallFont: 13 property int smallFont: 13
property int mediumFont: 16 property int mediumFont: 16

View File

@ -19,6 +19,37 @@ Item {
property alias bottomPadding: content.bottomPadding property alias bottomPadding: content.bottomPadding
signal clicked(); signal clicked();
signal pressAndHold();
function wobble() {
wobbleAnimation.start();
}
transform: Translate { id: wobbleTransform }
SequentialAnimation {
id: wobbleAnimation
PropertyAnimation {
target: wobbleTransform
property: "x"
from: 0
to: 10
duration: 50
easing.type: Easing.OutCirc
}
PropertyAnimation {
target: wobbleTransform
property: "x"
from: 10
to: 0
duration: 400
easing.type: Easing.OutElastic
easing.amplitude: 2
easing.period: 0.4
}
}
Rectangle { Rectangle {
id: background id: background
@ -64,6 +95,7 @@ Item {
Layout.fillWidth: true Layout.fillWidth: true
height: contentItem.implicitHeight height: contentItem.implicitHeight
onClicked: root.clicked() onClicked: root.clicked()
onPressAndHold: root.pressAndHold()
} }
} }
} }

View File

@ -28,89 +28,81 @@
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
import QtQuick 2.3 import QtQuick 2.9
import QtGraphicalEffects 1.0
import Nymea 1.0
import "../utils"
Item { Item {
id: root id: root
implicitWidth: orientation == Qt.Horizontal ? 300 : app.hugeIconSize
implicitHeight: orientation == Qt.Horizontal ? app.hugeIconSize : 300
property int brightness: min property Thing thing: null
property int min: 0
property int max: 100
property Component touchDelegate: Rectangle { height: root.height; width: 5; color: app.foregroundColor }
property bool active: true readonly property StateType colorTemperatureStateType: root.thing.thingClass.stateTypes.findByName("brightness")
property bool pressed: mouseArea.pressed
signal moved(real brightness); property int value: thing.stateByName("brightness").value
property int orientation: Qt.Horizontal
ActionQueue {
id: actionQueue
thing: root.thing
stateType: root.colorTemperatureStateType
}
Rectangle { Rectangle {
height: parent.width id: clipRect
width: parent.height anchors.fill: parent
anchors.centerIn: parent radius: app.radius
rotation: -90 color: Qt.tint(app.backgroundColor, Qt.rgba(app.foregroundColor.r, app.foregroundColor.g, app.foregroundColor.b, 0.1))
border.width: 1 }
border.color: app.foregroundColor
LinearGradient {
anchors.fill: parent
anchors.rightMargin: root.orientation == Qt.Horizontal ?
parent.width - (dragHandle.x + dragHandle.width / 2)
: 0
anchors.topMargin: root.orientation == Qt.Vertical ?
dragHandle.y + dragHandle.height / 2
: 0
start: root.orientation == Qt.Horizontal ? Qt.point(0,0) : Qt.point(0, height)
end: root.orientation == Qt.Horizontal ? Qt.point(width, 0) : Qt.point(0, 0)
source: clipRect
gradient: Gradient { gradient: Gradient {
GradientStop { position: 0.0; color: Qt.rgba(0, 0, 0, .5) } GradientStop { position: 0.0; color: "transparent" }
GradientStop { position: 1.0; color: Qt.rgba(1, 1, 1, .5) } GradientStop { position: 1.0; color: "#55ffffff" }
} }
} }
Loader { Rectangle {
id: touchDelegateLoader id: dragHandle
// 0 : width = min : max x: root.orientation === Qt.Horizontal ?
// x = (width * (brightness - min) / (max-min)) (actionQueue.pendingValue || root.value) * (root.width - dragHandle.width) / 100
property int position: (root.width * (root.brightness - root.min) / (root.max - root.min)); : 0
x: item ? Math.max(0, Math.min(position - width * .5, parent.width - item.width)) : 0 y: root.orientation === Qt.Vertical ?
sourceComponent: root.touchDelegate root.height - dragHandle.height - ((actionQueue.pendingValue || root.value) * (root.height - dragHandle.height) / 100)
visible: !mouseArea.pressed && root.active : 0
Behavior on x { height: root.orientation === Qt.Horizontal ? parent.height : 8
enabled: !mouseArea.pressed width: root.orientation === Qt.Horizontal ? 8 : parent.width
NumberAnimation {} radius: 4
} color: app.foregroundColor
} }
MouseArea { MouseArea {
id: mouseArea
anchors.fill: parent 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: { onPositionChanged: {
root.brightness = Math.min(root.max, Math.max(root.min, (mouseX * (root.max - root.min) / width) + root.min)) var minCt = root.colorTemperatureStateType.minValue;
var maxCt = root.colorTemperatureStateType.maxValue
var currentTime = new Date(); var ct;
if (pressed && currentTime - lastSentTime > 200) { if (root.orientation == Qt.Horizontal) {
root.moved(root.brightness) ct = Math.min(maxCt, Math.max(minCt, (mouseX * (maxCt - minCt) / (width - dragHandle.width)) + minCt))
lastSentTime = currentTime } else {
ct = Math.min(maxCt, Math.max(minCt, ((height - mouseY) * (maxCt - minCt) / (height - dragHandle.height)) + minCt))
} }
actionQueue.sendValue(ct);
} }
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

@ -1,249 +1,126 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * import QtQuick 2.9
* import QtGraphicalEffects 1.0
* Copyright 2013 - 2020, nymea GmbH import Nymea 1.0
* Contact: contact@nymea.io import "../utils"
*
* This file is part of nymea.
* This project including source code and documentation is protected by
* copyright law, and remains the property of nymea GmbH. All rights, including
* reproduction, publication, editing and translation, are reserved. The use of
* this project is subject to the terms of a license agreement to be concluded
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
* under https://nymea.io/license
*
* GNU General Public License Usage
* Alternatively, this project may be redistributed and/or modified under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, GNU version 3. This project is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this project. If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under
* contact@nymea.io or see our FAQ/Licensing Information on
* https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
import QtQuick 2.5
Item { Item {
id: root id: root
property color color: actionState property Thing thing: null
property bool pressed: mouseArea.pressed
property bool hovered: mouseArea.containsMouse
property bool active: true ActionQueue {
id: actionQueue
property Component touchDelegate: Rectangle { thing: root.thing
height: 15 stateType: thing.thingClass.stateTypes.findByName("color")
width: height
radius: height / 2
color: app.accentColor
Rectangle {
color: root.hovered || root.pressed ? "#11000000" : "transparent"
anchors.centerIn: parent
height: 30
width: height
radius: width / 2
Behavior on color { ColorAnimation { duration: 200 } }
}
} }
function calculateXy(color) { ConicalGradient {
if (!color.hasOwnProperty("r")) { id: gradient
// Qt 4.8's color doesn't have r,g,b properties
var colorString = color.toString();
color = new Object;
color.r = 1.0 * parseInt("0x" + colorString.substring(1,3), 16) / 256;
color.g = 1.0 * parseInt("0x" + colorString.substring(3,5), 16) / 256;
color.b = 1.0 * parseInt("0x" + colorString.substring(5,7), 16) / 256;
}
var point = new Object;
var brightness = Math.min(color.r, color.g, color.b);
point.y = Math.round(root.height * brightness);
var newColor = new Object;
newColor.r = color.r - brightness;
newColor.g = color.g - brightness;
newColor.b = color.b - brightness;
var sectionWidth = root.width / 6;
var sections = [true, true, true];
if (newColor.r > 0) {
sections[1] = false;
}
if (newColor.g > 0) {
sections[2] = false;
}
if (newColor.b > 0) {
sections[0] = false;
}
if (sections[0]) {
if (newColor.r > newColor.g) {
point.x = sectionWidth * newColor.g;
} else if (newColor.r == newColor.g) {
point.x = sectionWidth
} else {
point.x = sectionWidth * 2 - newColor.r * sectionWidth;
}
} else if (sections[1]) {
if (newColor.g > newColor.b) {
point.x = sectionWidth * 2 + sectionWidth * newColor.b;
} else if (newColor.g == newColor.b) {
point.x = sectionWidth * 3;
} else {
point.x = sectionWidth * 4 - newColor.g * sectionWidth
}
} else {
if (newColor.b > newColor.r) {
point.x = sectionWidth * 4 + sectionWidth * newColor.r
} else if (newColor.b == newColor.r) {
point.x = sectionWidth * 5;
} else {
point.x = sectionWidth * 6 - newColor.b * sectionWidth;
}
}
return point;
}
function calculateColor(x, y) {
x = Math.min(Math.max(0, x), width - 1);
y = Math.min(Math.max(0, y), height - 1);
var color = root.color;
var sectionWidth = root.width / 6;
var section = Math.floor(x / sectionWidth)
var sectionX = Math.floor(x % (sectionWidth - 0.00001)) // the - 0.00001 is to prevent a mismatch when rounding
// sectionVal : 1.0 = sectionX : sectionWidth
var sectionVal = (1.0 * sectionX / sectionWidth)
// brightnessVal : 1.0 = mouseY : height
var brightness = 1.0 * y / height
switch (section) {
case 0:
// GradientStop { position: 0.0; color: "#ff0000" }
color = Qt.rgba(1, sectionVal + brightness, brightness, 1)
break;
case 1:
// GradientStop { position: 0.17; color: "#ffff00" }
color = Qt.rgba(1 - sectionVal + brightness, 1, brightness, 1)
break;
case 2:
// GradientStop { position: 0.33; color: "#00ff00" }
color = Qt.rgba(brightness, 1, sectionVal + brightness, 1)
break;
case 3:
// GradientStop { position: 0.5; color: "#00ffff" }
color = Qt.rgba(brightness, 1 - sectionVal + brightness, 1, 1)
break;
case 4:
// GradientStop { position: 0.66; color: "#0000ff" }
color = Qt.rgba(sectionVal + brightness, brightness, 1, 1)
break;
case 5:
// GradientStop { position: 0.83; color: "#ff00ff" }
color = Qt.rgba(1, brightness, 1 - sectionVal + brightness, 1)
break;
}
// print("got color", color.r, color.g, color.b)
return color
}
Rectangle {
height: parent.width
width: parent.height
anchors.centerIn: parent anchors.centerIn: parent
rotation: -90 width: Math.min(parent.width, parent.height)
height: width
gradient: Gradient { visible: false
GradientStop { position: 0.0; color: "#ff0000" } gradient: Gradient{
GradientStop { position: 0.17; color: "#ffff00" } id: g
GradientStop { position: 0.33; color: "#00ff00" } GradientStop { position: 0.000; color: Qt.rgba(1, 0, 0, 1) }
GradientStop { position: 0.5; color: "#00ffff" } GradientStop { position: 0.167; color: Qt.rgba(1, 1, 0, 1) }
GradientStop { position: 0.66; color: "#0000ff" } GradientStop { position: 0.333; color: Qt.rgba(0, 1, 0, 1) }
GradientStop { position: 0.83; color: "#ff00ff" } GradientStop { position: 0.500; color: Qt.rgba(0, 1, 1, 1) }
GradientStop { position: 1.0; color: "#ff0000" } GradientStop { position: 0.667; color: Qt.rgba(0, 0, 1, 1) }
GradientStop { position: 0.833; color: Qt.rgba(1, 0, 1, 1) }
GradientStop { position: 1.000; color: Qt.rgba(1, 0, 0, 1) }
} }
} }
Rectangle { Rectangle {
anchors.fill: parent id: mask
border.color: app.foregroundColor anchors.fill: gradient
border.width: 1 radius: width / 2
gradient: Gradient { }
GradientStop { position: 0.0; color: "transparent" } OpacityMask {
GradientStop { position: 1.0; color: "white" } anchors.fill: gradient
source: gradient
maskSource: mask
}
RadialGradient {
anchors.fill: gradient
gradient: Gradient{
GradientStop { position: 0.05; color: Qt.rgba(1, 1, 1, 1) }
GradientStop { position: 0.10; color: Qt.rgba(1, 1, 1, .9) }
GradientStop { position: 0.20; color: Qt.rgba(1, 1, 1, .7) }
GradientStop { position: 0.30; color: Qt.rgba(1, 1, 1, .5) }
GradientStop { position: 0.40; color: Qt.rgba(1, 1, 1, .3) }
GradientStop { position: 0.50; color: "transparent" }
} }
} }
MouseArea { MouseArea {
id: mouseArea id: mouseArea
anchors.fill: parent anchors.fill: parent
preventStealing: true
hoverEnabled: true
drag.minimumX: 0
drag.maximumX: width - dndItem.width
drag.minimumY: 0
drag.maximumY: height - dndItem.height
property variant draggedItem
property variant draggedLight
onPressed: {
mouseArea.drag.target = dndItem;
dndItem.x = Math.min(width - dndItem.width, Math.max(0, mouseX - dndItem.width / 2))
dndItem.y = Math.min(height - dndItem.height, Math.max(0, mouseY - dndItem.height / 2))
mouseArea.draggedItem = touchDelegateLoader;
}
onPositionChanged: { onPositionChanged: {
if (mouseArea.draggedItem) {
root.color = root.calculateColor(mouseX, mouseY); var angle = calculateAngle(mouseX, mouseY)
if (mouseArea.draggedLight) { var position = angle / 360;
mouseArea.draggedLight.color = root.calculateColor(mouseX, mouseY);
var stopBefore = null;
var stopAfter = null;
for (var i = 0; i < g.stops.length; i++) {
var stop = g.stops[i];
if (stop.position < position) {
stopBefore = stop;
continue
} }
stopAfter = stop;
break;
} }
var colorBefore = stopBefore.color
var colorAfter = stopAfter.color
// p : 1 = pis : (a - b)
var positionInStop = (position - stopBefore.position) / (stopAfter.position - stopBefore.position);
var dr = stopAfter.color.r - stopBefore.color.r;
var dg = stopAfter.color.g - stopBefore.color.g;
var db = stopAfter.color.b - stopBefore.color.b;
var distanceFromCenter = calculateDistance(mouseX, mouseY)
// Reduce width a bit to keep outside circle for full color intensity
var positionFromCenter = Math.min(distanceFromCenter / (width * 0.9 / 2), 1)
// Invert it, The further we're away, the less impact this should have
positionFromCenter = 1 - positionFromCenter;
print("pos", positionFromCenter)
var color = Qt.rgba((stopBefore.color.r + dr * positionInStop) + positionFromCenter,
(stopBefore.color.g + dg * positionInStop) + positionFromCenter,
(stopBefore.color.b + db * positionInStop) + positionFromCenter,
1)
actionQueue.sendValue(color);
} }
onReleased: { function calculateAngle(mouseX, mouseY) {
if (mouseArea.draggedItem) { // transform coords to center of dial
root.color = root.calculateColor(mouseX, mouseY); mouseX -= mouseArea.width / 2
if (mouseArea.draggedLight) { mouseY -= mouseArea.height / 2
mouseArea.draggedLight.color = root.calculateColor(mouseX, mouseY);
}
}
mouseArea.draggedItem = undefined;
mouseArea.draggedLight = undefined;
mouseArea.drag.target = undefined;
var rad = Math.atan(mouseY / mouseX);
var angle = rad * 180 / Math.PI
angle += 90;
if (mouseX < 0 && mouseY >= 0) angle = 180 + angle;
if (mouseX < 0 && mouseY < 0) angle = 180 + angle;
return angle;
} }
} function calculateDistance(mouseX, mouseY) {
mouseX -= mouseArea.width / 2
mouseY -= mouseArea.height / 2
Loader { return Math.abs(Math.sqrt(Math.pow(mouseX, 2) + Math.pow(mouseY, 2)))
id: touchDelegateLoader }
property variant point: calculateXy(root.color);
x: item ? Math.max(0, Math.min(point.x - width * .5, parent.width - item.width)) : 0
y: item ? Math.max(0, Math.min(point.y - height * .5, parent.height - item.height)) : 0
sourceComponent: root.touchDelegate
visible: mouseArea.draggedItem !== touchDelegateLoader && root.active
// Behavior on x {
// enabled: !mouseArea.pressed
// NumberAnimation {}
// }
}
Loader {
id: dndItem
sourceComponent: root.touchDelegate
visible: mouseArea.draggedItem !== undefined && root.active
} }
} }

View File

@ -102,5 +102,4 @@ Item {
sourceComponent: root.touchDelegate sourceComponent: root.touchDelegate
visible: mouseArea.pressed && root.active visible: mouseArea.pressed && root.active
} }
} }

View File

@ -0,0 +1,249 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea.
* This project including source code and documentation is protected by
* copyright law, and remains the property of nymea GmbH. All rights, including
* reproduction, publication, editing and translation, are reserved. The use of
* this project is subject to the terms of a license agreement to be concluded
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
* under https://nymea.io/license
*
* GNU General Public License Usage
* Alternatively, this project may be redistributed and/or modified under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, GNU version 3. This project is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this project. If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under
* contact@nymea.io or see our FAQ/Licensing Information on
* https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
import QtQuick 2.5
Item {
id: root
property color color: actionState
property bool pressed: mouseArea.pressed
property bool hovered: mouseArea.containsMouse
property bool active: true
property Component touchDelegate: Rectangle {
height: 15
width: height
radius: height / 2
color: app.accentColor
Rectangle {
color: root.hovered || root.pressed ? "#11000000" : "transparent"
anchors.centerIn: parent
height: 30
width: height
radius: width / 2
Behavior on color { ColorAnimation { duration: 200 } }
}
}
function calculateXy(color) {
if (!color.hasOwnProperty("r")) {
// Qt 4.8's color doesn't have r,g,b properties
var colorString = color.toString();
color = new Object;
color.r = 1.0 * parseInt("0x" + colorString.substring(1,3), 16) / 256;
color.g = 1.0 * parseInt("0x" + colorString.substring(3,5), 16) / 256;
color.b = 1.0 * parseInt("0x" + colorString.substring(5,7), 16) / 256;
}
var point = new Object;
var brightness = Math.min(color.r, color.g, color.b);
point.y = Math.round(root.height * brightness);
var newColor = new Object;
newColor.r = color.r - brightness;
newColor.g = color.g - brightness;
newColor.b = color.b - brightness;
var sectionWidth = root.width / 6;
var sections = [true, true, true];
if (newColor.r > 0) {
sections[1] = false;
}
if (newColor.g > 0) {
sections[2] = false;
}
if (newColor.b > 0) {
sections[0] = false;
}
if (sections[0]) {
if (newColor.r > newColor.g) {
point.x = sectionWidth * newColor.g;
} else if (newColor.r == newColor.g) {
point.x = sectionWidth
} else {
point.x = sectionWidth * 2 - newColor.r * sectionWidth;
}
} else if (sections[1]) {
if (newColor.g > newColor.b) {
point.x = sectionWidth * 2 + sectionWidth * newColor.b;
} else if (newColor.g == newColor.b) {
point.x = sectionWidth * 3;
} else {
point.x = sectionWidth * 4 - newColor.g * sectionWidth
}
} else {
if (newColor.b > newColor.r) {
point.x = sectionWidth * 4 + sectionWidth * newColor.r
} else if (newColor.b == newColor.r) {
point.x = sectionWidth * 5;
} else {
point.x = sectionWidth * 6 - newColor.b * sectionWidth;
}
}
return point;
}
function calculateColor(x, y) {
x = Math.min(Math.max(0, x), width - 1);
y = Math.min(Math.max(0, y), height - 1);
var color = root.color;
var sectionWidth = root.width / 6;
var section = Math.floor(x / sectionWidth)
var sectionX = Math.floor(x % (sectionWidth - 0.00001)) // the - 0.00001 is to prevent a mismatch when rounding
// sectionVal : 1.0 = sectionX : sectionWidth
var sectionVal = (1.0 * sectionX / sectionWidth)
// brightnessVal : 1.0 = mouseY : height
var brightness = 1.0 * y / height
switch (section) {
case 0:
// GradientStop { position: 0.0; color: "#ff0000" }
color = Qt.rgba(1, sectionVal + brightness, brightness, 1)
break;
case 1:
// GradientStop { position: 0.17; color: "#ffff00" }
color = Qt.rgba(1 - sectionVal + brightness, 1, brightness, 1)
break;
case 2:
// GradientStop { position: 0.33; color: "#00ff00" }
color = Qt.rgba(brightness, 1, sectionVal + brightness, 1)
break;
case 3:
// GradientStop { position: 0.5; color: "#00ffff" }
color = Qt.rgba(brightness, 1 - sectionVal + brightness, 1, 1)
break;
case 4:
// GradientStop { position: 0.66; color: "#0000ff" }
color = Qt.rgba(sectionVal + brightness, brightness, 1, 1)
break;
case 5:
// GradientStop { position: 0.83; color: "#ff00ff" }
color = Qt.rgba(1, brightness, 1 - sectionVal + brightness, 1)
break;
}
// print("got color", color.r, color.g, color.b)
return color
}
Rectangle {
height: parent.width
width: parent.height
anchors.centerIn: parent
rotation: -90
gradient: Gradient {
GradientStop { position: 0.0; color: "#ff0000" }
GradientStop { position: 0.17; color: "#ffff00" }
GradientStop { position: 0.33; color: "#00ff00" }
GradientStop { position: 0.5; color: "#00ffff" }
GradientStop { position: 0.66; color: "#0000ff" }
GradientStop { position: 0.83; color: "#ff00ff" }
GradientStop { position: 1.0; color: "#ff0000" }
}
}
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" }
}
}
MouseArea {
id: mouseArea
anchors.fill: parent
preventStealing: true
hoverEnabled: true
drag.minimumX: 0
drag.maximumX: width - dndItem.width
drag.minimumY: 0
drag.maximumY: height - dndItem.height
property variant draggedItem
property variant draggedLight
onPressed: {
mouseArea.drag.target = dndItem;
dndItem.x = Math.min(width - dndItem.width, Math.max(0, mouseX - dndItem.width / 2))
dndItem.y = Math.min(height - dndItem.height, Math.max(0, mouseY - dndItem.height / 2))
mouseArea.draggedItem = touchDelegateLoader;
}
onPositionChanged: {
if (mouseArea.draggedItem) {
root.color = root.calculateColor(mouseX, mouseY);
if (mouseArea.draggedLight) {
mouseArea.draggedLight.color = root.calculateColor(mouseX, mouseY);
}
}
}
onReleased: {
if (mouseArea.draggedItem) {
root.color = root.calculateColor(mouseX, mouseY);
if (mouseArea.draggedLight) {
mouseArea.draggedLight.color = root.calculateColor(mouseX, mouseY);
}
}
mouseArea.draggedItem = undefined;
mouseArea.draggedLight = undefined;
mouseArea.drag.target = undefined;
}
}
Loader {
id: touchDelegateLoader
property variant point: calculateXy(root.color);
x: item ? Math.max(0, Math.min(point.x - width * .5, parent.width - item.width)) : 0
y: item ? Math.max(0, Math.min(point.y - height * .5, parent.height - item.height)) : 0
sourceComponent: root.touchDelegate
visible: mouseArea.draggedItem !== touchDelegateLoader && root.active
// Behavior on x {
// enabled: !mouseArea.pressed
// NumberAnimation {}
// }
}
Loader {
id: dndItem
sourceComponent: root.touchDelegate
visible: mouseArea.draggedItem !== undefined && root.active
}
}

View File

@ -0,0 +1,69 @@
import QtQuick 2.9
import QtGraphicalEffects 1.0
import Nymea 1.0
import "../utils"
Item {
id: root
implicitWidth: orientation == Qt.Horizontal ? 300 : app.hugeIconSize
implicitHeight: orientation == Qt.Horizontal ? app.hugeIconSize : 300
property Thing thing: null
property int orientation: Qt.Horizontal
readonly property StateType colorTemperatureStateType: root.thing.thingClass.stateTypes.findByName("colorTemperature")
property int value: thing.stateByName("colorTemperature").value
ActionQueue {
id: actionQueue
thing: root.thing
stateType: root.colorTemperatureStateType
}
Rectangle {
id: clipRect
anchors.fill: parent
radius: app.radius
}
LinearGradient {
anchors.fill: parent
start: root.orientation == Qt.Horizontal ? Qt.point(0, 0) : Qt.point(0, height)
end: root.orientation == Qt.Horizontal ? Qt.point(width, 0) : Qt.point(0, 0)
source: clipRect
gradient: Gradient {
GradientStop { position: 0.0; color: "#dfffff" }
GradientStop { position: 0.5; color: "#ffffea" }
GradientStop { position: 1.0; color: "#ffd649" }
}
}
Rectangle {
id: dragHandle
property double valuePercentage: ((actionQueue.pendingValue || root.value) - root.colorTemperatureStateType.minValue) / (root.colorTemperatureStateType.maxValue - root.colorTemperatureStateType.minValue)
x: orientation == Qt.Horizontal ? valuePercentage * (root.width - dragHandle.width) : 0
y: root.orientation === Qt.Vertical ? root.height - dragHandle.height - (valuePercentage * (root.height - dragHandle.height)) : 0
height: root.orientation == Qt.Horizontal ? parent.height : 8
width: root.orientation == Qt.Horizontal ? 8 : parent.width
radius: 4
color: Qt.tint(app.backgroundColor, Qt.rgba(app.foregroundColor.r, app.foregroundColor.g, app.foregroundColor.b, 0.5))
}
MouseArea {
anchors.fill: parent
onPositionChanged: {
var minCt = root.colorTemperatureStateType.minValue;
var maxCt = root.colorTemperatureStateType.maxValue
var ct;
if (root.orientation == Qt.Horizontal) {
ct = Math.min(maxCt, Math.max(minCt, (mouseX * (maxCt - minCt) / (width - dragHandle.width)) + minCt))
} else {
ct = Math.min(maxCt, Math.max(minCt, ((height - mouseY) * (maxCt - minCt) / (height - dragHandle.height)) + minCt))
}
actionQueue.sendValue(ct);
}
}
}

View File

@ -280,7 +280,7 @@ ItemDelegate {
Component { Component {
id: colorPickerComponent id: colorPickerComponent
ColorPicker { ColorPickerPre510 {
id: colorPicker id: colorPicker
implicitHeight: 200 implicitHeight: 200
// color: root.param.value // color: root.param.value

View File

@ -81,7 +81,7 @@ Item {
padding: app.margins padding: app.margins
property var colorValue property var colorValue
property int preferredY: 0 property int preferredY: 0
contentItem: ColorPicker { contentItem: ColorPickerPre510 {
color: colorPickerDialog.colorValue color: colorPickerDialog.colorValue
property var lastSentTime: new Date() property var lastSentTime: new Date()
onColorChanged: { onColorChanged: {

View File

@ -29,12 +29,13 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
import QtQuick 2.5 import QtQuick 2.5
import QtQuick.Controls 2.1 import QtQuick.Controls 2.2
import QtQuick.Controls.Material 2.1 import QtQuick.Controls.Material 2.2
import QtQuick.Layouts 1.1 import QtQuick.Layouts 1.1
import QtGraphicalEffects 1.0 import QtGraphicalEffects 1.0
import Nymea 1.0 import Nymea 1.0
import "../components" import "../components"
import "../utils"
DeviceListPageBase { DeviceListPageBase {
id: root id: root
@ -95,50 +96,37 @@ DeviceListPageBase {
bottomPadding: 0 bottomPadding: 0
leftPadding: 0 leftPadding: 0
rightPadding: 0 rightPadding: 0
enabled: connectedState == null || connectedState.value === true
property State connectedState: thing.stateByName("connected") property State connectedState: thing.stateByName("connected")
property State powerState: thing.stateByName("power") property State powerState: thing.stateByName("power")
property State brightnessState: thing.stateByName("brightness") property State brightnessState: thing.stateByName("brightness")
property State colorState: thing.stateByName("color") property State colorState: thing.stateByName("color")
onClicked: root.enterPage(index) property bool tileColored: enabled && colorState && powerState.value === true
property bool colorInverted: tileColored && NymeaUtils.isDark(app.foregroundColor) === NymeaUtils.isDark(colorState.value)
property bool isConnected: connectedState && connectedState.value === true
property int pendingCommand: -1
property var pendingValue: null
function adjustBrightness(value) { onClicked: {
if (pendingCommand != -1) { if (isConnected) {
// busy, cache value root.enterPage(index)
pendingValue = value; } else {
return; itemDelegate.wobble()
} }
pendingCommand = engine.thingManager.executeAction(itemDelegate.thing.id,
itemDelegate.brightnessState.stateTypeId,
[{
paramTypeId: itemDelegate.brightnessState.stateTypeId,
value: value
}])
pendingValue = null;
} }
Connections { ActionQueue {
target: engine.thingManager id: actionQueue
onExecuteActionReply: { thing: itemDelegate.thing
if (itemDelegate.pendingCommand == commandId) { stateType: thing.thingClass.stateTypes.findByName("brightness")
itemDelegate.pendingCommand = -1;
if (itemDelegate.pendingValue != null) {
itemDelegate.adjustBrightness(pendingValue)
}
}
}
} }
contentItem: Rectangle { contentItem: Rectangle {
color: itemDelegate.powerState.value === true && itemDelegate.colorState ? itemDelegate.colorState.value : "#00000000" color: enabled && itemDelegate.powerState.value === true && itemDelegate.colorState ? itemDelegate.colorState.value : "#00000000"
implicitHeight: contentColumn.implicitHeight implicitHeight: contentColumn.implicitHeight
Behavior on implicitHeight { NumberAnimation { duration: 100 } } Behavior on implicitHeight { NumberAnimation { duration: 100 } }
radius: 6 radius: 6
enabled: itemDelegate.connectedState == null || connectedState.value === true
ColumnLayout { ColumnLayout {
id: contentColumn id: contentColumn
@ -150,10 +138,17 @@ DeviceListPageBase {
spacing: app.margins spacing: app.margins
ColorIcon { ColorIcon {
id: lightIcon
Layout.preferredHeight: app.iconSize Layout.preferredHeight: app.iconSize
Layout.preferredWidth: app.iconSize Layout.preferredWidth: app.iconSize
name: itemDelegate.powerState.value === true ? "../images/light-on.svg" : "../images/light-off.svg" name: itemDelegate.powerState.value === true ? "../images/light-on.svg" : "../images/light-off.svg"
color: itemDelegate.powerState.value === true ? app.accentColor : keyColor color: itemDelegate.powerState.value === true ? app.accentColor : keyColor
Binding {
target: lightIcon
property: "color"
value: itemDelegate.colorInverted ? app.backgroundColor : app.foregroundColor
when: itemDelegate.tileColored
}
} }
Label { Label {
@ -165,9 +160,8 @@ DeviceListPageBase {
Binding { Binding {
target: nameLabel target: nameLabel
property: "color" property: "color"
value: itemDelegate.colorState && NymeaUtils.isDark(app.foregroundColor) === NymeaUtils.isDark(itemDelegate.colorState.value) ? value: itemDelegate.colorInverted ? app.backgroundColor : app.foregroundColor
app.backgroundColor : app.foregroundColor when: itemDelegate.tileColored
when: nameLabel.enabled && itemDelegate.colorState !== null && itemDelegate.powerState.value === true
} }
} }
@ -176,6 +170,7 @@ DeviceListPageBase {
} }
Switch { Switch {
id: lightSwitch
checked: itemDelegate.powerState.value === true checked: itemDelegate.powerState.value === true
onClicked: { onClicked: {
var params = []; var params = [];
@ -186,6 +181,76 @@ DeviceListPageBase {
print("executing for thing:", itemDelegate.thing.id) print("executing for thing:", itemDelegate.thing.id)
engine.deviceManager.executeAction(itemDelegate.thing.id, itemDelegate.powerState.stateTypeId, params) engine.deviceManager.executeAction(itemDelegate.thing.id, itemDelegate.powerState.stateTypeId, params)
} }
indicator: Item {
id: indicator
implicitWidth: 38
implicitHeight: 32
x: lightSwitch.leftPadding + (lightSwitch.availableWidth - width) / 2
y: lightSwitch.topPadding + (lightSwitch.availableHeight - height) / 2
property Item control
property alias handle: handle
Material.elevation: 1
Rectangle {
id: indicatorBackground
width: parent.width
height: 14
radius: height / 2
y: parent.height / 2 - height / 2
color: lightSwitch.enabled ?
(lightSwitch.checked ? lightSwitch.Material.switchCheckedTrackColor : lightSwitch.Material.switchUncheckedTrackColor)
: lightSwitch.Material.switchDisabledTrackColor
Binding {
target: indicatorBackground
property: "color"
value: "#808080"
when: itemDelegate.tileColored
}
}
Rectangle {
id: handle
x: Math.max(0, Math.min(parent.width - width, lightSwitch.visualPosition * parent.width - (width / 2)))
y: (parent.height - height) / 2
width: 20
height: 20
radius: width / 2
color: lightSwitch.enabled ? (lightSwitch.checked ? lightSwitch.Material.switchCheckedHandleColor : lightSwitch.Material.switchUncheckedHandleColor)
: lightSwitch.Material.switchDisabledHandleColor
Binding {
target: handle
property: "color"
value: "#f0f0f0"
when: itemDelegate.tileColored
}
Behavior on x {
enabled: !lightSwitch.pressed
SmoothedAnimation {
duration: 300
}
}
// layer.enabled: indicator.Material.elevation > 0
// layer.effect: ElevationEffect {
// elevation: indicator.Material.elevation
// }
}
DropShadow {
anchors.fill: handle
horizontalOffset: 1
verticalOffset: 1
radius: 4.0
samples: 17
color: "#80000000"
source: handle
}
}
} }
} }
@ -196,21 +261,45 @@ DeviceListPageBase {
radius: 6 radius: 6
color: Qt.tint(app.backgroundColor, Qt.rgba(app.foregroundColor.r, app.foregroundColor.g, app.foregroundColor.b, .1)) color: Qt.tint(app.backgroundColor, Qt.rgba(app.foregroundColor.r, app.foregroundColor.g, app.foregroundColor.b, .1))
Rectangle {
height: knob.x + knob.width / 2
width: parent.height
anchors.centerIn: parent
anchors.horizontalCenterOffset: -(parent.width - height) / 2
rotation: -90
gradient: Gradient {
GradientStop { position: 0; color: "transparent" }
GradientStop { position: 1; color: "#55ffffff" }
}
}
Rectangle { Rectangle {
id: knob id: knob
height: 12 height: 14
width: 12 width: 14
radius: 8 radius: 8
color: app.accentColor color: "#f0f0f0"
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
x: itemDelegate.brightnessState ? itemDelegate.brightnessState.value * (parent.width - width) / 100 : 0 x: itemDelegate.brightnessState ?
(actionQueue.queuedValue || actionQueue.pendingValue || itemDelegate.brightnessState.value) * (parent.width - width) / 100
: 0
}
DropShadow {
anchors.fill: knob
horizontalOffset: 1
verticalOffset: 1
radius: 4.0
samples: 17
color: "#80000000"
source: knob
} }
MouseArea { MouseArea {
id: brightnessMouseArea
anchors.fill: parent anchors.fill: parent
preventStealing: true preventStealing: true
onMouseXChanged: { onMouseXChanged: {
itemDelegate.adjustBrightness(Math.max(1, Math.min(100, mouseX / width * 100))) actionQueue.sendValue(Math.max(1, Math.min(100, mouseX / width * 100)))
} }
} }
} }

View File

@ -239,7 +239,7 @@ DevicePageBase {
} }
property int pendingActionId: -1 property int pendingActionId: -1
property real valueCache: 0 property var valueCache: 0
property bool valueCacheDirty: false property bool valueCacheDirty: false
function enqueueSetValue(value) { function enqueueSetValue(value) {

View File

@ -28,11 +28,12 @@
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
import QtQuick 2.5 import QtQuick 2.9
import QtQuick.Controls 2.1 import QtQuick.Controls 2.1
import QtQuick.Layouts 1.1 import QtQuick.Layouts 1.1
import QtQuick.Controls.Material 2.1 import QtQuick.Controls.Material 2.1
import Nymea 1.0 import Nymea 1.0
import QtGraphicalEffects 1.0
import "../components" import "../components"
DevicePageBase { DevicePageBase {
@ -54,279 +55,139 @@ DevicePageBase {
readonly property var ctState: ctStateType ? device.states.getState(ctStateType.id) : null readonly property var ctState: ctStateType ? device.states.getState(ctStateType.id) : null
readonly property var ctActionType: deviceClass.actionTypes.findByName("colorTemperature") readonly property var ctActionType: deviceClass.actionTypes.findByName("colorTemperature")
readonly property int statesCount: (powerState !== null ? 1 : 0) +
(brightnessState !== null ? 1 : 0) +
(ctState !== null ? 1 : 0) +
(colorState !== null ? 1 : 0)
GridLayout { GridLayout {
anchors.fill: parent anchors.fill: parent
anchors.margins: app.margins anchors.margins: app.margins
columns: app.landscape ? 2 : 1 columns: app.landscape ? root.statesCount : 1
rowSpacing: app.margins rowSpacing: app.margins
columnSpacing: app.margins columnSpacing: app.margins
Layout.alignment: Qt.AlignCenter Layout.alignment: Qt.AlignCenter
Dial { GridLayout {
Layout.minimumWidth: app.landscape ? parent.width / 3 :app.iconSize * 4
Layout.preferredHeight: width
Layout.fillWidth: true
Layout.topMargin: app.margins
Layout.bottomMargin: app.landscape ? app.margins : 0
Layout.alignment: Qt.AlignCenter
Layout.rowSpan: app.landscape ? 3 : 1
Layout.fillHeight: true Layout.fillHeight: true
device: root.device Layout.fillWidth: !app.landscape
stateType: root.brightnessStateType columnSpacing: app.margins
showValueLabel: false rowSpacing: app.margins
}
// 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: 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);
// }
// }
// }
RowLayout {
Layout.fillHeight: true
spacing: app.margins
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
visible: root.ctStateType !== null visible: root.ctStateType !== null
columns: app.landscape ? 1 : 4
Repeater { Repeater {
model: ListModel { model: ListModel {
ListElement { name: "activate"; ct: "0"; bri: 100 } ListElement { name: "activate"; ct: "0"; bri: 100; color: "#00c5ff" }
ListElement { name: "concentrate"; ct: "23"; bri: 100 } ListElement { name: "concentrate"; ct: "23"; bri: 100; color: "#3dddff" }
ListElement { name: "reading"; ct: "57"; bri: 100 } ListElement { name: "reading"; ct: "57"; bri: 100; color: "#f4de00" }
ListElement { name: "relax"; ct: "95" ; bri: 55} ListElement { name: "relax"; ct: "95" ; bri: 55; color: "#ffaf2a"}
} }
delegate: Pane { delegate: Item {
Layout.preferredWidth: app.hugeIconSize
Layout.preferredHeight: app.hugeIconSize
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: Math.max(20, width) Layout.fillHeight: app.landscape
Material.elevation: 1 ItemDelegate {
// Layout.maximumWidth: app.iconSize * 2 height: app.hugeIconSize
padding: 0
Image {
source: "../images/lighting/" + model.name + ".svg"
anchors.fill: parent
ItemDelegate {
anchors.fill: parent
onClicked: {
// Translate from % to absolute value in min/max
// % : 100 = abs : (max - min)
print("min,max", root.ctStateType, root.ctStateType.minValue, root.ctStateType.maxValue)
var absoluteCtValue = (model.ct * (root.ctStateType.maxValue - root.ctStateType.minValue) / 100) + root.ctStateType.minValue
var params = [];
var param1 = {};
param1["paramTypeId"] = root.ctActionType.paramTypes.get(0).id;
param1["value"] = absoluteCtValue;
params.push(param1)
engine.deviceManager.executeAction(root.device.id, root.ctActionType.id, params)
params = [];
param1 = {};
param1["paramTypeId"] = root.brightnessActionType.paramTypes.get(0).id;
param1["value"] = model.bri;
params.push(param1)
engine.deviceManager.executeAction(root.device.id, root.brightnessActionType.id, params)
}
}
}
}
}
}
// Rectangle {
// color: "blue"
// Layout.fillWidth: true
// Layout.fillHeight: true
// Layout.minimumHeight: 20
// Layout.preferredHeight: 20
// visible: root.brightnessStateType
// Pane {
// anchors { left: parent.left; right: parent.right; verticalCenter: parent.verticalCenter }
// height: parent.height
// Material.elevation: 1
// padding: 0
// BrightnessSlider {
// anchors.fill: parent
// brightness: root.brightnessState ? root.brightnessState.value : 0
// 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);
// }
// }
// }
// }
Rectangle {
color: "red"
Layout.fillWidth: true
Layout.fillHeight: true
Layout.minimumHeight: 20
Layout.preferredHeight: 20
visible: root.ctStateType
Pane {
anchors { left: parent.left; right: parent.right; verticalCenter: parent.verticalCenter }
height: parent.height
Material.elevation: 1
padding: 0
ColorPickerCt {
id: pickerCt
anchors.fill: parent
ct: root.ctState ? root.ctState.value : 0
minCt: root.ctActionType ? root.ctStateType.minValue : 0
maxCt: root.ctActionType ? root.ctStateType.maxValue : 0
touchDelegate: Rectangle {
height: pickerCt.height
width: 5
color: app.accentColor
}
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);
}
}
}
}
Rectangle {
color: "green"
Layout.fillWidth: true
Layout.fillHeight: true
Layout.minimumHeight: 80
Layout.preferredHeight: 80
visible: root.colorStateType
Pane {
anchors { left: parent.left; right: parent.right; verticalCenter: parent.verticalCenter }
height: parent.height
Material.elevation: 1
padding: 0
ColorPicker {
id: colorPicker
anchors.fill: parent
property int pendingCommand: -1
property var queuedColor: null
function sendColor(color) {
var params = [];
var param1 = {};
param1["paramTypeId"] = root.colorActionType.paramTypes.get(0).id;
param1["value"] = color;
params.push(param1)
colorPicker.pendingCommand = engine.deviceManager.executeAction(root.device.id, root.colorActionType.id, params)
print("sent command", colorPicker.pendingCommand, color)
}
color: root.colorState ? root.colorState.value : "white"
touchDelegate: Rectangle {
height: 15
width: height width: height
radius: height / 2 anchors.centerIn: parent
color: app.foregroundColor
Rectangle { leftPadding: 0
color: colorPicker.hovered || colorPicker.pressed ? "#11000000" : "transparent" rightPadding: 0
anchors.centerIn: parent topPadding: 0
height: 30 bottomPadding: 0
width: height
radius: width / 2 contentItem: Rectangle {
Behavior on color { color: model.color
ColorAnimation { radius: 6
duration: 200
} ColorIcon {
anchors.fill: parent
name: "../images/lighting/" + model.name + ".svg"
color: "white"
} }
} }
}
Connections { onClicked: {
target: engine.deviceManager // Translate from % to absolute value in min/max
onExecuteActionReply: { // % : 100 = abs : (max - min)
print("action finished", JSON.stringify(params)) print("min,max", root.ctStateType, root.ctStateType.minValue, root.ctStateType.maxValue)
if (commandId === colorPicker.pendingCommand) { var absoluteCtValue = (model.ct * (root.ctStateType.maxValue - root.ctStateType.minValue) / 100) + root.ctStateType.minValue
colorPicker.pendingCommand = -1; var params = [];
if (colorPicker.queuedColor) { var param1 = {};
colorPicker.sendColor(colorPicker.queuedColor); param1["paramTypeId"] = root.ctActionType.paramTypes.get(0).id;
colorPicker.queuedColor = null param1["value"] = absoluteCtValue;
} params.push(param1)
} engine.deviceManager.executeAction(root.device.id, root.ctActionType.id, params)
params = [];
param1 = {};
param1["paramTypeId"] = root.brightnessActionType.paramTypes.get(0).id;
param1["value"] = model.bri;
params.push(param1)
engine.deviceManager.executeAction(root.device.id, root.brightnessActionType.id, params)
} }
} }
onColorChanged: {
if (!pressed) {
return;
}
if (pendingCommand != -1) {
queuedColor = color;
return;
}
sendColor(color);
}
} }
} }
} }
ColorPicker {
Layout.fillWidth: true
Layout.fillHeight: true
Layout.maximumHeight: width
thing: root.thing
visible: root.thing.thingClass.stateTypes.findByName("color") !== null
}
ColorTemperaturePicker {
Layout.fillWidth: !app.landscape
Layout.fillHeight: app.landscape
thing: root.thing
orientation: app.landscape ? Qt.Vertical : Qt.Horizontal
visible: root.thing.thingClass.stateTypes.findByName("colorTemperature") !== null
}
GridLayout {
id: basicItems
Layout.fillWidth: !app.landscape
Layout.fillHeight: app.landscape
Layout.alignment: Qt.AlignHCenter
columnSpacing: app.margins
rowSpacing: app.margins
columns: (app.landscape && (root.colorState !== null && root.ctState !== null))
|| (!app.landscape && (root.colorState === null && root.ctState === null)) ? 1 : 2
Rectangle {
Layout.preferredWidth: app.hugeIconSize
Layout.preferredHeight: width
radius: app.radius
color: root.colorState ? root.colorState.value : "red"
// color: Qt.tint(app.backgroundColor, Qt.rgba(app.foregroundColor.r, app.foregroundColor.g, app.foregroundColor.b, 0.1))
ColorIcon {
anchors.centerIn: parent
height: app.largeIconSize
width: height
name: root.powerState.value === true ? "../images/light-on.svg" : "../images/light-off.svg"
color: root.colorState ?
NymeaUtils.isDark(root.colorState.value) ? "white" : "black" : "white"
}
MouseArea {
anchors.fill: parent
onClicked: {
engine.thingManager.executeAction(root.thing.id, root.powerStateType.id, [{paramTypeId: root.powerStateType.id, value: !root.powerState.value}])
}
}
}
BrightnessSlider {
Layout.fillWidth: orientation == Qt.Horizontal
Layout.fillHeight: orientation == Qt.Vertical
thing: root.thing
orientation: basicItems.columns === 1 ? Qt.Vertical : Qt.Horizontal
visible: root.thing.stateByName("brightness") !== null
}
}
} }
} }

View File

@ -196,7 +196,7 @@ DevicePageBase {
Rectangle { Rectangle {
id: mask id: mask
anchors.fill: parent anchors.fill: parent
radius: app.margins radius: app.radius
color: "blue" color: "blue"
visible: false visible: false
} }

View File

@ -1,6 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg <svg
xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#" xmlns:cc="http://creativecommons.org/ns#"
@ -14,7 +12,7 @@
viewBox="0 0 256 256" viewBox="0 0 256 256"
id="svg2" id="svg2"
version="1.1" version="1.1"
inkscape:version="0.91 r13725" inkscape:version="1.0.1 (1.0.1+r74)"
sodipodi:docname="activate.svg"> sodipodi:docname="activate.svg">
<defs <defs
id="defs4" /> id="defs4" />
@ -25,18 +23,19 @@
borderopacity="1.0" borderopacity="1.0"
inkscape:pageopacity="0.0" inkscape:pageopacity="0.0"
inkscape:pageshadow="2" inkscape:pageshadow="2"
inkscape:zoom="2.8" inkscape:zoom="2.1753186"
inkscape:cx="66.409554" inkscape:cx="123.21035"
inkscape:cy="199.91527" inkscape:cy="147.11516"
inkscape:document-units="px" inkscape:document-units="px"
inkscape:current-layer="layer1" inkscape:current-layer="layer1"
showgrid="true" showgrid="true"
units="px" units="px"
inkscape:window-width="2880" inkscape:window-width="1380"
inkscape:window-height="1752" inkscape:window-height="873"
inkscape:window-x="0" inkscape:window-x="60"
inkscape:window-y="48" inkscape:window-y="27"
inkscape:window-maximized="1"> inkscape:window-maximized="1"
inkscape:document-rotation="0">
<inkscape:grid <inkscape:grid
type="xygrid" type="xygrid"
id="grid4136" /> id="grid4136" />
@ -49,7 +48,7 @@
<dc:format>image/svg+xml</dc:format> <dc:format>image/svg+xml</dc:format>
<dc:type <dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title> <dc:title />
</cc:Work> </cc:Work>
</rdf:RDF> </rdf:RDF>
</metadata> </metadata>
@ -58,24 +57,10 @@
inkscape:groupmode="layer" inkscape:groupmode="layer"
id="layer1" id="layer1"
transform="translate(0,-796.36216)"> transform="translate(0,-796.36216)">
<rect
style="opacity:1;fill:#00c5ff;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4138"
width="256"
height="256"
x="0"
y="796.36218" />
<circle
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4140"
cx="128"
cy="924.36218"
r="92.000023" />
<path <path
style="opacity:1;fill:#00c5ff;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4140"
d="m 210.00002,924.36218 c 0,45.28736 -36.71266,82.00002 -82.00002,82.00002 -39.180492,0 -71.94291,-27.47904 -80.066297,-64.21617 C 55,937.36216 130.28569,892.21933 130.28569,892.21933 l -0.14284,40.14283 c 0,0 64.85715,-45 69.81602,-47.35033 6.4013,11.68105 10.04115,25.09063 10.04115,39.35035 z" style="opacity:1;fill:#808080;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4202" d="M 127.86133 36 A 92.000023 92.000023 0 0 0 36 128 A 92.000023 92.000023 0 0 0 128 220 A 92.000023 92.000023 0 0 0 220 128 A 92.000023 92.000023 0 0 0 128 36 A 92.000023 92.000023 0 0 0 127.86133 36 z M 199.95898 88.650391 C 206.36028 100.33144 210 113.74028 210 128 C 210 173.28736 173.28736 210 128 210 C 88.819508 210 56.056981 182.52033 47.933594 145.7832 C 54.999891 140.99933 130.28516 95.857422 130.28516 95.857422 L 130.14258 136 C 130.14258 136 195.00011 91.000721 199.95898 88.650391 z "
inkscape:connector-curvature="0" transform="translate(0,796.36216)" />
sodipodi:nodetypes="ssccccs" />
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -1,6 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg <svg
xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#" xmlns:cc="http://creativecommons.org/ns#"
@ -14,7 +12,7 @@
viewBox="0 0 256 256" viewBox="0 0 256 256"
id="svg2" id="svg2"
version="1.1" version="1.1"
inkscape:version="0.91 r13725" inkscape:version="1.0.1 (1.0.1+r74)"
sodipodi:docname="concentrate.svg"> sodipodi:docname="concentrate.svg">
<defs <defs
id="defs4" /> id="defs4" />
@ -25,18 +23,19 @@
borderopacity="1.0" borderopacity="1.0"
inkscape:pageopacity="0.0" inkscape:pageopacity="0.0"
inkscape:pageshadow="2" inkscape:pageshadow="2"
inkscape:zoom="11.2" inkscape:zoom="2.0704471"
inkscape:cx="128.78304" inkscape:cx="115.75638"
inkscape:cy="130.74689" inkscape:cy="121.69523"
inkscape:document-units="px" inkscape:document-units="px"
inkscape:current-layer="layer1" inkscape:current-layer="layer1"
showgrid="true" showgrid="true"
units="px" units="px"
inkscape:window-width="2880" inkscape:window-width="1380"
inkscape:window-height="1752" inkscape:window-height="873"
inkscape:window-x="0" inkscape:window-x="60"
inkscape:window-y="48" inkscape:window-y="27"
inkscape:window-maximized="1"> inkscape:window-maximized="1"
inkscape:document-rotation="0">
<inkscape:grid <inkscape:grid
type="xygrid" type="xygrid"
id="grid4136" /> id="grid4136" />
@ -49,7 +48,7 @@
<dc:format>image/svg+xml</dc:format> <dc:format>image/svg+xml</dc:format>
<dc:type <dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title> <dc:title />
</cc:Work> </cc:Work>
</rdf:RDF> </rdf:RDF>
</metadata> </metadata>
@ -58,46 +57,10 @@
inkscape:groupmode="layer" inkscape:groupmode="layer"
id="layer1" id="layer1"
transform="translate(0,-796.36216)"> transform="translate(0,-796.36216)">
<rect
style="opacity:1;fill:#3dddff;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4138"
width="256"
height="256"
x="0"
y="796.36218" />
<circle
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4140"
cx="128"
cy="924.36218"
r="92.000023" />
<path <path
style="opacity:1;fill:#3dddff;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4140"
d="M 210.00002,924.36218 A 82.000023,82.000023 0 0 1 128,1006.3622 82.000023,82.000023 0 0 1 45.999977,924.36218 82.000023,82.000023 0 0 1 128,842.36216 a 82.000023,82.000023 0 0 1 82.00002,82.00002 z" style="opacity:1;fill:#808080;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4202" /> d="M 127.86133 36 A 92.000023 92.000023 0 0 0 36 128 A 92.000023 92.000023 0 0 0 128 220 A 92.000023 92.000023 0 0 0 220 128 A 92.000023 92.000023 0 0 0 128 36 A 92.000023 92.000023 0 0 0 127.86133 36 z M 127.88281 46 A 82.000023 82.000023 0 0 1 128 46 A 82.000023 82.000023 0 0 1 210 128 A 82.000023 82.000023 0 0 1 128 210 A 82.000023 82.000023 0 0 1 46 128 A 82.000023 82.000023 0 0 1 127.88281 46 z M 127.79688 58 A 70 70 0 0 0 58 128 A 70 70 0 0 0 128 198 A 70 70 0 0 0 198 128 A 70 70 0 0 0 128 58 A 70 70 0 0 0 127.79688 58 z M 128 73 A 55.000023 55.000023 0 0 1 183 128 A 55.000023 55.000023 0 0 1 128 183 A 55.000023 55.000023 0 0 1 73 128 A 55.000023 55.000023 0 0 1 128 73 z M 127.74414 93 A 35.000023 35.000023 0 0 0 93 128 A 35.000023 35.000023 0 0 0 128 163 A 35.000023 35.000023 0 0 0 163 128 A 35.000023 35.000023 0 0 0 128 93 A 35.000023 35.000023 0 0 0 127.74414 93 z M 128 108 A 20.000023 20.000023 0 0 1 148 128 A 20.000023 20.000023 0 0 1 128 148 A 20.000023 20.000023 0 0 1 108 128 A 20.000023 20.000023 0 0 1 128 108 z "
<circle transform="translate(0,796.36216)" />
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4254"
cx="128"
cy="924.36218"
r="70" />
<circle
style="opacity:1;fill:#3dddff;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4256"
cx="128"
cy="924.36218"
r="55.000023" />
<circle
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4258"
cx="128"
cy="924.36218"
r="35.000023" />
<circle
style="opacity:1;fill:#3dddff;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4260"
cx="128"
cy="924.36218"
r="20.000023" />
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -1,6 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg <svg
xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#" xmlns:cc="http://creativecommons.org/ns#"
@ -14,7 +12,7 @@
viewBox="0 0 256 256" viewBox="0 0 256 256"
id="svg2" id="svg2"
version="1.1" version="1.1"
inkscape:version="0.91 r13725" inkscape:version="1.0.1 (1.0.1+r74)"
sodipodi:docname="reading.svg"> sodipodi:docname="reading.svg">
<defs <defs
id="defs4" /> id="defs4" />
@ -26,17 +24,18 @@
inkscape:pageopacity="0.0" inkscape:pageopacity="0.0"
inkscape:pageshadow="2" inkscape:pageshadow="2"
inkscape:zoom="2.8" inkscape:zoom="2.8"
inkscape:cx="66.409554" inkscape:cx="122.92774"
inkscape:cy="199.91527" inkscape:cy="133.69504"
inkscape:document-units="px" inkscape:document-units="px"
inkscape:current-layer="layer1" inkscape:current-layer="layer1"
showgrid="true" showgrid="true"
units="px" units="px"
inkscape:window-width="2880" inkscape:window-width="1380"
inkscape:window-height="1752" inkscape:window-height="873"
inkscape:window-x="0" inkscape:window-x="60"
inkscape:window-y="48" inkscape:window-y="27"
inkscape:window-maximized="1"> inkscape:window-maximized="1"
inkscape:document-rotation="0">
<inkscape:grid <inkscape:grid
type="xygrid" type="xygrid"
id="grid4136" /> id="grid4136" />
@ -49,7 +48,7 @@
<dc:format>image/svg+xml</dc:format> <dc:format>image/svg+xml</dc:format>
<dc:type <dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title> <dc:title />
</cc:Work> </cc:Work>
</rdf:RDF> </rdf:RDF>
</metadata> </metadata>
@ -58,65 +57,10 @@
inkscape:groupmode="layer" inkscape:groupmode="layer"
id="layer1" id="layer1"
transform="translate(0,-796.36216)"> transform="translate(0,-796.36216)">
<rect <path
style="opacity:1;fill:#f4de00;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4138"
width="256"
height="256"
x="0"
y="796.36218" />
<circle
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4140" id="path4140"
cx="128" style="opacity:1;fill:#808080;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
cy="924.36218" d="M 127.86133 36 A 92.000023 92.000023 0 0 0 36 128 A 92.000023 92.000023 0 0 0 128 220 A 92.000023 92.000023 0 0 0 220 128 A 92.000023 92.000023 0 0 0 128 36 A 92.000023 92.000023 0 0 0 127.86133 36 z M 78 73 L 178 73 L 178 83 L 78 83 L 78 73 z M 78 93 L 178 93 L 178 103 L 78 103 L 78 93 z M 78 113 L 178 113 L 178 123 L 78 123 L 78 113 z M 78 133 L 178 133 L 178 143 L 78 143 L 78 133 z M 78 153 L 178 153 L 178 163 L 78 163 L 78 153 z M 78 173 L 178 173 L 178 183 L 78 183 L 78 173 z "
r="92.000023" /> transform="translate(0,796.36216)" />
<g
id="g4156"
transform="translate(-2,1.9999774)"
style="fill:#f4de00;fill-opacity:1">
<rect
y="867.36218"
x="80"
height="10"
width="100"
id="rect4142"
style="opacity:1;fill:#f4de00;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
style="opacity:1;fill:#f4de00;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4144"
width="100"
height="10"
x="80"
y="887.36218" />
<rect
y="907.36218"
x="80"
height="10"
width="100"
id="rect4146"
style="opacity:1;fill:#f4de00;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
style="opacity:1;fill:#f4de00;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4148"
width="100"
height="10"
x="80"
y="927.36218" />
<rect
y="947.36218"
x="80"
height="10"
width="100"
id="rect4150"
style="opacity:1;fill:#f4de00;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
style="opacity:1;fill:#f4de00;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4152"
width="100"
height="10"
x="80"
y="967.36218" />
</g>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -1,6 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg <svg
xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#" xmlns:cc="http://creativecommons.org/ns#"
@ -14,7 +12,7 @@
viewBox="0 0 256 256" viewBox="0 0 256 256"
id="svg2" id="svg2"
version="1.1" version="1.1"
inkscape:version="0.91 r13725" inkscape:version="1.0.1 (1.0.1+r74)"
sodipodi:docname="relax.svg"> sodipodi:docname="relax.svg">
<defs <defs
id="defs4" /> id="defs4" />
@ -25,18 +23,19 @@
borderopacity="1.0" borderopacity="1.0"
inkscape:pageopacity="0.0" inkscape:pageopacity="0.0"
inkscape:pageshadow="2" inkscape:pageshadow="2"
inkscape:zoom="2.8" inkscape:zoom="1.1480033"
inkscape:cx="66.409554" inkscape:cx="56.435095"
inkscape:cy="199.91527" inkscape:cy="139.24953"
inkscape:document-units="px" inkscape:document-units="px"
inkscape:current-layer="layer1" inkscape:current-layer="layer1"
showgrid="true" showgrid="true"
units="px" units="px"
inkscape:window-width="2880" inkscape:window-width="1380"
inkscape:window-height="1752" inkscape:window-height="873"
inkscape:window-x="0" inkscape:window-x="60"
inkscape:window-y="48" inkscape:window-y="27"
inkscape:window-maximized="1"> inkscape:window-maximized="1"
inkscape:document-rotation="0">
<inkscape:grid <inkscape:grid
type="xygrid" type="xygrid"
id="grid4136" /> id="grid4136" />
@ -49,7 +48,7 @@
<dc:format>image/svg+xml</dc:format> <dc:format>image/svg+xml</dc:format>
<dc:type <dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title> <dc:title />
</cc:Work> </cc:Work>
</rdf:RDF> </rdf:RDF>
</metadata> </metadata>
@ -58,24 +57,10 @@
inkscape:groupmode="layer" inkscape:groupmode="layer"
id="layer1" id="layer1"
transform="translate(0,-796.36216)"> transform="translate(0,-796.36216)">
<rect
style="opacity:1;fill:#ffaf2a;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4138"
width="256"
height="256"
x="0"
y="796.36218" />
<circle
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4140"
cx="128"
cy="924.36218"
r="92.000023" />
<path <path
id="circle4230" id="path4140"
style="opacity:1;fill:#ffaf2a;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" style="opacity:1;fill:#808080;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 128,1006.3622 c 45.28736,0 82.00002,-36.71266 82.21429,-82.00002 0.21428,22.88037 -18.33392,41.42857 -41.21429,41.42857 -22.88037,0 -41.42857,-18.5482 -41,-41.42857 0.42857,-22.88037 -18.11963,-41.42857 -41,-41.42857 -22.880367,0 -41.42857,18.5482 -41.214297,41.42857 0.214276,45.28736 36.926936,82.00002 82.214297,82.00002 z" d="M 127.86133 36 A 92.000023 92.000023 0 0 0 36 128 A 92.000023 92.000023 0 0 0 128 220 A 92.000023 92.000023 0 0 0 220 128 A 92.000023 92.000023 0 0 0 128 36 A 92.000023 92.000023 0 0 0 127.86133 36 z M 87 86.572266 C 109.88037 86.572266 128.42857 105.11963 128 128 C 127.57143 150.88037 146.11963 169.42773 169 169.42773 C 191.12817 169.42773 209.2011 152.08002 210.17188 130.24219 C 210.1953 129.49734 210.2113 128.74967 210.21484 128 C 210.22189 128.7522 210.20487 129.49986 210.17188 130.24219 C 208.78032 174.49311 172.53769 210 128 210 C 82.712639 210 45.999432 173.28736 45.785156 128 C 45.570883 105.11963 64.119633 86.572266 87 86.572266 z "
inkscape:connector-curvature="0" transform="translate(0,796.36216)" />
sodipodi:nodetypes="scscscs" />
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -0,0 +1,48 @@
import QtQuick 2.9
import Nymea 1.0
Item {
id: root
property Thing thing: null
property StateType stateType: null
readonly property var pendingValue: d.queuedValue || d.pendingValue
function sendValue(value) {
if (d.pendingCommand != -1) {
// busy, cache value
d.queuedValue = value;
return;
}
d.pendingValue = value;
d.pendingCommand = engine.thingManager.executeAction(root.thing.id,
root.stateType.id,
[{
paramTypeId: root.stateType.id,
value: value
}])
d.queuedValue = null
}
QtObject {
id: d
property int pendingCommand: -1
property var pendingValue: null
property var queuedValue: null
}
Connections {
target: engine.thingManager
onExecuteActionReply: {
if (d.pendingCommand == commandId) {
d.pendingCommand = -1;
if (d.queuedValue != null) {
root.sendValue(d.queuedValue)
} else {
d.pendingValue = null
}
}
}
}
}