Update ParamDelegates and many small improvements
This commit is contained in:
parent
1431e7001e
commit
28ce85b561
@ -3,7 +3,7 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright (C) 2013 - 2024, nymea GmbH
|
||||
* Copyright (C) 2024 - 2025, chargebyte austria GmbH
|
||||
* Copyright (C) 2024 - 2026, chargebyte austria GmbH
|
||||
*
|
||||
* This file is part of libnymea-app.
|
||||
*
|
||||
@ -26,10 +26,9 @@
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
ThingClass::ThingClass(QObject *parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
}
|
||||
ThingClass::ThingClass(QObject *parent)
|
||||
: QObject(parent)
|
||||
{}
|
||||
|
||||
QUuid ThingClass::id() const
|
||||
{
|
||||
@ -330,3 +329,8 @@ bool ThingClass::hasActionType(const QUuid &actionTypeId)
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ThingClass::isAutoCreated() const
|
||||
{
|
||||
return m_createMethods.contains("CreateMethodAuto");
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright (C) 2013 - 2024, nymea GmbH
|
||||
* Copyright (C) 2024 - 2025, chargebyte austria GmbH
|
||||
* Copyright (C) 2024 - 2026, chargebyte austria GmbH
|
||||
*
|
||||
* This file is part of libnymea-app.
|
||||
*
|
||||
@ -25,15 +25,15 @@
|
||||
#ifndef THINGCLASS_H
|
||||
#define THINGCLASS_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QUuid>
|
||||
#include <QList>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QUuid>
|
||||
|
||||
#include "actiontypes.h"
|
||||
#include "eventtypes.h"
|
||||
#include "paramtypes.h"
|
||||
#include "statetypes.h"
|
||||
#include "eventtypes.h"
|
||||
#include "actiontypes.h"
|
||||
|
||||
class ThingClass : public QObject
|
||||
{
|
||||
@ -135,6 +135,8 @@ public:
|
||||
|
||||
Q_INVOKABLE bool hasActionType(const QUuid &actionTypeId);
|
||||
|
||||
Q_INVOKABLE bool isAutoCreated() const;
|
||||
|
||||
signals:
|
||||
void paramTypesChanged();
|
||||
void settingsTypesChanged();
|
||||
|
||||
@ -126,7 +126,7 @@ Item {
|
||||
ValueAxis {
|
||||
id: yAxis
|
||||
max: {
|
||||
if (root.stateType && root.stateType.type.toLowerCase() == "bool") {
|
||||
if (root.stateType && root.stateType.type.toLowerCase() === "bool") {
|
||||
return 1;
|
||||
} else {
|
||||
Math.ceil(logsModelNg.maxValue + Math.abs(logsModelNg.maxValue * .05))
|
||||
@ -137,7 +137,7 @@ Item {
|
||||
// onMaxChanged: applyNiceNumbers();
|
||||
labelsFont: Style.extraSmallFont
|
||||
labelFormat: {
|
||||
if (root.stateType && root.stateType.type.toLowerCase() == "bool") {
|
||||
if (root.stateType && root.stateType.type.toLowerCase() === "bool") {
|
||||
return "x";
|
||||
} else {
|
||||
return "%d";
|
||||
|
||||
@ -147,7 +147,7 @@ Item {
|
||||
// y: chartView.plotArea.y
|
||||
// height: chartView.plotArea.height
|
||||
// width: chartView.plotArea.x - x
|
||||
// visible: root.stateType.type.toLowerCase() != "bool" && logsModel.minValue != logsModel.maxValue
|
||||
// visible: root.stateType.type.toLowerCase() !== "bool" && logsModel.minValue != logsModel.maxValue
|
||||
// property double range: Math.abs(valueAxis.max - valueAxis.min)
|
||||
// property double stepSize: range / (valueAxis.tickCount - 1)
|
||||
// property int precision: valueAxis.max - valueAxis.min < 5 ? 2 : 0
|
||||
@ -256,7 +256,7 @@ Item {
|
||||
print("entry", entry.timestamp, entry.source, JSON.stringify(entry.values))
|
||||
d.ensureValue(zeroSeries, entry.timestamp)
|
||||
|
||||
if (stateType.type.toLowerCase() == "bool") {
|
||||
if (stateType.type.toLowerCase() === "bool") {
|
||||
var value = entry.values[stateType.name]
|
||||
if (value == null) {
|
||||
value = false;
|
||||
@ -290,7 +290,7 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
if (stateType.type.toLowerCase() == "bool") {
|
||||
if (stateType.type.toLowerCase() === "bool") {
|
||||
|
||||
var last = series.at(series.count-1);
|
||||
if (last.x < d.endTime) {
|
||||
@ -304,7 +304,7 @@ Item {
|
||||
}
|
||||
onEntriesRemoved: (index, count) => {
|
||||
print("removing:", index, count, series.count)
|
||||
if (stateType.type.toLowerCase() == "bool") {
|
||||
if (stateType.type.toLowerCase() === "bool") {
|
||||
series.removePoints(index * 2, count * 2)
|
||||
if (series.count == 1) {
|
||||
series.removePoints(0, 1);
|
||||
|
||||
@ -57,7 +57,7 @@ Item {
|
||||
if (root.interfaceName == "closablesensor") {
|
||||
return true
|
||||
}
|
||||
return sensorStateType && sensorStateType.type.toLowerCase() == "bool" && sensorState.value === true
|
||||
return sensorStateType && sensorStateType.type.toLowerCase() === "bool" && sensorState.value === true
|
||||
}
|
||||
iconSource: {
|
||||
if (root.interfaceName == "closablesensor") {
|
||||
@ -100,7 +100,7 @@ Item {
|
||||
}
|
||||
|
||||
sourceComponent: {
|
||||
if (stateType.type.toLowerCase() == "bool") {
|
||||
if (stateType.type.toLowerCase() === "bool") {
|
||||
return boolComponent;
|
||||
}
|
||||
|
||||
|
||||
@ -56,7 +56,7 @@ Item {
|
||||
property date now: new Date()
|
||||
|
||||
readonly property int range: selectionTabs.currentValue.range
|
||||
readonly property int sampleRate: root.stateType == null || root.stateType.type.toLowerCase() == "bool" ? NewLogsModel.SampleRateAny : selectionTabs.currentValue.sampleRate
|
||||
readonly property int sampleRate: root.stateType == null || root.stateType.type.toLowerCase() === "bool" ? NewLogsModel.SampleRateAny : selectionTabs.currentValue.sampleRate
|
||||
|
||||
readonly property int visibleValues: range / sampleRate
|
||||
|
||||
@ -114,7 +114,7 @@ Item {
|
||||
// print("entry", entry.timestamp, entry.source, JSON.stringify(entry.values))
|
||||
zeroSeries.ensureValue(entry.timestamp)
|
||||
|
||||
if (root.stateType.type.toLowerCase() == "bool") {
|
||||
if (root.stateType.type.toLowerCase() === "bool") {
|
||||
var value = entry.values[root.stateType.name]
|
||||
if (value == null) {
|
||||
value = false;
|
||||
@ -148,7 +148,7 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
if (root.stateType.type.toLowerCase() == "bool") {
|
||||
if (root.stateType.type.toLowerCase() === "bool") {
|
||||
var last = valueSeries.at(valueSeries.count-1);
|
||||
if (last.x < d.endTime) {
|
||||
valueSeries.append(d.endTime, last.y)
|
||||
@ -160,7 +160,7 @@ Item {
|
||||
}
|
||||
onEntriesRemoved: (index, count) => {
|
||||
print("removing:", index, count, valueSeries.count)
|
||||
if (root.stateType.type.toLowerCase() == "bool") {
|
||||
if (root.stateType.type.toLowerCase() === "bool") {
|
||||
valueSeries.removePoints(index * 2, count * 2)
|
||||
if (valueSeries.count == 1) {
|
||||
valueSeries.removePoints(0, 1);
|
||||
@ -419,7 +419,7 @@ Item {
|
||||
y: chartView.y + chartView.plotArea.y
|
||||
height: chartView.plotArea.height
|
||||
width: Math.max(0, chartContainer.yAxisLabelAreaWidth - Style.smallMargins)
|
||||
visible: root.stateType && root.stateType.type.toLowerCase() != "bool" && logsModel.minValue != logsModel.maxValue
|
||||
visible: root.stateType && root.stateType.type.toLowerCase() !== "bool" && logsModel.minValue != logsModel.maxValue
|
||||
property double range: Math.abs(valueAxis.max - valueAxis.min)
|
||||
property double stepSize: range / (valueAxis.tickCount - 1)
|
||||
property int precision: valueAxis.max - valueAxis.min < 5 ? 2 : 0
|
||||
@ -589,7 +589,7 @@ Item {
|
||||
elide: Text.ElideRight
|
||||
text: toolTip.value === null
|
||||
? qsTr("No data")
|
||||
: root.stateType.type.toLowerCase() == "bool"
|
||||
: root.stateType.type.toLowerCase() === "bool"
|
||||
? root.stateType.displayName + ": " + (toolTip.value ? qsTr("Yes") : qsTr("No"))
|
||||
: Types.toUiValue(toolTip.value, root.stateType.unit).toFixed(root.roundTo) + Types.toUiUnit(root.stateType.unit)
|
||||
font: Style.extraSmallFont
|
||||
|
||||
@ -37,6 +37,7 @@ ItemDelegate {
|
||||
property alias value: d.value
|
||||
property Param param: Param {
|
||||
id: d
|
||||
|
||||
paramTypeId: paramType.id
|
||||
value: paramType.defaultValue
|
||||
}
|
||||
@ -48,9 +49,11 @@ ItemDelegate {
|
||||
bottomPadding: 0
|
||||
contentItem: ColumnLayout {
|
||||
id: contentItemColumn
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: Style.margins
|
||||
anchors.rightMargin: Style.margins
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: Style.margins
|
||||
@ -70,8 +73,6 @@ ItemDelegate {
|
||||
Layout.fillWidth: true//!parent.labelFillsWidth
|
||||
Layout.maximumWidth: root.nameVisible ? contentItemColumn.width / 2 : contentItemColumn.width
|
||||
sourceComponent: {
|
||||
print("Loading ParamDelegate");
|
||||
print("Writable:", root.writable, "type:", root.paramType.type, "min:", root.paramType.minValue, "max:", root.paramType.maxValue, "value:", root.param.value)
|
||||
if (!root.writable) {
|
||||
return stringComponent;
|
||||
}
|
||||
@ -123,12 +124,11 @@ ItemDelegate {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Component {
|
||||
id: stringComponent
|
||||
|
||||
Label {
|
||||
text: {
|
||||
switch (root.paramType.type.toLowerCase()) {
|
||||
@ -141,15 +141,17 @@ ItemDelegate {
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: boolComponent
|
||||
|
||||
Item {
|
||||
implicitHeight: theSwitch.implicitHeight
|
||||
implicitWidth: theSwitch.implicitWidth
|
||||
Switch {
|
||||
id: theSwitch
|
||||
anchors { top: parent.top; right: parent.right; bottom: parent.bottom }
|
||||
width: Math.min(parent.width, implicitiWidth)
|
||||
width: Math.min(parent.width, implicitWidth)
|
||||
checked: root.param.value === true
|
||||
Component.onCompleted: {
|
||||
if (root.param.value === undefined) {
|
||||
@ -162,10 +164,11 @@ ItemDelegate {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Component {
|
||||
id: sliderComponent
|
||||
|
||||
RowLayout {
|
||||
spacing: Style.margins
|
||||
|
||||
@ -206,6 +209,7 @@ ItemDelegate {
|
||||
root.param.value = newValue;
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
text: Types.toUiValue(root.param.value, root.paramType.unit).toFixed(slider.decimals) + Types.toUiUnit(root.paramType.unit)
|
||||
}
|
||||
@ -231,18 +235,19 @@ ItemDelegate {
|
||||
: 2000000000
|
||||
editable: true
|
||||
width: 150
|
||||
onValueModified: root.param.value = value
|
||||
floatingPoint: root.paramType.type.toLowerCase() === "double"
|
||||
|
||||
floatingPoint: root.paramType.type.toLowerCase() == "double"
|
||||
onValueModified: (value) => { root.param.value = value }
|
||||
|
||||
Component.onCompleted: {
|
||||
print("from:", from, "min", root.paramType.minValue)
|
||||
print("to:", to, "max", root.paramType.maxValue)
|
||||
if (root.value === undefined) {
|
||||
root.value = value
|
||||
if (root.param.value === undefined) {
|
||||
root.param.value = value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
text: Types.toUiUnit(root.paramType.unit)
|
||||
visible: text.length > 0
|
||||
@ -255,40 +260,48 @@ ItemDelegate {
|
||||
TextField {
|
||||
text: root.param.value !== undefined
|
||||
? root.param.value
|
||||
: root.paramType.defaultValue
|
||||
: root.paramType.defaultValue !== undefined
|
||||
? root.paramType.defaultValue
|
||||
: ""
|
||||
|
||||
placeholderText: root.placeholderText
|
||||
onEditingFinished: {
|
||||
root.param.value = text
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
if (root.param.value === undefined) {
|
||||
root.param.value = text;
|
||||
}
|
||||
}
|
||||
placeholderText: root.placeholderText
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: comboBoxComponent
|
||||
|
||||
ComboBox {
|
||||
id: control
|
||||
Layout.fillWidth: true
|
||||
model: root.paramType.allowedValues
|
||||
displayText: currentText + ( root.paramType.unit != Types.UnitNone ? " " + Types.toUiUnit(root.paramType.unit) : "")
|
||||
displayText: {
|
||||
if (currentIndex < 0 || currentIndex >= root.paramType.allowedValues.length) {
|
||||
return "";
|
||||
}
|
||||
return Types.toUiValue(root.paramType.allowedValues[currentIndex], root.paramType.unit)
|
||||
+ (root.paramType.unit !== Types.UnitNone ? " " + Types.toUiUnit(root.paramType.unit) : "");
|
||||
}
|
||||
currentIndex: root.paramType.allowedValues.indexOf(root.param.value !== undefined ? root.param.value : root.paramType.defaultValue)
|
||||
delegate: ItemDelegate {
|
||||
width: control.width
|
||||
text: Types.toUiValue(modelData, root.paramType.unit) + ( root.paramType.unit != Types.UnitNone ? " " + Types.toUiUnit(root.paramType.unit) : "")
|
||||
text: Types.toUiValue(modelData, root.paramType.unit) + ( root.paramType.unit !== Types.UnitNone ? " " + Types.toUiUnit(root.paramType.unit) : "")
|
||||
highlighted: control.highlightedIndex === index
|
||||
}
|
||||
onActivated: (index) => {
|
||||
root.param.value = root.paramType.allowedValues[index]
|
||||
}
|
||||
onActivated: (index) => { root.param.value = root.paramType.allowedValues[index] }
|
||||
Component.onCompleted: {
|
||||
if (root.value === undefined) {
|
||||
root.value = model[0]
|
||||
if (root.param.value === undefined) {
|
||||
root.param.value = model[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -296,6 +309,7 @@ ItemDelegate {
|
||||
|
||||
Component {
|
||||
id: colorPickerComponent
|
||||
|
||||
ColorPickerPre510 {
|
||||
id: colorPicker
|
||||
implicitHeight: 200
|
||||
@ -333,6 +347,7 @@ ItemDelegate {
|
||||
|
||||
Component {
|
||||
id: colorTemperaturePickerComponent
|
||||
|
||||
ColorPickerCt {
|
||||
id: colorPickerCt
|
||||
implicitHeight: 50
|
||||
@ -340,7 +355,7 @@ ItemDelegate {
|
||||
maxCt: root.paramType.maxValue
|
||||
ct: root.param.value !== undefined
|
||||
? root.param.value
|
||||
: root.paramType.defaultValue
|
||||
: root.paramType.defaultValue !== undefined
|
||||
? root.paramType.defaultValue
|
||||
: root.paramType.minValue
|
||||
|
||||
@ -359,6 +374,7 @@ ItemDelegate {
|
||||
|
||||
Component {
|
||||
id: colorPreviewComponent
|
||||
|
||||
Rectangle {
|
||||
implicitHeight: app.mediumFont
|
||||
implicitWidth: implicitHeight
|
||||
|
||||
@ -63,7 +63,7 @@ ItemDelegate {
|
||||
id: loader
|
||||
Layout.fillWidth: !parent.labelFillsWidth
|
||||
sourceComponent: {
|
||||
print("Loading ParamDelegate");
|
||||
print("Loading StateDelegate");
|
||||
print("Writable:", root.writable, "type:", root.stateType.type, "min:", root.stateType.minValue, "max:", root.stateType.maxValue, "value:", root.param.value)
|
||||
if (!root.writable) {
|
||||
return stringComponent;
|
||||
@ -222,7 +222,7 @@ ItemDelegate {
|
||||
width: 150
|
||||
onValueModified: root.param.value = value
|
||||
|
||||
floatingPoint: root.stateType.type.toLowerCase() == "double"
|
||||
floatingPoint: root.stateType.type.toLowerCase() === "double"
|
||||
|
||||
Component.onCompleted: {
|
||||
print("from:", from, "min", root.stateType.minValue)
|
||||
@ -264,11 +264,11 @@ ItemDelegate {
|
||||
id: control
|
||||
Layout.fillWidth: true
|
||||
model: root.stateType.allowedValues
|
||||
displayText: currentText + ( root.stateType.unit != Types.UnitNone ? " " + Types.toUiUnit(root.stateType.unit) : "")
|
||||
displayText: currentText + ( root.stateType.unit !== Types.UnitNone ? " " + Types.toUiUnit(root.stateType.unit) : "")
|
||||
currentIndex: root.stateType.allowedValues.indexOf(root.param.value !== undefined ? root.param.value : root.stateType.defaultValue)
|
||||
delegate: ItemDelegate {
|
||||
width: control.width
|
||||
text: Types.toUiValue(modelData, root.stateType.unit) + ( root.stateType.unit != Types.UnitNone ? " " + Types.toUiUnit(root.stateType.unit) : "")
|
||||
text: Types.toUiValue(modelData, root.stateType.unit) + ( root.stateType.unit !== Types.UnitNone ? " " + Types.toUiUnit(root.stateType.unit) : "")
|
||||
highlighted: control.highlightedIndex === index
|
||||
}
|
||||
onActivated: (index) => {
|
||||
|
||||
@ -36,7 +36,7 @@ SpinBox {
|
||||
stepSize: Math.min(10, (to - from) / 10)
|
||||
property var unit: Types.UnitNone
|
||||
editable: true
|
||||
onValueModified: {
|
||||
onValueModified: (value) => {
|
||||
changed(value)
|
||||
}
|
||||
textFromValue: function(value) {
|
||||
|
||||
@ -172,17 +172,9 @@ Page {
|
||||
var maxValue = stateDelegate.stateType.maxValue !== undefined
|
||||
? stateDelegate.stateType.maxValue
|
||||
: 2000000000;
|
||||
print("pushing delegate for", stateDelegate.stateType.name, "from:", minValue, "to:", maxValue, "possible:", stateDelegate.stateType.possibleValuesDisplayNames)
|
||||
stateDelegateLoader.setSource("../delegates/statedelegates/" + sourceComp,
|
||||
{
|
||||
value: root.thing.states.getState(stateType.id).value,
|
||||
possibleValues: stateDelegate.stateType.possibleValues,
|
||||
possibleValuesDisplayNames: stateDelegate.stateType.possibleValuesDisplayNames,
|
||||
from: minValue,
|
||||
to: maxValue,
|
||||
unit: stateDelegate.stateType.unit,
|
||||
writable: false,
|
||||
stateType: stateDelegate.stateType
|
||||
console.log("pushing delegate for", stateDelegate.stateType.name, "from:", minValue, "to:", maxValue, "possible:", stateDelegate.stateType.possibleValuesDisplayNames)
|
||||
stateDelegateLoader.setSource("../delegates/statedelegates/" + sourceComp, {
|
||||
value: root.thing.states.getState(stateType.id).value
|
||||
})
|
||||
|
||||
}
|
||||
@ -231,6 +223,16 @@ Page {
|
||||
property: "unit"
|
||||
value: stateDelegate.stateType.unit
|
||||
}
|
||||
Binding {
|
||||
target: stateDelegateLoader.item.hasOwnProperty("writable") ? stateDelegateLoader.item : null
|
||||
property: "writable"
|
||||
value: false
|
||||
}
|
||||
Binding {
|
||||
target: stateDelegateLoader.item.hasOwnProperty("stateType") ? stateDelegateLoader.item : null
|
||||
property: "stateType"
|
||||
value: stateDelegate.stateType
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -61,7 +61,7 @@ NymeaSwipeDelegate {
|
||||
operatorString = " = ";
|
||||
break;
|
||||
case ParamDescriptor.ValueOperatorNotEquals:
|
||||
operatorString = " != ";
|
||||
operatorString = " !== ";
|
||||
break;
|
||||
case ParamDescriptor.ValueOperatorGreater:
|
||||
operatorString = " > ";
|
||||
|
||||
@ -84,7 +84,7 @@ DashboardDelegateBase {
|
||||
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
visible: root.stateType && root.stateType.type.toLowerCase() != "bool"
|
||||
visible: root.stateType && root.stateType.type.toLowerCase() !== "bool"
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
font: Style.largeFont
|
||||
elide: Text.ElideRight
|
||||
|
||||
@ -59,20 +59,27 @@ SettingsPageBase {
|
||||
width: implicitWidth + app.margins
|
||||
x: parent.width - width
|
||||
|
||||
Component.onCompleted: {
|
||||
deviceMenu.addItem(menuEntryComponent.createObject(deviceMenu, {text: qsTr("Rename"), iconSource: "qrc:/icons/edit.svg", functionName: "renameThing"}))
|
||||
// FIXME: This isn't entirely correct... we should have a way to know if a particular thing is in fact autocreated
|
||||
// This check might be wrong for thingClasses with multiple create methods...
|
||||
if (!root.thing.isChild || root.thing.thingClass.createMethods.indexOf("CreateMethodAuto") < 0) {
|
||||
deviceMenu.addItem(menuEntryComponent.createObject(deviceMenu, {text: qsTr("Delete"), iconSource: "qrc:/icons/delete.svg", functionName: "deleteThing"}))
|
||||
}
|
||||
// FIXME: This isn't entirely correct... we should have a way to know if a particular thing is in fact autocreated
|
||||
// This check might be wrong for thingClasses with multiple create methods...
|
||||
if (!root.thing.isChild || root.thingClass.createMethods.indexOf("CreateMethodAuto") < 0) {
|
||||
deviceMenu.addItem(menuEntryComponent.createObject(deviceMenu, {text: qsTr("Reconfigure"), iconSource: "qrc:/icons/configure.svg", functionName: "reconfigureThing"}))
|
||||
function addMenuEntry(properties) {
|
||||
var item = menuEntryComponent.createObject(null, properties)
|
||||
if (!item) {
|
||||
console.warn("Failed to create menu entry", properties && properties.text)
|
||||
return
|
||||
}
|
||||
|
||||
deviceMenu.addItem(menuEntryComponent.createObject(deviceMenu, {text: qsTr("Details"), iconSource: "qrc:/icons/info.svg", functionName: "thingDetails"}))
|
||||
deviceMenu.addItem(item)
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
addMenuEntry({text: qsTr("Rename"), iconSource: "qrc:/icons/edit.svg", functionName: "renameThing"})
|
||||
|
||||
// FIXME: This isn't entirely correct... we should have a way to know if a particular thing is in fact autocreated
|
||||
// This check might be wrong for thingClasses with multiple create methods...
|
||||
if (!root.thing.isChild && !root.thing.thingClass.isAutoCreated()) {
|
||||
addMenuEntry({text: qsTr("Delete"), iconSource: "qrc:/icons/delete.svg", functionName: "deleteThing"})
|
||||
addMenuEntry({text: qsTr("Reconfigure"), iconSource: "qrc:/icons/configure.svg", functionName: "reconfigureThing"})
|
||||
}
|
||||
|
||||
addMenuEntry({text: qsTr("Details"), iconSource: "qrc:/icons/info.svg", functionName: "thingDetails"})
|
||||
}
|
||||
|
||||
function renameThing() {
|
||||
@ -106,8 +113,8 @@ SettingsPageBase {
|
||||
|
||||
Connections {
|
||||
target: engine.thingManager
|
||||
onRemoveThingReply: {
|
||||
if (d.pendingCommand != commandId) {
|
||||
function onRemoveThingReply(commandId, thingError, ruleIds) {
|
||||
if (d.pendingCommand !== commandId) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -140,6 +147,7 @@ SettingsPageBase {
|
||||
prominentSubText: false
|
||||
progressive: false
|
||||
}
|
||||
|
||||
NymeaItemDelegate {
|
||||
Layout.fillWidth: true
|
||||
text: root.thing.thingClass.displayName
|
||||
@ -191,6 +199,7 @@ SettingsPageBase {
|
||||
|
||||
StateTypesProxy {
|
||||
id: ioModel
|
||||
|
||||
stateTypes: root.thing.thingClass.stateTypes
|
||||
digitalInputs: true
|
||||
digitalOutputs: true
|
||||
@ -200,13 +209,14 @@ SettingsPageBase {
|
||||
|
||||
Repeater {
|
||||
model: ioModel
|
||||
|
||||
delegate: NymeaSwipeDelegate {
|
||||
Layout.fillWidth: true
|
||||
|
||||
iconName: "qrc:/icons/io-connections.svg"
|
||||
text: model.displayName
|
||||
subText: {
|
||||
if (ioStateType.ioType == Types.IOTypeDigitalInput || ioStateType.ioType == Types.IOTypeAnalogInput) {
|
||||
if (ioStateType.ioType === Types.IOTypeDigitalInput || ioStateType.ioType === Types.IOTypeAnalogInput) {
|
||||
if (inputConnectionWatcher.ioConnection) {
|
||||
return "%1: %2".arg(inputConnectionWatcher.outputThing.name).arg(inputConnectionWatcher.outputStateType.displayName)
|
||||
}
|
||||
@ -223,14 +233,17 @@ SettingsPageBase {
|
||||
|
||||
IOInputConnectionWatcher {
|
||||
id: inputConnectionWatcher
|
||||
|
||||
ioConnections: engine.thingManager.ioConnections
|
||||
inputThingId: root.thing.id
|
||||
inputStateTypeId: ioStateType.id
|
||||
property Thing outputThing: ioConnection ? engine.thingManager.things.getThing(ioConnection.outputThingId) : null
|
||||
property StateType outputStateType: ioConnection ? outputThing.thingClass.stateTypes.getStateType(ioConnection.outputStateTypeId) : null
|
||||
}
|
||||
|
||||
IOOutputConnectionWatcher {
|
||||
id: outputConnectionWatcher
|
||||
|
||||
ioConnections: engine.thingManager.ioConnections
|
||||
outputThingId: root.thing.id
|
||||
outputStateTypeId: ioStateType.id
|
||||
@ -253,6 +266,7 @@ SettingsPageBase {
|
||||
|
||||
Repeater {
|
||||
id: settingsRepeater
|
||||
|
||||
model: root.thing.settings
|
||||
delegate: ParamDelegate {
|
||||
Layout.fillWidth: true
|
||||
@ -360,7 +374,7 @@ SettingsPageBase {
|
||||
property IOInputConnectionWatcher inputWatcher: null
|
||||
property IOOutputConnectionWatcher outputWatcher: null
|
||||
|
||||
readonly property bool isInput: ioConnectionDialog.ioStateType.ioType == Types.IOTypeDigitalInput || ioConnectionDialog.ioStateType.ioType == Types.IOTypeAnalogInput
|
||||
readonly property bool isInput: ioConnectionDialog.ioStateType.ioType == Types.IOTypeDigitalInput || ioConnectionDialog.ioStateType.ioType === Types.IOTypeAnalogInput
|
||||
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
@ -377,16 +391,16 @@ SettingsPageBase {
|
||||
model: ThingsProxy {
|
||||
id: connectableIODevices
|
||||
engine: _engine
|
||||
showDigitalInputs: ioConnectionDialog.ioStateType.ioType == Types.IOTypeDigitalOutput
|
||||
showDigitalOutputs: ioConnectionDialog.ioStateType.ioType == Types.IOTypeDigitalInput
|
||||
showAnalogInputs: ioConnectionDialog.ioStateType.ioType == Types.IOTypeAnalogOutput
|
||||
showAnalogOutputs: ioConnectionDialog.ioStateType.ioType == Types.IOTypeAnalogInput
|
||||
showDigitalInputs: ioConnectionDialog.ioStateType.ioType === Types.IOTypeDigitalOutput
|
||||
showDigitalOutputs: ioConnectionDialog.ioStateType.ioType === Types.IOTypeDigitalInput
|
||||
showAnalogInputs: ioConnectionDialog.ioStateType.ioType === Types.IOTypeAnalogOutput
|
||||
showAnalogOutputs: ioConnectionDialog.ioStateType.ioType === Types.IOTypeAnalogInput
|
||||
}
|
||||
textRole: "name"
|
||||
Layout.fillWidth: true
|
||||
Component.onCompleted: {
|
||||
for (var i = 0; i < connectableIODevices.count; i++) {
|
||||
if (ioConnectionDialog.ioStateType.ioType == Types.IOTypeDigitalInput || ioConnectionDialog.ioStateType.ioType == Types.IOTypeAnalogInput) {
|
||||
if (ioConnectionDialog.ioStateType.ioType === Types.IOTypeDigitalInput || ioConnectionDialog.ioStateType.ioType === Types.IOTypeAnalogInput) {
|
||||
if (connectableIODevices.get(i).id === ioConnectionDialog.inputWatcher.ioConnection.outputThingId) {
|
||||
ioThingComboBox.currentIndex = i;
|
||||
break;
|
||||
@ -407,10 +421,10 @@ SettingsPageBase {
|
||||
model: StateTypesProxy {
|
||||
id: connectableStateTypes
|
||||
stateTypes: connectableIODevices.get(ioThingComboBox.currentIndex).thingClass.stateTypes
|
||||
digitalInputs: ioConnectionDialog.ioStateType.ioType == Types.IOTypeDigitalOutput
|
||||
digitalOutputs: ioConnectionDialog.ioStateType.ioType == Types.IOTypeDigitalInput
|
||||
analogInputs: ioConnectionDialog.ioStateType.ioType == Types.IOTypeAnalogOutput
|
||||
analogOutputs: ioConnectionDialog.ioStateType.ioType == Types.IOTypeAnalogInput
|
||||
digitalInputs: ioConnectionDialog.ioStateType.ioType === Types.IOTypeDigitalOutput
|
||||
digitalOutputs: ioConnectionDialog.ioStateType.ioType === Types.IOTypeDigitalInput
|
||||
analogInputs: ioConnectionDialog.ioStateType.ioType === Types.IOTypeAnalogOutput
|
||||
analogOutputs: ioConnectionDialog.ioStateType.ioType === Types.IOTypeAnalogInput
|
||||
}
|
||||
textRole: "displayName"
|
||||
Layout.fillWidth: true
|
||||
@ -418,7 +432,7 @@ SettingsPageBase {
|
||||
// print("loading for:", ioConnectionDialog.inputWatcher.ioConnection.outputStateTypeId)
|
||||
for (var i = 0; i < connectableStateTypes.count; i++) {
|
||||
print("checking:", connectableStateTypes.get(i).id)
|
||||
if (ioConnectionDialog.ioStateType.ioType == Types.IOTypeDigitalInput || ioConnectionDialog.ioStateType.ioType == Types.IOTypeAnalogInput) {
|
||||
if (ioConnectionDialog.ioStateType.ioType === Types.IOTypeDigitalInput || ioConnectionDialog.ioStateType.ioType === Types.IOTypeAnalogInput) {
|
||||
if (connectableStateTypes.get(i).id === ioConnectionDialog.inputWatcher.ioConnection.outputStateTypeId) {
|
||||
ioStateComboBox.currentIndex = i;
|
||||
break;
|
||||
@ -442,6 +456,7 @@ SettingsPageBase {
|
||||
|
||||
CheckBox {
|
||||
id: invertCheckBox
|
||||
|
||||
checked: ioConnectionDialog.isInput ? ioConnectionDialog.inputWatcher.ioConnection.inverted : ioConnectionDialog.outputWatcher.ioConnection.inverted
|
||||
}
|
||||
}
|
||||
@ -453,7 +468,7 @@ SettingsPageBase {
|
||||
|
||||
columns: width > (cancelButton.implicitWidth + disconnectButton.implicitWidth + connectButton.implicitWidth)
|
||||
? 4 : 1
|
||||
layoutDirection: columns == 1 ? Qt.RightToLeft : Qt.LeftToRight
|
||||
layoutDirection: columns === 1 ? Qt.RightToLeft : Qt.LeftToRight
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
@ -473,8 +488,8 @@ SettingsPageBase {
|
||||
Layout.fillWidth: buttonGrid.columns === 1
|
||||
|
||||
onClicked: {
|
||||
if (ioConnectionDialog.ioStateType.ioType == Types.IOTypeDigitalInput
|
||||
|| ioConnectionDialog.ioStateType.ioType == Types.IOTypeAnalogInput) {
|
||||
if (ioConnectionDialog.ioStateType.ioType === Types.IOTypeDigitalInput
|
||||
|| ioConnectionDialog.ioStateType.ioType === Types.IOTypeAnalogInput) {
|
||||
engine.thingManager.disconnectIO(ioConnectionDialog.inputWatcher.ioConnection.id);
|
||||
} else {
|
||||
engine.thingManager.disconnectIO(ioConnectionDialog.outputWatcher.ioConnection.id);
|
||||
@ -495,8 +510,8 @@ SettingsPageBase {
|
||||
var inputStateTypeId;
|
||||
var outputThingId;
|
||||
var outputStateTypeId;
|
||||
if (ioConnectionDialog.ioStateType.ioType == Types.IOTypeDigitalInput
|
||||
|| ioConnectionDialog.ioStateType.ioType == Types.IOTypeAnalogInput) {
|
||||
if (ioConnectionDialog.ioStateType.ioType === Types.IOTypeDigitalInput
|
||||
|| ioConnectionDialog.ioStateType.ioType === Types.IOTypeAnalogInput) {
|
||||
inputThingId = root.thing.id;
|
||||
inputStateTypeId = ioConnectionDialog.ioStateType.id;
|
||||
outputThingId = connectableIODevices.get(ioThingComboBox.currentIndex).id;
|
||||
|
||||
@ -156,13 +156,12 @@ Page {
|
||||
|
||||
Connections {
|
||||
target: engine.thingManager
|
||||
onPairThingReply: {
|
||||
function onPairThingReply(commandId, thingError, pairingTransactionId, setupMethod, displayMessage, oAuthUrl) {
|
||||
busyOverlay.shown = false
|
||||
if (thingError !== Thing.ThingErrorNoError) {
|
||||
busyOverlay.shown = false;
|
||||
internalPageStack.push(resultsPage, {thingError: thingError, message: displayMessage});
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
d.pairingTransactionId = pairingTransactionId;
|
||||
@ -179,17 +178,21 @@ Page {
|
||||
break;
|
||||
default:
|
||||
print("Setup method reply not handled:", setupMethod);
|
||||
break;
|
||||
}
|
||||
}
|
||||
onConfirmPairingReply: {
|
||||
|
||||
function onConfirmPairingReply(commandId, thingError, thingId, displayMessage) {
|
||||
busyOverlay.shown = false
|
||||
internalPageStack.push(resultsPage, {thingError: thingError, thingId: thingId, message: displayMessage})
|
||||
}
|
||||
onAddThingReply: {
|
||||
|
||||
function onAddThingReply(commandId, thingError, thingId, displayMessage) {
|
||||
busyOverlay.shown = false;
|
||||
internalPageStack.push(resultsPage, {thingError: thingError, thingId: thingId, message: displayMessage})
|
||||
}
|
||||
onReconfigureThingReply: {
|
||||
|
||||
function onReconfigureThingReply(commandId, thingError, displayMessage) {
|
||||
busyOverlay.shown = false;
|
||||
internalPageStack.push(resultsPage, {thingError: thingError, thingId: root.thing.id, message: displayMessage})
|
||||
}
|
||||
@ -372,7 +375,7 @@ Page {
|
||||
Component.onCompleted: {
|
||||
if (root.thingClass.id.toString().match(/\{?f0dd4c03-0aca-42cc-8f34-9902457b05de\}?/)) {
|
||||
console.warn("checking Notification permission!")
|
||||
if (PlatformPermissions.notificationsPermission != PlatformPermissions.PermissionStatusGranted) {
|
||||
if (PlatformPermissions.notificationsPermission !== PlatformPermissions.PermissionStatusGranted) {
|
||||
console.warn("Notification permission missing!")
|
||||
PlatformPermissions.requestPermission(PlatformPermissions.PermissionNotifications)
|
||||
}
|
||||
@ -460,6 +463,11 @@ Page {
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: Style.margins
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: usernameTextField
|
||||
Layout.fillWidth: true
|
||||
@ -468,6 +476,11 @@ Page {
|
||||
visible: pairingPage.setupMethod === "SetupMethodUserAndPassword"
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: Style.margins
|
||||
}
|
||||
|
||||
PasswordTextField {
|
||||
id: pinTextField
|
||||
Layout.fillWidth: true
|
||||
@ -476,7 +489,6 @@ Page {
|
||||
signup: false
|
||||
}
|
||||
|
||||
|
||||
Button {
|
||||
Layout.fillWidth: true
|
||||
Layout.margins: app.margins
|
||||
@ -549,8 +561,9 @@ Page {
|
||||
|
||||
WebView {
|
||||
id: oAuthWebView
|
||||
anchors.fill: parent
|
||||
|
||||
url: oAuthPage.oAuthUrl
|
||||
anchors.fill: parent
|
||||
|
||||
function finishProcess(url) {
|
||||
print("Confirm pairing")
|
||||
@ -559,7 +572,7 @@ Page {
|
||||
oAuthWebView.visible = false
|
||||
}
|
||||
|
||||
onUrlChanged: {
|
||||
onUrlChanged: (url) => {
|
||||
print("OAUTH URL changed", url)
|
||||
if (url.toString().indexOf("https://127.0.0.1") == 0) {
|
||||
print("Redirect URL detected!")
|
||||
|
||||
Reference in New Issue
Block a user