From f946f8c76bdbd84f0571e3be88c040033f834077 Mon Sep 17 00:00:00 2001
From: Don Gagne <don@thegagnes.com>
Date: Sun, 25 Oct 2015 13:29:41 -0700
Subject: [PATCH] Decimal place support from meta data

---
 src/FactSystem/Fact.cc                       | 27 ++++++++++++++++-
 src/FactSystem/Fact.h                        | 34 +++++++++++-----------
 src/FactSystem/FactMetaData.cc               | 43 +++++++++++++++-------------
 src/FactSystem/FactMetaData.h                | 27 ++++++++++-------
 src/FirmwarePlugin/PX4/PX4ParameterLoader.cc | 13 +++++++++
 src/MissionItem.cc                           | 15 +++-------
 6 files changed, 100 insertions(+), 59 deletions(-)

diff --git a/src/FactSystem/Fact.cc b/src/FactSystem/Fact.cc
index a69b258..09441f6 100644
--- a/src/FactSystem/Fact.cc
+++ b/src/FactSystem/Fact.cc
@@ -131,7 +131,22 @@ QVariant Fact::value(void) const
 
 QString Fact::valueString(void) const
 {
-    return _value.toString();
+    QString valueString;
+
+    switch (type()) {
+        case FactMetaData::valueTypeFloat:
+            qDebug() << name() << value() << decimalPlaces();
+            valueString = QString("%1").arg(value().toFloat(), 0, 'g', decimalPlaces());
+            break;
+        case FactMetaData::valueTypeDouble:
+            valueString = QString("%1").arg(value().toDouble(), 0, 'g', decimalPlaces());
+            break;
+        default:
+            valueString = value().toString();
+            break;
+    }
+
+    return valueString;
 }
 
 QVariant Fact::defaultValue(void) const
@@ -222,6 +237,16 @@ bool Fact::maxIsDefaultForType(void) const
     }
 }
 
+int Fact::decimalPlaces(void) const
+{
+    if (_metaData) {
+        return _metaData->decimalPlaces();
+    } else {
+        qWarning() << "Meta data pointer missing";
+        return FactMetaData::defaultDecimalPlaces;
+    }
+}
+
 QString Fact::group(void) const
 {
     if (_metaData) {
diff --git a/src/FactSystem/Fact.h b/src/FactSystem/Fact.h
index da8a85e..c946b19 100644
--- a/src/FactSystem/Fact.h
+++ b/src/FactSystem/Fact.h
@@ -46,22 +46,23 @@ public:
 
     const Fact& operator=(const Fact& other);
 
-    Q_PROPERTY(int componentId READ componentId CONSTANT)
-    Q_PROPERTY(QString name READ name CONSTANT)
-    Q_PROPERTY(QVariant value READ value WRITE setValue NOTIFY valueChanged USER true)
-    Q_PROPERTY(QVariant valueString READ valueString NOTIFY valueChanged)
-    Q_PROPERTY(QString units READ units CONSTANT)
-    Q_PROPERTY(QVariant defaultValue READ defaultValue CONSTANT)
-    Q_PROPERTY(bool defaultValueAvailable READ defaultValueAvailable CONSTANT)
-    Q_PROPERTY(bool valueEqualsDefault READ valueEqualsDefault NOTIFY valueChanged)
-    Q_PROPERTY(FactMetaData::ValueType_t type READ type CONSTANT)
-    Q_PROPERTY(QString shortDescription READ shortDescription CONSTANT)
-    Q_PROPERTY(QString longDescription READ longDescription CONSTANT)
-    Q_PROPERTY(QVariant min READ min CONSTANT)
-    Q_PROPERTY(bool minIsDefaultForType READ minIsDefaultForType CONSTANT)
-    Q_PROPERTY(QVariant max READ max CONSTANT)
-    Q_PROPERTY(bool maxIsDefaultForType READ maxIsDefaultForType CONSTANT)
-    Q_PROPERTY(QString group READ group CONSTANT)
+    Q_PROPERTY(int      componentId             READ componentId                            CONSTANT)
+    Q_PROPERTY(QString  group                   READ group                                  CONSTANT)
+    Q_PROPERTY(QString  name                    READ name                                   CONSTANT)
+    Q_PROPERTY(QVariant value                   READ value                  WRITE setValue  NOTIFY valueChanged USER true)
+    Q_PROPERTY(QVariant valueString             READ valueString                            NOTIFY valueChanged)
+    Q_PROPERTY(QString  units                   READ units                                  CONSTANT)
+    Q_PROPERTY(QVariant defaultValue            READ defaultValue                           CONSTANT)
+    Q_PROPERTY(bool     defaultValueAvailable   READ defaultValueAvailable                  CONSTANT)
+    Q_PROPERTY(bool     valueEqualsDefault      READ valueEqualsDefault                     NOTIFY valueChanged)
+    Q_PROPERTY(FactMetaData::ValueType_t type   READ type                                   CONSTANT)
+    Q_PROPERTY(QString  shortDescription        READ shortDescription                       CONSTANT)
+    Q_PROPERTY(QString  longDescription         READ longDescription                        CONSTANT)
+    Q_PROPERTY(QVariant min                     READ min                                    CONSTANT)
+    Q_PROPERTY(bool     minIsDefaultForType     READ minIsDefaultForType                    CONSTANT)
+    Q_PROPERTY(QVariant max                     READ max                                    CONSTANT)
+    Q_PROPERTY(bool     maxIsDefaultForType     READ maxIsDefaultForType                    CONSTANT)
+    Q_PROPERTY(int      decimalPlaces           READ decimalPlaces                          CONSTANT)
     
     /// Convert and validate value
     ///     @param convertOnly true: validate type conversion only, false: validate against meta data as well
@@ -86,6 +87,7 @@ public:
     QVariant max(void) const;
     bool maxIsDefaultForType(void) const;
     QString group(void) const;
+    int decimalPlaces(void) const;
     
     /// Sets and sends new value to vehicle even if value is the same
     void forceSetValue(const QVariant& value);
diff --git a/src/FactSystem/FactMetaData.cc b/src/FactSystem/FactMetaData.cc
index 7360e65..942d4e3 100644
--- a/src/FactSystem/FactMetaData.cc
+++ b/src/FactSystem/FactMetaData.cc
@@ -32,30 +32,32 @@
 
 #include <limits>
 
-FactMetaData::FactMetaData(QObject* parent) :
-    QObject(parent),
-    _group("*Default Group"),
-    _type(valueTypeInt32),
-    _defaultValue(0),
-    _defaultValueAvailable(false),
-    _min(_minForType()),
-    _max(_maxForType()),
-    _minIsDefaultForType(true),
-    _maxIsDefaultForType(true)
+FactMetaData::FactMetaData(QObject* parent)
+    : QObject(parent)
+    , _group("*Default Group")
+    , _type(valueTypeInt32)
+    , _defaultValue(0)
+    , _defaultValueAvailable(false)
+    , _min(_minForType())
+    , _max(_maxForType())
+    , _minIsDefaultForType(true)
+    , _maxIsDefaultForType(true)
+    , _decimalPlaces(defaultDecimalPlaces)
 {
 
 }
 
-FactMetaData::FactMetaData(ValueType_t type, QObject* parent) :
-    QObject(parent),
-    _group("*Default Group"),
-    _type(type),
-    _defaultValue(0),
-    _defaultValueAvailable(false),
-    _min(_minForType()),
-    _max(_maxForType()),
-    _minIsDefaultForType(true),
-    _maxIsDefaultForType(true)
+FactMetaData::FactMetaData(ValueType_t type, QObject* parent)
+    : QObject(parent)
+    , _group("*Default Group")
+    , _type(type)
+    , _defaultValue(0)
+    , _defaultValueAvailable(false)
+    , _min(_minForType())
+    , _max(_maxForType())
+    , _minIsDefaultForType(true)
+    , _maxIsDefaultForType(true)
+    , _decimalPlaces(defaultDecimalPlaces)
 {
 
 }
@@ -76,6 +78,7 @@ const FactMetaData& FactMetaData::operator=(const FactMetaData& other)
     _max                    = other._max;
     _minIsDefaultForType    = other._minIsDefaultForType;
     _maxIsDefaultForType    = other._maxIsDefaultForType;
+    _decimalPlaces          = other._decimalPlaces;
     
     return *this;
 }
diff --git a/src/FactSystem/FactMetaData.h b/src/FactSystem/FactMetaData.h
index 49c72d8..03c78d2 100644
--- a/src/FactSystem/FactMetaData.h
+++ b/src/FactSystem/FactMetaData.h
@@ -59,18 +59,19 @@ public:
     const FactMetaData& operator=(const FactMetaData& other);
 
     // Property accessors
-    QString     name(void) const                  { return _name; }
-    QString     group(void) const                 { return _group; }
-    ValueType_t type(void) const                  { return _type; }
+    QString     name(void) const                    { return _name; }
+    QString     group(void) const                   { return _group; }
+    ValueType_t type(void) const                    { return _type; }
     QVariant    defaultValue(void) const;
-    bool		defaultValueAvailable(void) const { return _defaultValueAvailable; }
-    QString     shortDescription(void) const      { return _shortDescription; }
-    QString     longDescription(void) const       { return _longDescription;}
-    QString     units(void) const                 { return _units; }
-    QVariant    min(void) const                   { return _min; }
-    QVariant    max(void) const                   { return _max; }
-    bool        minIsDefaultForType(void) const   { return _minIsDefaultForType; }
-    bool        maxIsDefaultForType(void) const   { return _maxIsDefaultForType; }
+    bool		defaultValueAvailable(void) const   { return _defaultValueAvailable; }
+    QString     shortDescription(void) const        { return _shortDescription; }
+    QString     longDescription(void) const         { return _longDescription;}
+    QString     units(void) const                   { return _units; }
+    QVariant    min(void) const                     { return _min; }
+    QVariant    max(void) const                     { return _max; }
+    bool        minIsDefaultForType(void) const     { return _minIsDefaultForType; }
+    bool        maxIsDefaultForType(void) const     { return _maxIsDefaultForType; }
+    int         decimalPlaces(void) const           { return _decimalPlaces; }
 
     // Property setters
     void setName(const QString& name)                           { _name = name; }
@@ -81,6 +82,7 @@ public:
     void setUnits(const QString& units)                         { _units = units; }
     void setMin(const QVariant& max);
     void setMax(const QVariant& max);
+    void setDecimalPlaces(int decimalPlaces)                    { _decimalPlaces = decimalPlaces; }
     
     /// Converts the specified value, validating against meta data
     ///     @param value Value to convert, can be string
@@ -90,6 +92,8 @@ public:
     /// @returns false: Convert failed, errorString set
     bool convertAndValidate(const QVariant& value, bool convertOnly, QVariant& typedValue, QString& errorString);
 
+    static const int defaultDecimalPlaces = 3;
+
 private:
     QVariant _minForType(void) const;
     QVariant _maxForType(void) const;
@@ -106,6 +110,7 @@ private:
     QVariant    _max;
     bool        _minIsDefaultForType;
     bool        _maxIsDefaultForType;
+    int         _decimalPlaces;
 };
 
 #endif
diff --git a/src/FirmwarePlugin/PX4/PX4ParameterLoader.cc b/src/FirmwarePlugin/PX4/PX4ParameterLoader.cc
index aea72c1..c7d989d 100644
--- a/src/FirmwarePlugin/PX4/PX4ParameterLoader.cc
+++ b/src/FirmwarePlugin/PX4/PX4ParameterLoader.cc
@@ -299,6 +299,19 @@ void PX4ParameterLoader::loadParameterFactMetaData(void)
                         qCDebug(PX4ParameterLoaderLog) << "Unit:" << text;
                         metaData->setUnits(text);
                         
+                    } else if (elementName == "decimal") {
+                        Q_ASSERT(metaData);
+                        QString text = xml.readElementText();
+                        qCDebug(PX4ParameterLoaderLog) << "Decimal:" << text;
+
+                        bool convertOk;
+                        QVariant varDecimals = QVariant(text).toUInt(&convertOk);
+                        if (convertOk) {
+                            metaData->setDecimalPlaces(varDecimals.toInt());
+                        } else {
+                            qCWarning(PX4ParameterLoaderLog) << "Invalid decimals value, name:" << metaData->name() << " type:" << metaData->type() << " decimals:" << text << " error: invalid number";
+                        }
+
                     } else {
                         qDebug() << "Unknown element in XML: " << elementName;
                     }
diff --git a/src/MissionItem.cc b/src/MissionItem.cc
index 0d0943e..4e3f9d1 100644
--- a/src/MissionItem.cc
+++ b/src/MissionItem.cc
@@ -20,15 +20,6 @@ This file is part of the QGROUNDCONTROL project
 
 ======================================================================*/
 
-/**
- * @file
- *   @brief MissionItem class
- *
- *   @author Benjamin Knecht <mavteam@student.ethz.ch>
- *   @author Petri Tanskanen <mavteam@student.ethz.ch>
- *
- */
-
 #include <QStringList>
 #include <QDebug>
 
@@ -115,10 +106,12 @@ MissionItem::MissionItem(QObject*       parent,
     
     FactMetaData* latitudeMetaData = new FactMetaData(FactMetaData::valueTypeDouble, _latitudeFact);
     latitudeMetaData->setUnits("deg");
-    
+    latitudeMetaData->setDecimalPlaces(7);
+
     FactMetaData* longitudeMetaData = new FactMetaData(FactMetaData::valueTypeDouble, _longitudeFact);
     longitudeMetaData->setUnits("deg");
-    
+    longitudeMetaData->setDecimalPlaces(7);
+
     FactMetaData* altitudeMetaData = new FactMetaData(FactMetaData::valueTypeDouble, _altitudeFact);
     altitudeMetaData->setUnits("meters");