// SPDX-License-Identifier: GPL-3.0-or-later /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright (C) 2013 - 2024, nymea GmbH * Copyright (C) 2024 - 2025, chargebyte austria GmbH * * This file is part of nymea-app. * * nymea-app is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * nymea-app 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 nymea-app. If not, see . * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ import QtQuick import QtQuick.Controls import QtQuick.Layouts import Nymea import "../components" ItemDelegate { id: root property ParamType paramType: null property StateType stateType: null property var value: null property int operatorType: ParamDescriptors.ValueOperatorEquals readonly property string type: paramType ? paramType.type.toLowerCase() : stateType ? stateType.type.toLowerCase() : "" readonly property var minValue: paramType ? paramType.minValue : stateType ? stateType.minValue : undefined readonly property var maxValue: paramType ? paramType.maxValue : stateType ? stateType.maxValue : undefined readonly property var allowedValues: paramType ? paramType.allowedValues : stateType ? stateType.allowedValues : undefined readonly property int unit: paramType ? root.paramType.unit : root.stateType.unit contentItem: ColumnLayout { Label { Layout.fillWidth: true text: root.paramType ? root.paramType.displayName : root.stateType.displayName } RowLayout { Layout.fillWidth: true spacing: app.margins ComboBox { FontMetrics { id: fm } textRole: "text" Layout.fillWidth: true Layout.minimumWidth: { var minWidth = 0; for (var i = 0; i < model.length; i++) { minWidth = Math.max(minWidth, fm.boundingRect(model[i]).width) } return minWidth + 60; } property bool isNumeric: { switch (root.type) { case "bool": case "string": case "qstring": case "color": return false; case "uint": case "int": case "double": return true; } console.warn("ParamDescriptorDelegate: Unhandled data type:", root.type); return false; } model: isNumeric ? numericModel : nonNumericModel ListModel { id: numericModel ListElement { text: qsTr("is equal to"); value: ParamDescriptor.ValueOperatorEquals } ListElement { text: qsTr("is not equal to"); value: ParamDescriptor.ValueOperatorNotEquals } ListElement { text: qsTr("is greater than"); value: ParamDescriptor.ValueOperatorGreater } ListElement { text: qsTr("is less than"); value: ParamDescriptor.ValueOperatorLess } ListElement { text: qsTr("is greater than or equal to"); value: ParamDescriptor.ValueOperatorGreaterOrEqual } ListElement { text: qsTr("is less than or equal to"); value: ParamDescriptor.ValueOperatorLessOrEqual } } ListModel { id: nonNumericModel ListElement { text: qsTr("is"); value: ParamDescriptor.ValueOperatorEquals } ListElement { text: qsTr("is not "); value: ParamDescriptor.ValueOperatorNotEquals } } onCurrentIndexChanged: { root.operatorType = model.get(currentIndex).value print("set operator to", root.operatorType, currentText, currentIndex, model, model.get(currentIndex)) } } Loader { id: placeHolder Layout.fillWidth: true sourceComponent: { print("Datatye is:", root.type, root.minValue, root.maxValue, root.allowedValues) switch (root.type) { case "bool": return boolComponent; case "uint": case "int": case "double": if (root.minValue !== undefined && root.maxValue !== undefined) { return labelComponent; } return spinboxComponent; case "string": case "qstring": case "color": if (root.allowedValues.length > 0) { return comboBoxComponent } return textFieldComponent; } console.warn("ParamDescriptorDelegate: Type delegate not implemented", root.type) return null; } } Label { text: Types.toUiUnit(root.unit) visible: root.unit !== Types.UnitNone } } Loader { Layout.fillWidth: true sourceComponent: { switch (root.type) { case "uint": case "int": case "double": if (root.minValue !== undefined && root.maxValue !== undefined) { return sliderComponent } } } } } Component { id: labelComponent Label { text: { switch (root.type.toLowerCase()) { case "double": return Math.round(Types.toUiValue(root.value, root.unit) * 10) / 10 } return Types.toUiValue(root.value, root.unit) } } } Component { id: textFieldComponent TextField { text: "" onTextChanged: { root.value = text; } Component.onCompleted: { if (root.value == null || root.v^alue == undefined) { root.value = "" } } } } Component { id: sliderComponent RowLayout { spacing: app.margins Label { text: Types.toUiValue(root.minValue, root.unit) } Slider { from: root.minValue to: root.maxValue value: root.value stepSize: { switch (root.type.toLowerCase()) { case "double": return 0.1 } return 1 } Layout.fillWidth: true onMoved: { root.value = value; } Component.onCompleted: { if (root.value == null || root.value == undefined) { root.value = from; } } } Label { text: Types.toUiValue(root.maxValue, root.unit) } } } Component { id: spinboxComponent NymeaSpinBox { from: root.minValue to: root.maxValue value: root.value != undefined ? root.value : 0 onValueModified: root.value = value floatingPoint: root.type === "double" Component.onCompleted: { if (root.value == null || root.v^alue == undefined) { root.value = from } } } } Component { id: boolComponent ComboBox { model: ListModel { ListElement { modelData: "true"; value: true } ListElement { modelData: "false"; value: false } } onCurrentIndexChanged: { root.value = model.get(currentIndex).value } Component.onCompleted: { if (root.value == null || root.v^alue == undefined) { root.value = model.get(currentIndex).value } } } } Component { id: comboBoxComponent ComboBox { model: root.allowedValues onCurrentIndexChanged: { root.value = root.allowedValues[currentIndex] } Component.onCompleted: { if (root.value == null || root.v^alue == undefined) { root.value = root.allowedValues[currentIndex] } } } } }