From 0ea07bd508ea27598accf29ac77df32ac27b3cff Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Tue, 21 Jan 2020 14:43:05 +0100 Subject: [PATCH] Add support for imperial unit conversion --- libnymea-app-core/libnymea-app-core.h | 10 +- libnymea-app-core/libnymea-app-core.pro | 5 +- libnymea-app-core/models/logsmodelng.cpp | 23 +- libnymea-common/libnymea-common.pro | 1 + libnymea-common/types/paramtype.h | 1 + libnymea-common/types/types.cpp | 222 ++++++++++++++++++ libnymea-common/types/types.h | 45 +++- nymea-app/translations/nymea-app-de.ts | 21 ++ nymea-app/translations/nymea-app-en.ts | 21 ++ nymea-app/translations/nymea-app-en_US.ts | 21 ++ nymea-app/translations/nymea-app-ko.ts | 21 ++ nymea-app/ui/Nymea.qml | 9 +- .../appsettings/LookAndFeelSettingsPage.qml | 18 ++ nymea-app/ui/components/Dial.qml | 3 +- nymea-app/ui/components/Graph.qml | 5 +- nymea-app/ui/customviews/GenericTypeGraph.qml | 2 +- nymea-app/ui/customviews/SensorView.qml | 2 +- nymea-app/ui/delegates/ParamDelegate.qml | 6 +- .../ui/delegates/ParamDescriptorDelegate.qml | 11 +- nymea-app/ui/delegates/ThingTile.qml | 4 +- .../statedelegates/NumberLabelDelegate.qml | 3 +- .../statedelegates/SliderDelegate.qml | 3 +- .../statedelegates/SpinBoxDelegate.qml | 4 + .../devicelistpages/SensorsDeviceListPage.qml | 9 +- .../SmartMeterDeviceListPage.qml | 2 +- nymea-app/ui/devicepages/DeviceLogPage.qml | 4 +- .../ui/devicepages/GenericDevicePage.qml | 10 +- .../ui/mainviews/DevicesPageDelegate.qml | 2 +- nymea-app/ui/system/LogViewerPage.qml | 3 +- 29 files changed, 444 insertions(+), 47 deletions(-) create mode 100644 libnymea-common/types/types.cpp diff --git a/libnymea-app-core/libnymea-app-core.h b/libnymea-app-core/libnymea-app-core.h index a9d21c28..cea924a8 100644 --- a/libnymea-app-core/libnymea-app-core.h +++ b/libnymea-app-core/libnymea-app-core.h @@ -74,6 +74,7 @@ #include "scripting/completionmodel.h" #include "types/script.h" #include "types/scripts.h" +#include "types/types.h" #include @@ -93,6 +94,13 @@ static QObject* awsClientProvider(QQmlEngine *engine, QJSEngine *scriptEngine) return AWSClient::instance(); } +static QObject* typesProvider(QQmlEngine *engine, QJSEngine *scriptEngine) +{ + Q_UNUSED(engine) + Q_UNUSED(scriptEngine) + return Types::instance(); +} + void registerQmlTypes() { const char uri[] = "Nymea"; @@ -104,7 +112,7 @@ void registerQmlTypes() { qmlRegisterUncreatableType(uri, 1, 0, "NymeaConnection", "Can't create this in QML. Get it from the Engine."); // libnymea-common - qmlRegisterUncreatableType(uri, 1, 0, "Types", "Can't create this in QML. Get it from the Engine."); + qmlRegisterSingletonType(uri, 1, 0, "Types", typesProvider); qmlRegisterUncreatableType(uri, 1, 0, "ParamType", "Can't create this in QML. Get it from the ParamTypes."); qmlRegisterUncreatableType(uri, 1, 0, "ParamTypes", "Can't create this in QML. Get it from the DeviceClass."); diff --git a/libnymea-app-core/libnymea-app-core.pro b/libnymea-app-core/libnymea-app-core.pro index 9cd42144..3079594c 100644 --- a/libnymea-app-core/libnymea-app-core.pro +++ b/libnymea-app-core/libnymea-app-core.pro @@ -86,7 +86,7 @@ SOURCES += \ configuration/mqttpolicy.cpp \ configuration/mqttpolicies.cpp \ models/devicemodel.cpp \ - system/systemcontroller.cpp + system/systemcontroller.cpp \ HEADERS += \ configuration/networkmanager.h \ @@ -153,8 +153,7 @@ HEADERS += \ configuration/mqttpolicy.h \ configuration/mqttpolicies.h \ models/devicemodel.h \ - system/systemcontroller.h - + system/systemcontroller.h \ ubports: { DEFINES += UBPORTS diff --git a/libnymea-app-core/models/logsmodelng.cpp b/libnymea-app-core/models/logsmodelng.cpp index c030ab52..83bcf281 100644 --- a/libnymea-app-core/models/logsmodelng.cpp +++ b/libnymea-app-core/models/logsmodelng.cpp @@ -226,10 +226,16 @@ void LogsModelNg::logsReply(const QVariantMap &data) for (int i = 0; i < newBlock.count(); i++) { LogEntry *entry = newBlock.at(i); m_list.insert(offset + i, entry); + Device *dev = m_engine->deviceManager()->devices()->getDevice(entry->deviceId()); + if (!dev) { + qWarning() << "Device not found in system. Cannot add item to graph series."; + continue; + } + + StateType *entryStateType = dev->deviceClass()->stateTypes()->getStateType(entry->typeId()); if (m_graphSeries) { - Device *dev = m_engine->deviceManager()->devices()->getDevice(entry->deviceId()); - if (dev && dev->deviceClass()->stateTypes()->getStateType(entry->typeId())->type() == "Bool") { + if (entryStateType->type() == "Bool") { // We don't want bools painting triangles, add a toggle point to keep lines straight if (i > 0) { @@ -265,18 +271,19 @@ void LogsModelNg::logsReply(const QVariantMap &data) // Add a pint in the future to extend the graph (so it can scroll with time and the graph wouldn't end at the last known value) if (m_graphSeries->count() == 0) { - m_graphSeries->append(QPointF(QDateTime::currentDateTime().addDays(1).toMSecsSinceEpoch(), entry->value().toReal())); + m_graphSeries->append(QPointF(QDateTime::currentDateTime().addDays(1).toMSecsSinceEpoch(), Types::instance()->toUiValue(entry->value(), entryStateType->unit()).toReal())); } // Add the actual value - m_graphSeries->append(QPointF(entry->timestamp().toMSecsSinceEpoch(), entry->value().toReal())); + QVariant value = Types::instance()->toUiValue(entry->value(), entryStateType->unit()); + m_graphSeries->append(QPointF(entry->timestamp().toMSecsSinceEpoch(), value.toReal())); // Adjust min/max - if (!newMin.isValid() || newMin > entry->value()) { - newMin = entry->value().toReal(); + if (!newMin.isValid() || newMin > value) { + newMin = value.toReal(); } - if (!newMax.isValid() || newMax < entry->value()) { - newMax = entry->value().toReal(); + if (!newMax.isValid() || newMax < value) { + newMax = value.toReal(); } } } diff --git a/libnymea-common/libnymea-common.pro b/libnymea-common/libnymea-common.pro index fb80b51f..26206534 100644 --- a/libnymea-common/libnymea-common.pro +++ b/libnymea-common/libnymea-common.pro @@ -76,6 +76,7 @@ SOURCES += \ types/repository.cpp \ types/script.cpp \ types/scripts.cpp \ + types/types.cpp \ types/vendor.cpp \ types/vendors.cpp \ types/deviceclass.cpp \ diff --git a/libnymea-common/types/paramtype.h b/libnymea-common/types/paramtype.h index aaaf56fc..b31b6806 100644 --- a/libnymea-common/types/paramtype.h +++ b/libnymea-common/types/paramtype.h @@ -42,6 +42,7 @@ class ParamType : public QObject Q_PROPERTY(QVariant minValue READ minValue CONSTANT) Q_PROPERTY(QVariant maxValue READ maxValue CONSTANT) Q_PROPERTY(Types::InputType inputType READ inputType CONSTANT) + Q_PROPERTY(Types::Unit unit READ unit CONSTANT) Q_PROPERTY(QString unitString READ unitString CONSTANT) Q_PROPERTY(QVariantList allowedValues READ allowedValues CONSTANT) Q_PROPERTY(bool readOnly READ readOnly CONSTANT) diff --git a/libnymea-common/types/types.cpp b/libnymea-common/types/types.cpp new file mode 100644 index 00000000..b2ba196f --- /dev/null +++ b/libnymea-common/types/types.cpp @@ -0,0 +1,222 @@ +#include "types.h" + +#include + +Types *Types::s_instance = nullptr; + +Types::Types(QObject *parent) : QObject(parent) +{ + +} + +Types *Types::instance() +{ + if (!s_instance) { + s_instance = new Types(); + } + return s_instance; +} + +Types::UnitSystem Types::unitSystem() const +{ + return m_unitSystem; +} + +void Types::setUnitSystem(Types::UnitSystem unitSystem) +{ + if (m_unitSystem != unitSystem) { + m_unitSystem = unitSystem; + emit unitSystemChanged(); + } +} + +QString Types::toUiUnit(Types::Unit unit) const +{ + Types::Unit uiUnit = unit; + if (m_unitSystem == UnitSystemImperial) { + switch (unit) { + case Types::UnitDegreeCelsius: + uiUnit = Types::UnitDegreeFahrenheit; + break; + case Types::UnitGram: + uiUnit = Types::UnitOunce; + break; + case Types::UnitKiloGram: + uiUnit = Types::UnitPound; + break; + case Types::UnitMilliMeter: + case Types::UnitCentiMeter: + uiUnit = Types::UnitInch; + break; + case Types::UnitMeter: + uiUnit = Types::UnitFoot; + break; + case Types::UnitKiloMeter: + uiUnit = Types::UnitMile; + break; + case Types::UnitMeterPerSecond: + uiUnit = Types::UnitFootPerSecond; + break; + case Types::UnitKiloMeterPerHour: + uiUnit = Types::UnitMilePerHour; + break; + default: + uiUnit = unit; + } + } + switch (uiUnit) { + case Types::UnitNone: + return ""; + case Types::UnitSeconds: + return "s"; + case Types::UnitMinutes: + return "m"; + case Types::UnitHours: + return "h"; + case Types::UnitUnixTime: + return "datetime"; + case Types::UnitMeterPerSecond: + return "m/s"; + case Types::UnitKiloMeterPerHour: + return "km/h"; + case Types::UnitDegree: + return "°"; + case Types::UnitRadiant: + return "rad"; + case Types::UnitDegreeCelsius: + return "°C"; + case Types::UnitDegreeKelvin: + return "°K"; + case Types::UnitMired: + return "mir"; + case Types::UnitMilliBar: + return "mbar"; + case Types::UnitBar: + return "bar"; + case Types::UnitPascal: + return "Pa"; + case Types::UnitHectoPascal: + return "hPa"; + case Types::UnitAtmosphere: + return "atm"; + case Types::UnitLumen: + return "lm"; + case Types::UnitLux: + return "lx"; + case Types::UnitCandela: + return "cd"; + case Types::UnitMilliMeter: + return "mm"; + case Types::UnitCentiMeter: + return "cm"; + case Types::UnitMeter: + return "m"; + case Types::UnitKiloMeter: + return "km"; + case Types::UnitGram: + return "g"; + case Types::UnitKiloGram: + return "kg"; + case Types::UnitDezibel: + return "db"; + case Types::UnitBpm: + return "bpm"; + case Types::UnitKiloByte: + return "kB"; + case Types::UnitMegaByte: + return "MB"; + case Types::UnitGigaByte: + return "GB"; + case Types::UnitTeraByte: + return "TB"; + case Types::UnitMilliWatt: + return "mW"; + case Types::UnitWatt: + return "W"; + case Types::UnitKiloWatt: + return "kW"; + case Types::UnitKiloWattHour: + return "kWh"; + case Types::UnitEuroPerMegaWattHour: + return "€/MWh"; + case Types::UnitEuroCentPerKiloWattHour: + return "ct/kWh"; + case Types::UnitPercentage: + return "%"; + case Types::UnitPartsPerMillion: + return "ppm"; + case Types::UnitEuro: + return "€"; + case Types::UnitDollar: + return "$"; + case Types::UnitHertz: + return "Hz"; + case Types::UnitAmpere: + return "A"; + case Types::UnitMilliAmpere: + return "mA"; + case Types::UnitVolt: + return "V"; + case Types::UnitMilliVolt: + return "mV"; + case Types::UnitVoltAmpere: + return "VA"; + case Types::UnitVoltAmpereReactive: + return "VAR"; + case Types::UnitAmpereHour: + return "Ah"; + case Types::UnitMicroSiemensPerCentimeter: + return "µS/cm"; + case Types::UnitDuration: + return "s"; + + // Units not in nymea:core + case Types::UnitDegreeFahrenheit: + return "°F"; + case Types::UnitOunce: + return "oz"; + case Types::UnitPound: + return "lb"; + case Types::UnitInch: + return "in"; + case Types::UnitFoot: + return "ft"; + case Types::UnitMile: + return "mi"; + case Types::UnitFootPerSecond: + return "fps"; + case Types::UnitMilePerHour: + return "mph"; + } + + return ""; +} + +QVariant Types::toUiValue(const QVariant &value, Types::Unit unit) const +{ + if (m_unitSystem == UnitSystemImperial) { + switch (unit) { + case Types::UnitDegreeCelsius: // To Fahrenheit + return (value.toDouble() * 9/5) + 32; + case Types::UnitGram: // To Ounce + return value.toDouble() / 28.35; + case Types::UnitKiloGram: // To Pound + return value.toDouble() * 2.205; + case Types::UnitMilliMeter: // To Inch + return value.toDouble() / 25.4; + case Types::UnitCentiMeter: // To Inch + return value.toDouble() / 2.54; + case Types::UnitMeter: // To Feet + return value.toDouble() * 3.281; + case Types::UnitKiloMeter: // To Mile + return value.toDouble() / 1.609; + case Types::UnitMeterPerSecond: // To foot per second + return value.toDouble() * 3.281; + case Types::UnitKiloMeterPerHour: + return value.toDouble() / 1.609; + default: + return value; + } + } + return value; +} diff --git a/libnymea-common/types/types.h b/libnymea-common/types/types.h index 6fdfa33e..5ec36eda 100644 --- a/libnymea-common/types/types.h +++ b/libnymea-common/types/types.h @@ -24,12 +24,12 @@ #define TYPES_H #include +#include -class Types +class Types: public QObject { - Q_GADGET - Q_ENUMS(InputType) - Q_ENUMS(Unit) + Q_OBJECT + Q_PROPERTY(UnitSystem unitSystem READ unitSystem WRITE setUnitSystem NOTIFY unitSystemChanged) public: enum InputType { @@ -44,6 +44,7 @@ public: InputTypeUrl, InputTypeMacAddress }; + Q_ENUM(InputType) enum Unit { UnitNone, @@ -97,10 +98,42 @@ public: UnitVoltAmpereReactive, UnitAmpereHour, UnitMicroSiemensPerCentimeter, - UnitDuration - }; + UnitDuration, + // Those do not exist in nymea:core at this point, Adding them for easier conversion to imperial + UnitDegreeFahrenheit, + UnitOunce, + UnitPound, + UnitInch, + UnitFoot, + UnitMile, + UnitFootPerSecond, + UnitMilePerHour, + }; + Q_ENUM(Unit) + + enum UnitSystem { + UnitSystemMetric, + UnitSystemImperial + }; + Q_ENUM(UnitSystem) + + static Types* instance(); + + UnitSystem unitSystem() const; + void setUnitSystem(UnitSystem unitSystem); + + Q_INVOKABLE QString toUiUnit(Types::Unit unit) const; + Q_INVOKABLE QVariant toUiValue(const QVariant &value, Types::Unit unit) const; + +signals: + void unitSystemChanged(); + +private: Types(QObject *parent = nullptr); + static Types *s_instance; + + UnitSystem m_unitSystem = UnitSystemMetric; }; #endif // TYPES_H diff --git a/nymea-app/translations/nymea-app-de.ts b/nymea-app/translations/nymea-app-de.ts index e91e7bca..ed0b4568 100644 --- a/nymea-app/translations/nymea-app-de.ts +++ b/nymea-app/translations/nymea-app-de.ts @@ -2904,6 +2904,18 @@ Bitte versuche es erneut. Automatic Automatisch + + Unit system + Einheitensystem + + + Metric + Metrisch + + + Imperial + Imperialistisch + MagicPage @@ -3886,6 +3898,15 @@ Möchtest Du fortfahren? Accounts Konten + + Smartlocks + Smartlocks + + + smartlock + Select ... + Smartlock + NymeaConnection diff --git a/nymea-app/translations/nymea-app-en.ts b/nymea-app/translations/nymea-app-en.ts index cf630de5..b85c126b 100644 --- a/nymea-app/translations/nymea-app-en.ts +++ b/nymea-app/translations/nymea-app-en.ts @@ -2242,6 +2242,18 @@ Please try again. Automatic + + Unit system + + + + Metric + + + + Imperial + + MagicPage @@ -3044,6 +3056,15 @@ Please try again. Accounts + + Smartlocks + + + + smartlock + Select ... + + NymeaConnection diff --git a/nymea-app/translations/nymea-app-en_US.ts b/nymea-app/translations/nymea-app-en_US.ts index cf630de5..b85c126b 100644 --- a/nymea-app/translations/nymea-app-en_US.ts +++ b/nymea-app/translations/nymea-app-en_US.ts @@ -2242,6 +2242,18 @@ Please try again. Automatic + + Unit system + + + + Metric + + + + Imperial + + MagicPage @@ -3044,6 +3056,15 @@ Please try again. Accounts + + Smartlocks + + + + smartlock + Select ... + + NymeaConnection diff --git a/nymea-app/translations/nymea-app-ko.ts b/nymea-app/translations/nymea-app-ko.ts index 98fbf6e9..29323f2c 100644 --- a/nymea-app/translations/nymea-app-ko.ts +++ b/nymea-app/translations/nymea-app-ko.ts @@ -2294,6 +2294,18 @@ Please try again. Automatic + + Unit system + + + + Metric + + + + Imperial + + MagicPage @@ -3107,6 +3119,15 @@ Please try again. Accounts + + Smartlocks + + + + smartlock + Select ... + + NymeaConnection diff --git a/nymea-app/ui/Nymea.qml b/nymea-app/ui/Nymea.qml index 173566df..f764619f 100644 --- a/nymea-app/ui/Nymea.qml +++ b/nymea-app/ui/Nymea.qml @@ -45,6 +45,7 @@ ApplicationWindow { property string cloudEnvironment: "Community" property bool showConnectionTabs: false property int tabCount: 1 + property string units: "metric" // or "imperial" } property string privacyPolicyUrl: "https://nymea.io/privacy-statement/en/nymea_privacy.html" @@ -55,6 +56,12 @@ ApplicationWindow { PlatformHelper.bottomPanelColor = Material.background } + Binding { + target: Types + property: "unitSystem" + value: settings.units === "metric" ? Types.UnitSystemMetric : Types.UnitSystemImperial + } + RootItem { id: rootItem anchors.fill: parent @@ -65,7 +72,7 @@ ApplicationWindow { id: discovery objectName: "discovery" awsClient: AWSClient -// discovering: pageStack.currentItem.objectName === "discoveryPage" + // discovering: pageStack.currentItem.objectName === "discoveryPage" } property alias _discovery: discovery diff --git a/nymea-app/ui/appsettings/LookAndFeelSettingsPage.qml b/nymea-app/ui/appsettings/LookAndFeelSettingsPage.qml index f6eeac96..605cef34 100644 --- a/nymea-app/ui/appsettings/LookAndFeelSettingsPage.qml +++ b/nymea-app/ui/appsettings/LookAndFeelSettingsPage.qml @@ -83,6 +83,24 @@ Page { } } + RowLayout { + Layout.fillWidth: true + Layout.leftMargin: app.margins + Layout.rightMargin: app.margins + Label { + Layout.fillWidth: true + text: qsTr("Unit system") + } + ComboBox { + id: unitsComboBox + currentIndex: settings.units === "metric" ? 0 : 1 + model: [ qsTr("Metric"), qsTr("Imperial") ] + onActivated: { + settings.units = index == 0 ? "metric" : "imperial"; + } + } + } + CheckDelegate { Layout.fillWidth: true text: qsTr("Return to home on idle") diff --git a/nymea-app/ui/components/Dial.qml b/nymea-app/ui/components/Dial.qml index 56395aac..921c5bfc 100644 --- a/nymea-app/ui/components/Dial.qml +++ b/nymea-app/ui/components/Dial.qml @@ -90,7 +90,8 @@ ColumnLayout { Label { id: topLabel Layout.fillWidth: true - text: rotateMouseArea.currentValue + (dial.stateType ? dial.stateType.unitString : "") + property var unit: dial.stateType ? dial.stateType.unit : Types.UnitNone + text: Types.toUiValue(rotateMouseArea.currentValue, unit) + Types.toUiUnit(unit) font.pixelSize: app.largeFont * 1.5 horizontalAlignment: Text.AlignHCenter visible: dial.showValueLabel && dial.stateType !== null diff --git a/nymea-app/ui/components/Graph.qml b/nymea-app/ui/components/Graph.qml index 6691519a..70980ac4 100644 --- a/nymea-app/ui/components/Graph.qml +++ b/nymea-app/ui/components/Graph.qml @@ -164,10 +164,11 @@ Item { ctx.strokeStyle = Material.foreground ctx.fillStyle = Material.foreground ctx.lineWidth = 0; - var label = root.stateType ? root.stateType.unitString : "" + var unit = root.stateType ? root.stateType.unit : Types.UnitNone + var label = Types.toUiUnit(unit) var textSize = ctx.measureText(label) ctx.text(label, -textSize.width - app.margins, height + app.margins + app.smallFont) -// ctx.stroke(); + ctx.stroke(); ctx.fill() ctx.closePath() diff --git a/nymea-app/ui/customviews/GenericTypeGraph.qml b/nymea-app/ui/customviews/GenericTypeGraph.qml index bb49843c..309db71f 100644 --- a/nymea-app/ui/customviews/GenericTypeGraph.qml +++ b/nymea-app/ui/customviews/GenericTypeGraph.qml @@ -64,7 +64,7 @@ Item { Layout.fillWidth: true text: root.stateType.type.toLowerCase() === "bool" ? root.stateType.displayName - : 1.0 * Math.round(root.valueState.value * Math.pow(10, root.roundTo)) / Math.pow(10, root.roundTo) + " " + root.stateType.unitString + : 1.0 * Math.round(Types.toUiValue(root.valueState.value, root.stateType.unit) * Math.pow(10, root.roundTo)) / Math.pow(10, root.roundTo) + " " + Types.toUiUnit(root.stateType.unit) font.pixelSize: app.largeFont } diff --git a/nymea-app/ui/customviews/SensorView.qml b/nymea-app/ui/customviews/SensorView.qml index 0a1ba567..3ed884a2 100644 --- a/nymea-app/ui/customviews/SensorView.qml +++ b/nymea-app/ui/customviews/SensorView.qml @@ -60,7 +60,7 @@ CustomViewBase { color: app.interfaceToColor(root.interfaceName) } Label { - text: deviceState.value + " " + stateType.unitString + text: Types.toUiValue(deviceState.value, stateType.unit) + " " + Types.toUiUnit(stateType.unit) font.pixelSize: app.largeFont } diff --git a/nymea-app/ui/delegates/ParamDelegate.qml b/nymea-app/ui/delegates/ParamDelegate.qml index c5d123d2..2ed3c183 100644 --- a/nymea-app/ui/delegates/ParamDelegate.qml +++ b/nymea-app/ui/delegates/ParamDelegate.qml @@ -145,7 +145,7 @@ ItemDelegate { } } Label { - text: root.param.value.toFixed(slider.decimals) + root.paramType.unitString + text: Types.toUiValue(root.param.value, root.paramType.unit).toFixed(slider.decimals) + Types.toUiUnit(root.paramType.unit) } } @@ -170,7 +170,7 @@ ItemDelegate { width: 150 onValueModified: root.param.value = value textFromValue: function(value) { - return value + return Types.toUiValue(value, root.paramType.unit) } Component.onCompleted: { if (root.value === undefined) { @@ -179,7 +179,7 @@ ItemDelegate { } } Label { - text: root.paramType.unitString + text: Types.toUiUnit(root.paramType.unit) visible: text.length > 0 } } diff --git a/nymea-app/ui/delegates/ParamDescriptorDelegate.qml b/nymea-app/ui/delegates/ParamDescriptorDelegate.qml index 17cf896c..bcabea10 100644 --- a/nymea-app/ui/delegates/ParamDescriptorDelegate.qml +++ b/nymea-app/ui/delegates/ParamDescriptorDelegate.qml @@ -106,7 +106,7 @@ ItemDelegate { } Label { - text: paramType.unitString + text: Types.toUiUnit(paramType.unit) } } @@ -132,9 +132,9 @@ ItemDelegate { text: { switch (root.paramType.type.toLowerCase()) { case "double": - return Math.round(root.value * 10) / 10 + return Math.round(Types.toUiValue(root.value, root.paramType.unit) * 10) / 10 } - return root.value + return Types.toUiValue(root.value, root.paramType.unit) } } } @@ -153,10 +153,11 @@ ItemDelegate { id: sliderComponent RowLayout { spacing: app.margins - Label { text: root.paramType.minValue } + Label { text: Types.toUiValue(root.paramType.minValue, root.paramType.unit) } Slider { from: paramType.minValue to: paramType.maxValue + value: root.value stepSize: { switch (root.paramType.type.toLowerCase()) { case "double": @@ -169,7 +170,7 @@ ItemDelegate { root.value = value; } } - Label { text: root.paramType.maxValue } + Label { text: Types.toUiValue(root.paramType.maxValue, root.paramType.unit) } } } diff --git a/nymea-app/ui/delegates/ThingTile.qml b/nymea-app/ui/delegates/ThingTile.qml index 47dbb6d8..b6e10dd8 100644 --- a/nymea-app/ui/delegates/ThingTile.qml +++ b/nymea-app/ui/delegates/ThingTile.qml @@ -209,13 +209,13 @@ MainPageTile { Label { Layout.fillWidth: true horizontalAlignment: Text.AlignRight - text: sensorsRoot.currentStateType.unitString + text: Types.toUiUnit(sensorsRoot.currentStateType.unit) font.pixelSize: app.smallFont } Label { Layout.fillWidth: true horizontalAlignment: Text.AlignRight - text: sensorsRoot.currentState.value// + " " + sensorsRoot.currentStateType.unitString + text: Math.round(Types.toUiValue(sensorsRoot.currentState.value, sensorsRoot.currentStateType.unit) * 100) / 100 elide: Text.ElideRight } } diff --git a/nymea-app/ui/delegates/statedelegates/NumberLabelDelegate.qml b/nymea-app/ui/delegates/statedelegates/NumberLabelDelegate.qml index 2ac99a57..36bdea12 100644 --- a/nymea-app/ui/delegates/statedelegates/NumberLabelDelegate.qml +++ b/nymea-app/ui/delegates/statedelegates/NumberLabelDelegate.qml @@ -7,6 +7,7 @@ import "../../components" Label { property var value - text: Math.round(value * 100) / 100 + property var unit: Types.UnitNone + text: Math.round(Types.toUiValue(value, unit) * 100) / 100 horizontalAlignment: Text.AlignRight } diff --git a/nymea-app/ui/delegates/statedelegates/SliderDelegate.qml b/nymea-app/ui/delegates/statedelegates/SliderDelegate.qml index 54dc2848..3b8eea83 100644 --- a/nymea-app/ui/delegates/statedelegates/SliderDelegate.qml +++ b/nymea-app/ui/delegates/statedelegates/SliderDelegate.qml @@ -11,6 +11,7 @@ RowLayout { signal changed(var value) property var value + property var unit: Types.UnitNone property alias from: slider.from property alias to: slider.to @@ -52,6 +53,6 @@ RowLayout { } } Label { - text: slider.value.toFixed(root.decimals) + text: Types.toUiValue(slider.value, root.unit).toFixed(root.decimals) } } diff --git a/nymea-app/ui/delegates/statedelegates/SpinBoxDelegate.qml b/nymea-app/ui/delegates/statedelegates/SpinBoxDelegate.qml index 57347e5a..8658fbc6 100644 --- a/nymea-app/ui/delegates/statedelegates/SpinBoxDelegate.qml +++ b/nymea-app/ui/delegates/statedelegates/SpinBoxDelegate.qml @@ -9,8 +9,12 @@ SpinBox { width: 150 signal changed(var value) stepSize: Math.min(10, (to - from) / 10) + property var unit: Types.UnitNone editable: true onValueModified: { changed(value) } + textFromValue: function(value) { + return Types.toUiValue(value, unit) + } } diff --git a/nymea-app/ui/devicelistpages/SensorsDeviceListPage.qml b/nymea-app/ui/devicelistpages/SensorsDeviceListPage.qml index e86641f5..7759f0b8 100644 --- a/nymea-app/ui/devicelistpages/SensorsDeviceListPage.qml +++ b/nymea-app/ui/devicelistpages/SensorsDeviceListPage.qml @@ -104,7 +104,7 @@ DeviceListPageBase { color: { switch (model.interfaceName) { case "closablesensor": - return sensorValueDelegate.stateValue.value === true ? "green" : "red"; + return sensorValueDelegate.stateValue && sensorValueDelegate.stateValue.value === true ? "green" : "red"; default: return app.interfaceToColor(model.interfaceName) } @@ -112,7 +112,7 @@ DeviceListPageBase { name: { switch (model.interfaceName) { case "closablesensor": - return sensorValueDelegate.stateValue.value === true ? Qt.resolvedUrl("../images/lock-closed.svg") : Qt.resolvedUrl("../images/lock-open.svg"); + return sensorValueDelegate.stateValue && sensorValueDelegate.stateValue.value === true ? Qt.resolvedUrl("../images/lock-closed.svg") : Qt.resolvedUrl("../images/lock-open.svg"); default: return app.interfaceToIcon(model.interfaceName) } @@ -121,15 +121,16 @@ DeviceListPageBase { Label { Layout.fillWidth: true + property var unit: sensorValueDelegate.stateType ? sensorValueDelegate.stateType.unit : Types.UnitNone text: { switch (model.interfaceName) { case "closablesensor": - return sensorValueDelegate.stateValue.value === true ? qsTr("is closed") : qsTr("is open"); + return sensorValueDelegate.stateValue && sensorValueDelegate.stateValue.value === true ? qsTr("is closed") : qsTr("is open"); default: return sensorValueDelegate.stateType && sensorValueDelegate.stateType.type.toLowerCase() === "bool" ? sensorValueDelegate.stateType.displayName : sensorValueDelegate.stateValue - ? "%1 %2".arg(Math.round(sensorValueDelegate.stateValue.value * 100) / 100).arg(sensorValueDelegate.stateType.unitString) + ? "%1 %2".arg(Math.round(Types.toUiValue(sensorValueDelegate.stateValue.value, unit) * 100) / 100).arg(Types.toUiUnit(unit)) : "" } } diff --git a/nymea-app/ui/devicelistpages/SmartMeterDeviceListPage.qml b/nymea-app/ui/devicelistpages/SmartMeterDeviceListPage.qml index 4f1e324a..515bc1ce 100644 --- a/nymea-app/ui/devicelistpages/SmartMeterDeviceListPage.qml +++ b/nymea-app/ui/devicelistpages/SmartMeterDeviceListPage.qml @@ -110,7 +110,7 @@ DeviceListPageBase { Label { Layout.fillWidth: true text: sensorValueDelegate.stateValue - ? "%1 %2".arg(1.0 * Math.round(sensorValueDelegate.stateValue.value * 100000) / 100000).arg(sensorValueDelegate.stateType.unitString) + ? "%1 %2".arg(1.0 * Math.round(Types.toUiValue(sensorValueDelegate.stateValue.value, sensorValueDelegate.stateType.unit) * 100000) / 100000).arg(Types.toUiUnit(sensorValueDelegate.stateType.unit)) : "" elide: Text.ElideRight verticalAlignment: Text.AlignVCenter diff --git a/nymea-app/ui/devicepages/DeviceLogPage.qml b/nymea-app/ui/devicepages/DeviceLogPage.qml index 27086dcb..68a8fa6c 100644 --- a/nymea-app/ui/devicepages/DeviceLogPage.qml +++ b/nymea-app/ui/devicepages/DeviceLogPage.qml @@ -229,11 +229,11 @@ Page { return labelComponent } - Binding { target: valueLoader.item; property: "value"; value: model.value } + Binding { target: valueLoader.item; property: "value"; value: Types.toUiValue(model.value, entryDelegate.stateType.unit) } Binding { target: entryDelegate.stateType && valueLoader.item.hasOwnProperty("unitString") ? valueLoader.item : null; property: "unitString" - value: entryDelegate.stateType ? entryDelegate.stateType.unitString : "" + value: entryDelegate.stateType ? Types.toUiUnit(entryDelegate.stateType.unit) : "" } } } diff --git a/nymea-app/ui/devicepages/GenericDevicePage.qml b/nymea-app/ui/devicepages/GenericDevicePage.qml index b89d5798..1cdc099f 100644 --- a/nymea-app/ui/devicepages/GenericDevicePage.qml +++ b/nymea-app/ui/devicepages/GenericDevicePage.qml @@ -125,8 +125,8 @@ DevicePageBase { Layout.fillWidth: true } Label { - visible: stateDelegate.stateType.unit !== Types.UnitUnixTime && stateDelegate.stateType.unitString.length > 0 - text: stateDelegate.stateType.unitString + visible: stateDelegate.stateType.unit !== Types.UnitUnixTime && stateDelegate.stateType.unit !== Types.UnitUnixTime + text: Types.toUiUnit(stateDelegate.stateType.unit) } Component.onCompleted: updateLoader() @@ -202,6 +202,7 @@ DevicePageBase { possibleValues: stateDelegate.stateType.allowedValues, from: minValue, to: maxValue, + unit: stateDelegate.stateType.unit, writable: isWritable, stateType: stateDelegate.stateType }) @@ -237,6 +238,11 @@ DevicePageBase { value: stateDelegate.deviceState.value when: !stateDelegate.valueCacheDirty && stateDelegate.pendingActionId === -1 } + Binding { + target: stateDelegateLoader.item.hasOwnProperty("unit") ? stateDelegateLoader.item : null + property: "unit" + value: stateDelegate.stateType.unit + } Connections { target: stateDelegateLoader.item && stateDelegateLoader.item.hasOwnProperty("changed") ? stateDelegateLoader.item : null diff --git a/nymea-app/ui/mainviews/DevicesPageDelegate.qml b/nymea-app/ui/mainviews/DevicesPageDelegate.qml index 1345cb0a..62cc87fd 100644 --- a/nymea-app/ui/mainviews/DevicesPageDelegate.qml +++ b/nymea-app/ui/mainviews/DevicesPageDelegate.qml @@ -560,7 +560,7 @@ MainPageTile { Label { text: sensorsRoot.shownStateType - ? Math.round(sensorsRoot.device.states.getState(shownStateType.id).value * 100) / 100 + " " + sensorsRoot.shownStateType.unitString + ? (Math.round(Types.toUiValue(sensorsRoot.device.states.getState(shownStateType.id).value, sensorsRoot.shownStateType.unit) * 100) / 100) + " " + Types.toUiUnit(sensorsRoot.shownStateType.unit) : "" // font.pixelSize: app.smallFont Layout.fillWidth: true diff --git a/nymea-app/ui/system/LogViewerPage.qml b/nymea-app/ui/system/LogViewerPage.qml index 0219517b..e9818fca 100644 --- a/nymea-app/ui/system/LogViewerPage.qml +++ b/nymea-app/ui/system/LogViewerPage.qml @@ -147,7 +147,8 @@ Page { text : { switch (model.source) { case LogEntry.LoggingSourceStates: - return "%1 -> %2".arg(delegate.deviceClass.stateTypes.getStateType(model.typeId).displayName).arg(model.value); + var stateType = delegate.deviceClass.stateTypes.getStateType(model.typeId); + return "%1 -> %2 %3".arg(stateType.displayName).arg(Types.toUiValue(model.value, stateType.unit)).arg(Types.toUiUnit(stateType.unit)); case LogEntry.LoggingSourceSystem: return model.loggingEventType === LogEntry.LoggingEventTypeActiveChange ? qsTr("System started") : "N/A" case LogEntry.LoggingSourceActions: