Merge PR #311: Add support for imperial unit conversion

This commit is contained in:
Jenkins nymea 2020-01-21 14:55:48 +01:00
commit 334acd6622
29 changed files with 444 additions and 47 deletions

View File

@ -74,6 +74,7 @@
#include "scripting/completionmodel.h"
#include "types/script.h"
#include "types/scripts.h"
#include "types/types.h"
#include <QtQml/qqml.h>
@ -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<NymeaConnection>(uri, 1, 0, "NymeaConnection", "Can't create this in QML. Get it from the Engine.");
// libnymea-common
qmlRegisterUncreatableType<Types>(uri, 1, 0, "Types", "Can't create this in QML. Get it from the Engine.");
qmlRegisterSingletonType<Types>(uri, 1, 0, "Types", typesProvider);
qmlRegisterUncreatableType<ParamType>(uri, 1, 0, "ParamType", "Can't create this in QML. Get it from the ParamTypes.");
qmlRegisterUncreatableType<ParamTypes>(uri, 1, 0, "ParamTypes", "Can't create this in QML. Get it from the DeviceClass.");

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,222 @@
#include "types.h"
#include <QDebug>
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;
}

View File

@ -24,12 +24,12 @@
#define TYPES_H
#include <QObject>
#include <QVariant>
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

View File

@ -2904,6 +2904,18 @@ Bitte versuche es erneut.</translation>
<source>Automatic</source>
<translation>Automatisch</translation>
</message>
<message>
<source>Unit system</source>
<translation>Einheitensystem</translation>
</message>
<message>
<source>Metric</source>
<translation>Metrisch</translation>
</message>
<message>
<source>Imperial</source>
<translation>Imperialistisch</translation>
</message>
</context>
<context>
<name>MagicPage</name>
@ -3886,6 +3898,15 @@ Möchtest Du fortfahren?</translation>
<source>Accounts</source>
<translation>Konten</translation>
</message>
<message>
<source>Smartlocks</source>
<translation>Smartlocks</translation>
</message>
<message>
<source>smartlock</source>
<extracomment>Select ...</extracomment>
<translation>Smartlock</translation>
</message>
</context>
<context>
<name>NymeaConnection</name>

View File

@ -2242,6 +2242,18 @@ Please try again.</source>
<source>Automatic</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unit system</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Metric</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Imperial</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>MagicPage</name>
@ -3044,6 +3056,15 @@ Please try again.</source>
<source>Accounts</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Smartlocks</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>smartlock</source>
<extracomment>Select ...</extracomment>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>NymeaConnection</name>

View File

@ -2242,6 +2242,18 @@ Please try again.</source>
<source>Automatic</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unit system</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Metric</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Imperial</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>MagicPage</name>
@ -3044,6 +3056,15 @@ Please try again.</source>
<source>Accounts</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Smartlocks</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>smartlock</source>
<extracomment>Select ...</extracomment>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>NymeaConnection</name>

View File

@ -2294,6 +2294,18 @@ Please try again.</source>
<source>Automatic</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unit system</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Metric</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Imperial</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>MagicPage</name>
@ -3107,6 +3119,15 @@ Please try again.</source>
<source>Accounts</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Smartlocks</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>smartlock</source>
<extracomment>Select ...</extracomment>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>NymeaConnection</name>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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