]> sigrok.org Git - pulseview.git/blobdiff - pv/util.cpp
Util: Fix malformed time formatting
[pulseview.git] / pv / util.cpp
index cf42eb16f25b78a11c5fbef9db610c8f58d9cda0..029ae079b64fcea1253bc66ed5fead8f7969f757 100644 (file)
@@ -39,6 +39,7 @@ static const QString SIPrefixes[17] =
        "T", "P", "E", "Z", "Y"};
 const int FirstSIPrefix = 8;
 const int FirstSIPrefixPower = -(FirstSIPrefix * 3);
        "T", "P", "E", "Z", "Y"};
 const int FirstSIPrefix = 8;
 const int FirstSIPrefixPower = -(FirstSIPrefix * 3);
+const double MinTimeDelta = 1e-15; // Anything below 1 fs can be considered zero
 
 QString format_si_value(double v, QString unit, int prefix,
        unsigned int precision, bool sign)
 
 QString format_si_value(double v, QString unit, int prefix,
        unsigned int precision, bool sign)
@@ -118,7 +119,7 @@ static QString format_time_in_full(double t, signed precision, bool force_sign)
        if (precision >= 0) {
                ts << pad_number(seconds, use_padding ? 2 : 0);
 
        if (precision >= 0) {
                ts << pad_number(seconds, use_padding ? 2 : 0);
 
-               const double fraction = fabs(t - whole_seconds);
+               const double fraction = fabs(t) - whole_seconds;
 
                if (precision > 0 && precision < 1000) {
                        QString fs = QString("%1").arg(fraction, -(2 + precision), 'f',
 
                if (precision > 0 && precision < 1000) {
                        QString fs = QString("%1").arg(fraction, -(2 + precision), 'f',
@@ -140,45 +141,44 @@ static QString format_time_in_full(double t, signed precision, bool force_sign)
        return s;
 }
 
        return s;
 }
 
+static QString format_time_with_si(double t, QString unit, int prefix,
+       unsigned int precision, bool sign)
+{
+       // The precision is always given without taking the prefix into account
+       // so we need to deduct the number of decimals the prefix might imply
+       const int prefix_order =
+               -(prefix * 3 + pv::util::FirstSIPrefixPower);
+
+       const unsigned int relative_prec =
+               (prefix >= pv::util::FirstSIPrefix) ? precision :
+               std::max((int)(precision - prefix_order), 0);
+
+       return format_si_value(t, unit, prefix, relative_prec, sign);
+}
+
 QString format_time(double t, int prefix, TimeUnit unit,
        unsigned int precision, double step_size, bool sign)
 {
 QString format_time(double t, int prefix, TimeUnit unit,
        unsigned int precision, double step_size, bool sign)
 {
-       // If we have to use samples then we have no alternative formats
-       if (unit == Samples) {
-               // The precision is always given without taking the prefix into account
-               // so we need to deduct the number of decimals the prefix might imply
-               const int prefix_order =
-                       -(prefix * 3 + pv::util::FirstSIPrefixPower);
-
-               const unsigned int relative_prec =
-                       (prefix >= pv::util::FirstSIPrefix) ? precision :
-                       std::max((int)(precision - prefix_order), 0);
+       // Make 0 appear as 0, not random +0 or -0
+       if (fabs(t) < MinTimeDelta)
+               return "0";
 
 
-               return format_si_value(t, "sa", prefix, relative_prec, sign);
-       }
+       // If we have to use samples then we have no alternative formats
+       if (unit == Samples)
+               return format_time_with_si(t, "sa", prefix, precision, sign);
 
 
-       // View zoomed way out -> low precision (0), high step size (>60s)
+       // View zoomed way out -> low precision (0), high step size (>=60s)
        // -> DD:HH:MM
        // -> DD:HH:MM
-       if ((precision == 0) && (step_size >= 60)) {
+       if ((precision == 0) && (step_size >= 60))
                return format_time_in_full(t, -1, sign);
                return format_time_in_full(t, -1, sign);
-       }
 
        // View in "normal" range -> medium precision, medium step size
        // -> HH:MM:SS.mmm... or xxxx (si unit) if less than 60 seconds
        // View zoomed way in -> high precision (>3), low step size (<1s)
        // -> HH:MM:SS.mmm... or xxxx (si unit) if less than 60 seconds
 
        // View in "normal" range -> medium precision, medium step size
        // -> HH:MM:SS.mmm... or xxxx (si unit) if less than 60 seconds
        // View zoomed way in -> high precision (>3), low step size (<1s)
        // -> HH:MM:SS.mmm... or xxxx (si unit) if less than 60 seconds
-       if (abs(t) < 60) {
-               // The precision is always given without taking the prefix into account
-               // so we need to deduct the number of decimals the prefix might imply
-               const int prefix_order =
-                       -(prefix * 3 + pv::util::FirstSIPrefixPower);
-
-               const unsigned int relative_prec =
-                       (prefix >= pv::util::FirstSIPrefix) ? precision :
-                       std::max((int)(precision - prefix_order), 0);
-
-               return format_si_value(t, "s", prefix, relative_prec, sign);
-       } else
+       if (abs(t) < 60)
+               return format_time_with_si(t, "s", prefix, precision, sign);
+       else
                return format_time_in_full(t, precision, sign);
 }
 
                return format_time_in_full(t, precision, sign);
 }