6 #ifndef SWIFT_MISC_PQ_MEASUREMENTUNIT_H
7 #define SWIFT_MISC_PQ_MEASUREMENTUNIT_H
13 #include <QCoreApplication>
14 #include <QDBusArgument>
17 #include <QSharedData>
18 #include <QSharedDataPointer>
31 namespace swift::misc::physical_quantities
60 static double toDefault(
double value) {
return value; }
68 template <
class Policy>
73 return value * Policy::factor();
77 return value / Policy::factor();
85 template <
class Policy>
90 return (value - Policy::offset()) * Policy::factor();
94 return value / Policy::factor() + Policy::offset();
103 template <
class FactorPolicy,
class SubdivPolicy>
112 return value * FactorPolicy::factor();
119 double remaining = std::fmod(value / FactorPolicy::factor(), 1.0);
120 double part2 = remaining * SubdivPolicy::subfactor();
121 return part1 + part2 / SubdivPolicy::fraction();
130 template <
class FactorPolicy,
class SubdivPolicy>
140 (
CMathUtils::trunc(part2) + part3 / SubdivPolicy::subfactor()) / SubdivPolicy::subfactor();
141 return value * FactorPolicy::factor();
148 double remaining = std::fmod(value / FactorPolicy::factor(), 1.0);
150 remaining = std::fmod(remaining * SubdivPolicy::subfactor(), 1.0);
151 double part3 = remaining * SubdivPolicy::subfactor();
152 return part1 + part2 / SubdivPolicy::fraction() +
153 part3 / (SubdivPolicy::fraction() * SubdivPolicy::fraction());
163 template <
class Policy>
166 static double factor() {
return Policy::factor() * 2.0; }
169 template <
class Policy>
172 static double factor() {
return Policy::factor() / 1000.0; }
175 template <
class Policy>
178 static double factor() {
return Policy::factor() / 100.0; }
181 template <
class Policy>
184 static double factor() {
return Policy::factor() * 100.0; }
187 template <
class Policy>
190 static double factor() {
return Policy::factor() * 1000.0; }
193 template <
class Policy>
196 static double factor() {
return Policy::factor() * 1e+6; }
199 template <
class Policy>
202 static double factor() {
return Policy::factor() * 1e+9; }
205 template <
int Subfactor>
217 template <
class Converter>
218 constexpr
Data(QLatin1String name, QLatin1String symbol, Converter,
int displayDigits = 2,
219 double epsilon = 1e-9)
220 : m_name(name), m_symbol(symbol), m_epsilon(epsilon), m_displayDigits(displayDigits),
221 m_toDefault(Converter::toDefault), m_fromDefault(Converter::fromDefault)
225 constexpr
Data(QLatin1String name, QLatin1String symbol) : m_name(name), m_symbol(symbol) {}
229 double m_epsilon = 0.0;
230 int m_displayDigits = 0;
239 return QLatin1String(str, N - 1);
258 const Data *m_data = (
static_cast<void>(
throw std::logic_error(
"Uninitialized pimpl")),
nullptr);
289 if (&a == &b)
return true;
302 return i18n ? QCoreApplication::translate(
"CMeasurementUnit", m_data->
m_name.latin1()) : m_data->
m_name;
308 return i18n ? QCoreApplication::translate(
"CMeasurementUnit", m_data->
m_symbol.latin1()) : m_data->
m_symbol;
314 const QString c = candidate.trimmed();
315 return c.endsWith(this->getName(
false), cs) || c.endsWith(this->getName(
true)) ||
316 c.endsWith(this->getSymbol(
false), cs) || c.endsWith(this->getSymbol(
true));
321 double roundValue(
double value,
int digits = -1)
const;
325 double roundToEpsilon(
double value)
const;
329 virtual QString makeRoundedQString(
double value,
int digits = -1,
bool withGroupSeparator =
false,
330 bool i18n =
false)
const;
334 virtual QString makeRoundedQStringWithUnit(
double value,
int digits = -1,
bool withGroupSeparator =
false,
335 bool i18n =
false)
const;
349 if (this->isNull())
return false;
350 if (qFuzzyIsNull(value))
return true;
351 return std::abs(value) <= m_data->
m_epsilon;
369 if (symbol.isEmpty()) {
return U::defaultUnit(); }
371 static const bool cs = hasCaseSensitiveSymbols<U>();
372 for (
const auto &unit : U::allUnits())
376 if (unit.getSymbol() == symbol) {
return unit; }
380 if (
stringCompare(unit.getSymbol(), symbol, Qt::CaseInsensitive)) {
return unit; }
383 if (strict) qFatal(
"Illegal unit name");
384 return U::defaultUnit();
393 static const QStringList symbols = [] {
395 for (
const auto &unit : U::allUnits()) { s.push_back(unit.getSymbol()); }
407 static const QStringList symbols = [] {
409 for (
const QString &symbol : allSymbols<U>()) { s.insert(symbol.toLower()); }
421 static const bool cs = [] {
return (allSymbolsLowerCase<U>().size() != allSymbols<U>().size()); }();
432 static const bool cs = hasCaseSensitiveSymbols<U>();
433 return cs ? isValidUnitSymbol<U>(symbol, Qt::CaseSensitive) :
434 isValidUnitSymbol<U>(symbol, Qt::CaseInsensitive);
445 if (symbol.isEmpty())
return false;
446 for (
const auto &unit : U::allUnits())
448 if (
stringCompare(unit.getSymbol(), symbol, caseSensitivity)) {
return true; }
460 Qt::CaseSensitivity caseSensitivity = Qt::CaseSensitive)
462 if (candidate.isEmpty())
return false;
463 for (
const auto &unit : U::allUnits())
465 if (candidate.contains(unit.getSymbol(), caseSensitivity)) {
return true; }
477 Qt::CaseSensitivity caseSensitivity = Qt::CaseSensitive)
479 if (candidate.isEmpty())
return false;
480 for (
const auto &unit : U::allUnits())
482 if (candidate.endsWith(unit.getSymbol(), caseSensitivity)) {
return true; }
static double fract(double value)
Fractional part of value.
static double trunc(double value, double epsilon=1e-10)
Nearest integer not greater in magnitude than value, correcting for epsilon.
CRTP class template from which a derived class can inherit icon-related functions.
CRTP class template from which a derived class can inherit string streaming operations.
Base class for all units, such as meter, hertz.
void marshalToDataStream(QDataStream &stream) const
Marshal a value to a QDataStream.
CMeasurementUnit & operator=(const CMeasurementUnit &)=default
Copy assignment operator.
double(*)(double) ConverterFunction
Pointer to function for converting between units.
friend bool operator==(const CMeasurementUnit &a, const CMeasurementUnit &b)
Equal operator ==.
void unmarshalFromDataStream(QDataStream &)
Unmarshal a value from a QDataStream.
CMeasurementUnit(const Data &&)=delete
Constructor saves the address of its argument, so forbid rvalues.
bool isNull() const
Is unit null?
double getEpsilon() const
Threshold for comparions.
bool isEpsilon(double value) const
Is given value <= epsilon?
CMeasurementUnit(const CMeasurementUnit &)=default
Copy constructor.
friend size_t qHash(const CMeasurementUnit &unit)
qHash overload, needed for storing value in a QSet.
void marshallToDbus(QDBusArgument &argument) const
Marshall without begin/endStructure, for when composed within another object.
friend bool operator!=(const CMeasurementUnit &a, const CMeasurementUnit &b)
Unequal operator !=.
void unmarshallFromDbus(const QDBusArgument &)
Unmarshall without begin/endStructure, for when composed within another object.
int getDisplayDigits() const
Display digits.
static bool isValidUnitSymbol(const QString &symbol)
Valid unit symbol?
bool endsStringWithNameOrSymbol(const QString &candidate, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Does a string end with name or symbol? E.g. 3meter, 3m, 3deg.
CMeasurementUnit(const Data &data)
Constructor.
static bool endWithValidUnitSymbol(const QString &candidate, Qt::CaseSensitivity caseSensitivity=Qt::CaseSensitive)
Ends with valid unit symbol?
QString getSymbol(bool i18n=false) const
Unit name such as "m".
static const QStringList & allSymbols()
All symbols.
QString getName(bool i18n=false) const
Name such as "meter".
static bool containsValidUnitSymbol(const QString &candidate, Qt::CaseSensitivity caseSensitivity=Qt::CaseSensitive)
Contains valid unit symbol?
static CMeasurementUnit None()
Dimensionless unit.
static const QStringList & allSymbolsLowerCase()
All symbols case insensitive.
static bool hasCaseSensitiveSymbols()
Are symbols case sensitive?
static constexpr QLatin1String constQLatin1(const char(&str)[N])
Constant-initialize QLatin1String without using strlen.
static bool isValidUnitSymbol(const QString &symbol, Qt::CaseSensitivity caseSensitivity)
Valid unit symbol?
static U unitFromSymbol(const QString &symbol, bool strict=true)
Unit from symbol.
~CMeasurementUnit()=default
Destructor.
QString convertToQString(bool i18n=false) const
Cast as QString.
SWIFT_MISC_EXPORT bool stringCompare(const QString &c1, const QString &c2, Qt::CaseSensitivity cs)
String compare.
Concrete strategy pattern for converting unit with offset linear conversion.
static double toDefault(double value)
convert from this unit to the default unit
static double fromDefault(double value)
convert to this unit from the default unit
Metapolicy that can be used to modify template parameters of converters.
static double factor()
factor
ConverterFunction m_toDefault
convert from this unit to default unit
QLatin1String m_symbol
unit name, e.g.
QLatin1String m_name
name, e.g.
constexpr Data(QLatin1String name, QLatin1String symbol, Converter, int displayDigits=2, double epsilon=1e-9)
Construct a unit with custom conversion.
int m_displayDigits
standard rounding for string conversions
constexpr Data(QLatin1String name, QLatin1String symbol)
Construct a null unit.
double m_epsilon
values with differences below epsilon are the equal
Metapolicy that can be used to modify template parameters of converters.
static double factor()
factor
Metapolicy that can be used to modify template parameters of converters.
static double factor()
factor
Concrete strategy pattern for converting unit that does nothing.
static double fromDefault(double value)
convert to this unit from the default unit
static double toDefault(double value)
convert from this unit to the default unit
Metapolicy that can be used to modify template parameters of converters.
static double subfactor()
subfactor
static double fraction()
fraction
Metapolicy that can be used to modify template parameters of converters.
static double factor()
factor
Concrete strategy pattern for converting unit with linear conversion.
static double fromDefault(double value)
convert to this unit from the default unit
static double toDefault(double value)
convert from this unit to the default unit
Metapolicy that can be used to modify template parameters of converters.
static double factor()
factor
Metapolicy that can be used to modify template parameters of converters.
static double factor()
factor
Converter for default values, such as None, used with public constructor.
static double fromDefault(double)
convert to this unit from the default unit
static double toDefault(double)
convert from this unit to the default unit
Metapolicy that can be used to modify template parameters of converters.
static double factor()
factor
Concrete strategy pattern for converting unit with two subdivision conversions.
static double fromDefault(double value)
convert to this unit from the default unit
static double toDefault(double value)
convert from this unit to the default unit
Concrete strategy pattern for converting unit with one subdivision conversion.
static double fromDefault(double value)
convert to this unit from the default unit
static double toDefault(double value)
convert from this unit to the default unit
Metapolicy that can be used to modify template parameters of converters.
static double factor()
factor
#define SWIFT_MISC_EXPORT
Export a class or function from the library.