Merge PR #471: Fixes and improvements for lights
@ -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>
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -102,5 +102,4 @@ Item {
|
|||||||
sourceComponent: root.touchDelegate
|
sourceComponent: root.touchDelegate
|
||||||
visible: mouseArea.pressed && root.active
|
visible: mouseArea.pressed && root.active
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
249
nymea-app/ui/components/ColorPickerPre510.qml
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
69
nymea-app/ui/components/ColorTemperaturePicker.qml
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -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
|
||||||
|
|||||||
@ -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: {
|
||||||
|
|||||||
@ -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)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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) {
|
||||||
|
|||||||
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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 |
@ -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 |
@ -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 |
@ -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 |
48
nymea-app/ui/utils/ActionQueue.qml
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||