Update ParamDelegates and many small improvements

This commit is contained in:
Simon Stürz 2026-02-24 15:42:49 +01:00
parent 1431e7001e
commit 28ce85b561
14 changed files with 154 additions and 102 deletions

View File

@ -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");
}

View File

@ -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();

View File

@ -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";

View File

@ -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);

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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) => {

View File

@ -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) {

View File

@ -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
}
}
}

View File

@ -61,7 +61,7 @@ NymeaSwipeDelegate {
operatorString = " = ";
break;
case ParamDescriptor.ValueOperatorNotEquals:
operatorString = " != ";
operatorString = " !== ";
break;
case ParamDescriptor.ValueOperatorGreater:
operatorString = " > ";

View File

@ -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

View File

@ -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;

View File

@ -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!")