swift
pqstring.cpp
1 // SPDX-FileCopyrightText: Copyright (C) 2013 swift Project Community / Contributors
2 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3 
4 #include "misc/pq/pqstring.h"
5 
6 #include <QLocale>
7 #include <QRegularExpression>
8 #include <QtDebug>
9 
10 #include "misc/pq/acceleration.h"
11 #include "misc/pq/angle.h"
12 #include "misc/pq/frequency.h"
13 #include "misc/pq/length.h"
14 #include "misc/pq/mass.h"
16 #include "misc/pq/pressure.h"
17 #include "misc/pq/speed.h"
18 #include "misc/pq/temperature.h"
19 #include "misc/pq/time.h"
20 #include "misc/pq/units.h"
21 
22 SWIFT_DEFINE_VALUEOBJECT_MIXINS(swift::misc::physical_quantities, CPqString)
23 
24 namespace swift::misc::physical_quantities
25 {
26  QString CPqString::convertToQString(bool ) const { return m_string; }
27 
28  CVariant CPqString::parseToVariant(const QString &value, SeparatorMode mode)
29  {
30  CVariant v;
31 
32  // fine tuning of the string
33  const QString vs = value.trimmed().simplified();
34 
35  // check
36  if (vs.isEmpty()) { return v; }
37 
38  thread_local const QRegularExpression regex("([-+]?[0-9]*[\\.,]?[0-9]+)\\s*(\\D*)$");
39  const auto match = regex.match(value);
40  if (!match.hasMatch()) { return v; } // not a valid number
41  QString unit = match.captured(2).trimmed();
42  const QString number = QString(value).replace(unit, "");
43  unit = unit.trimmed(); // trim after replace, not before
44 
45  if (unit.isEmpty() || number.isEmpty()) { return v; }
46  bool success;
47  const double numberD = parseNumber(number, success, mode);
48  if (!success) { return v; }
49 
50  if (CMeasurementUnit::isValidUnitSymbol<CAccelerationUnit>(unit))
51  {
52  const CAcceleration pq(numberD, CMeasurementUnit::unitFromSymbol<CAccelerationUnit>(unit, false));
53  return CVariant::from(pq);
54  }
55 
56  if (CMeasurementUnit::isValidUnitSymbol<CAngleUnit>(unit))
57  {
58  const CAngle pq(numberD, CMeasurementUnit::unitFromSymbol<CAngleUnit>(unit, false));
59  return CVariant::from(pq);
60  }
61 
62  if (CMeasurementUnit::isValidUnitSymbol<CFrequencyUnit>(unit))
63  {
64  const CFrequency pq(numberD, CMeasurementUnit::unitFromSymbol<CFrequencyUnit>(unit, false));
65  return CVariant::from(pq);
66  }
67 
68  if (CMeasurementUnit::isValidUnitSymbol<CLengthUnit>(unit))
69  {
70  const CLength pq(numberD, CMeasurementUnit::unitFromSymbol<CLengthUnit>(unit, false));
71  return CVariant::from(pq);
72  }
73 
74  if (CMeasurementUnit::isValidUnitSymbol<CMassUnit>(unit))
75  {
76  const CMass pq(numberD, CMeasurementUnit::unitFromSymbol<CMassUnit>(unit, false));
77  return CVariant::from(pq);
78  }
79 
80  if (CMeasurementUnit::isValidUnitSymbol<CPressureUnit>(unit))
81  {
82  const CPressure pq(numberD, CMeasurementUnit::unitFromSymbol<CPressureUnit>(unit, false));
83  return CVariant::from(pq);
84  }
85 
86  if (CMeasurementUnit::isValidUnitSymbol<CSpeedUnit>(unit))
87  {
88  const CSpeed pq(numberD, CMeasurementUnit::unitFromSymbol<CSpeedUnit>(unit, false));
89  return CVariant::from(pq);
90  }
91 
92  if (CMeasurementUnit::isValidUnitSymbol<CTimeUnit>(unit))
93  {
94  const CTime pq(numberD, CMeasurementUnit::unitFromSymbol<CTimeUnit>(unit, false));
95  return CVariant::from(pq);
96  }
97 
98  if (CMeasurementUnit::isValidUnitSymbol<CTemperatureUnit>(unit))
99  {
100  const CTemperature pq(numberD, CMeasurementUnit::unitFromSymbol<CTemperatureUnit>(unit, false));
101  return CVariant::from(pq);
102  }
103  return v;
104  }
105 
106  double CPqString::parseNumber(const QString &number, bool &success, CPqString::SeparatorMode mode)
107  {
108  double numberD = -1;
109  switch (mode)
110  {
111  case SeparatorLocale: numberD = QLocale::system().toDouble(number, &success); break;
112  case SeparatorQtDefault: numberD = number.toDouble(&success); break;
113  case SeparatorBestGuess:
114  numberD = number.toDouble(&success);
115  if (!success) { numberD = QLocale::system().toDouble(number, &success); }
116  break;
117  default: qFatal("Wrong mode"); break;
118  }
119  return numberD;
120  }
121 } // namespace swift::misc::physical_quantities
Wrapper around QVariant which provides transparent access to CValueObject methods of the contained ob...
Definition: variant.h:66
static CVariant from(T &&value)
Synonym for fromValue().
Definition: variant.h:147
Physical unit angle (radians, degrees)
Definition: angle.h:23
Physical unit length (length)
Definition: length.h:18
static CVariant parseToVariant(const QString &value, SeparatorMode mode=SeparatorQtDefault)
Parse a string value like "100m", "10.3Mhz".
Definition: pqstring.cpp:28
SeparatorMode
Number separators / group separators.
Definition: pqstring.h:34
@ SeparatorLocale
depending on QLocale, e.g.
Definition: pqstring.h:36
@ SeparatorQtDefault
100000.00 no group separator
Definition: pqstring.h:35
QString convertToQString(bool i18n=false) const
Cast as QString.
Definition: pqstring.cpp:26
static double parseNumber(const QString &number, bool &success, SeparatorMode mode=SeparatorBestGuess)
Locale aware parsing.
Definition: pqstring.cpp:106
#define SWIFT_DEFINE_VALUEOBJECT_MIXINS(Namespace, Class)
Explicit template definition of mixins for a CValueObject subclass.
Definition: valueobject.h:67