mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-23 13:55:36 +08:00
refs #396 move Blackmisc PQ classes into subfolder
This commit is contained in:
committed by
Roland Winklmeier
parent
0ab755d510
commit
2363fab8c1
41
src/blackmisc/pq/acceleration.h
Normal file
41
src/blackmisc/pq/acceleration.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/* Copyright (C) 2013
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
|
||||
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
||||
* contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef BLACKMISC_PQ_ACCELERATION_H
|
||||
#define BLACKMISC_PQ_ACCELERATION_H
|
||||
|
||||
#include "blackmisc/pq/physicalquantity.h"
|
||||
|
||||
namespace BlackMisc
|
||||
{
|
||||
namespace PhysicalQuantities
|
||||
{
|
||||
|
||||
//! Acceleration
|
||||
class CAcceleration : public CValueObject<CAcceleration, CPhysicalQuantity<CAccelerationUnit, CAcceleration>>
|
||||
{
|
||||
public:
|
||||
//! Default constructor
|
||||
CAcceleration() : CValueObject(0, CAccelerationUnit::defaultUnit()) {}
|
||||
|
||||
//! Init by double value
|
||||
CAcceleration(double value, const CAccelerationUnit &unit) : CValueObject(value, unit) {}
|
||||
|
||||
//! \copydoc CPhysicalQuantity(const QString &unitString)
|
||||
CAcceleration(const QString &unitString) : CValueObject(unitString) {}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(BlackMisc::PhysicalQuantities::CAcceleration)
|
||||
|
||||
#endif // guard
|
||||
35
src/blackmisc/pq/angle.cpp
Normal file
35
src/blackmisc/pq/angle.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
/* Copyright (C) 2013
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
|
||||
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
||||
* contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "blackmisc/iconlist.h"
|
||||
#include "blackmisc/pq/angle.h"
|
||||
#include "blackmisc/aviation/heading.h"
|
||||
|
||||
namespace BlackMisc
|
||||
{
|
||||
namespace PhysicalQuantities
|
||||
{
|
||||
BlackMisc::CIcon CAngle::toIcon() const
|
||||
{
|
||||
BlackMisc::CIcon i = CIconList::iconByIndex(CIcons::StandardIconArrowMediumNorth16);
|
||||
i.setRotation(*this);
|
||||
return i;
|
||||
}
|
||||
|
||||
double CAngle::piFactor() const
|
||||
{
|
||||
return BlackMisc::Math::CMathUtils::round(this->value(CAngleUnit::rad()) / BlackMisc::Math::CMathUtils::PI() , 6);
|
||||
}
|
||||
|
||||
const double &CAngle::PI()
|
||||
{
|
||||
return BlackMisc::Math::CMathUtils::PI();
|
||||
}
|
||||
}
|
||||
}
|
||||
67
src/blackmisc/pq/angle.h
Normal file
67
src/blackmisc/pq/angle.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/* Copyright (C) 2013
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
|
||||
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
||||
* contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef BLACKMISC_PQ_ANGLE_H
|
||||
#define BLACKMISC_PQ_ANGLE_H
|
||||
|
||||
#include "blackmisc/pq/physicalquantity.h"
|
||||
#include "blackmisc/math/mathutils.h"
|
||||
|
||||
namespace BlackMisc
|
||||
{
|
||||
namespace PhysicalQuantities
|
||||
{
|
||||
//! Physical unit angle (radians, degrees)
|
||||
class CAngle : public CValueObject<CAngle, CPhysicalQuantity<CAngleUnit, CAngle>>
|
||||
{
|
||||
public:
|
||||
//! Default constructor
|
||||
CAngle() : CValueObject(0, CAngleUnit::defaultUnit()) {}
|
||||
|
||||
//! Init by double value
|
||||
CAngle(double value, const CAngleUnit &unit): CValueObject(value, unit) {}
|
||||
|
||||
//! \copydoc CPhysicalQuantity(const QString &unitString)
|
||||
CAngle(const QString &unitString) : CValueObject(unitString) {}
|
||||
|
||||
/*!
|
||||
* \brief Init as sexagesimal degrees, minutes, seconds
|
||||
* The sign of all parameters must be the same, either all positive or all negative.
|
||||
*/
|
||||
CAngle(int degrees, int minutes, double seconds) :
|
||||
CValueObject(
|
||||
degrees + minutes / 100.0 + seconds / 10000.0,
|
||||
CAngleUnit::sexagesimalDeg()) {}
|
||||
|
||||
/*!
|
||||
* \brief Init as sexagesimal degrees, minutes
|
||||
* The sign of both parameters must be the same, either both positive or both negative.
|
||||
*/
|
||||
CAngle(int degrees, double minutes) :
|
||||
CValueObject(
|
||||
degrees + minutes / 100.0,
|
||||
CAngleUnit::sexagesimalDegMin()) {}
|
||||
|
||||
//! \copydoc CValueObject::toIcon
|
||||
virtual BlackMisc::CIcon toIcon() const override;
|
||||
|
||||
//! Value as factor of PI (e.g. 0.5PI)
|
||||
double piFactor() const;
|
||||
|
||||
//! PI as convenience method
|
||||
static const double &PI();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(BlackMisc::PhysicalQuantities::CAngle)
|
||||
|
||||
#endif // guard
|
||||
95
src/blackmisc/pq/constants.h
Normal file
95
src/blackmisc/pq/constants.h
Normal file
@@ -0,0 +1,95 @@
|
||||
/* Copyright (C) 2013
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
|
||||
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
||||
* contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef BLACKMISC_PQ_CONSTANTS_H
|
||||
#define BLACKMISC_PQ_CONSTANTS_H
|
||||
|
||||
#include "blackmisc/pq/pq.h"
|
||||
|
||||
namespace BlackMisc
|
||||
{
|
||||
namespace PhysicalQuantities
|
||||
{
|
||||
|
||||
/*!
|
||||
* Physical quantities constants
|
||||
*/
|
||||
class CPhysicalQuantitiesConstants
|
||||
{
|
||||
public:
|
||||
//! Triple point of purified water, 0.01°C
|
||||
static const CTemperature &TemperatureTriplePointOfVSMOW()
|
||||
{
|
||||
static CTemperature t(-273.16, CTemperatureUnit::K());
|
||||
return t;
|
||||
}
|
||||
|
||||
//! Temperature absolute Zero in °C
|
||||
static const CTemperature &TemperatureAbsoluteZeroC()
|
||||
{
|
||||
static CTemperature t(-273.15, CTemperatureUnit::C());
|
||||
return t;
|
||||
}
|
||||
|
||||
//! International Standard Atmosphere pressure at mean sea level, 1013.25hPa
|
||||
static const CPressure &ISASeaLevelPressure()
|
||||
{
|
||||
static CPressure p(1013.25, CPressureUnit::hPa());
|
||||
return p;
|
||||
}
|
||||
|
||||
//! ICAO standard pressure datum for flight levels, 1013.2hPa
|
||||
static const CPressure &ICAOFlightLevelPressure()
|
||||
{
|
||||
static CPressure p(1013.2, CPressureUnit::hPa());
|
||||
return p;
|
||||
}
|
||||
|
||||
//! Standard pressure datum for flight levels in USA, Canada, parts of Latin America, 29.92inHg
|
||||
static const CPressure &USFlightLevelPressure()
|
||||
{
|
||||
static CPressure p(29.92, CPressureUnit::inHg());
|
||||
return p;
|
||||
}
|
||||
|
||||
//! Standard pressure datum for flight levels expressed in mmHg, such as in Russia, 760mmHg
|
||||
static const CPressure &RuFlightLevelPressure()
|
||||
{
|
||||
static CPressure p(760, CPressureUnit::mmHg());
|
||||
return p;
|
||||
}
|
||||
|
||||
//! Unicom frequency
|
||||
static const CFrequency &FrequencyUnicom()
|
||||
{
|
||||
static CFrequency f(122.8, CFrequencyUnit::MHz());
|
||||
return f;
|
||||
}
|
||||
|
||||
//! Civil aircraft emergency frequency
|
||||
static const CFrequency &FrequencyInternationalAirDistress()
|
||||
{
|
||||
static CFrequency f(121.5, CFrequencyUnit::MHz());
|
||||
return f;
|
||||
}
|
||||
|
||||
//! Military aircraft emergency frequency
|
||||
static const CFrequency &FrequencyMilitaryAirDistress()
|
||||
{
|
||||
static CFrequency f(243.0, CFrequencyUnit::MHz());
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
#endif // guard
|
||||
44
src/blackmisc/pq/frequency.h
Normal file
44
src/blackmisc/pq/frequency.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/* Copyright (C) 2013
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
|
||||
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
||||
* contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef BLACKMISC_PQ_FREQUENCY_H
|
||||
#define BLACKMISC_PQ_FREQUENCY_H
|
||||
|
||||
#include "blackmisc/pq/physicalquantity.h"
|
||||
|
||||
namespace BlackMisc
|
||||
{
|
||||
namespace PhysicalQuantities
|
||||
{
|
||||
/*!
|
||||
* Physical unit frequency
|
||||
*/
|
||||
class CFrequency : public CValueObject<CFrequency, CPhysicalQuantity<CFrequencyUnit, CFrequency>>
|
||||
{
|
||||
public:
|
||||
//! Default constructor
|
||||
CFrequency() : CValueObject(0, CFrequencyUnit::defaultUnit()) {}
|
||||
|
||||
//! Init by double value
|
||||
CFrequency(double value, const CFrequencyUnit &unit) : CValueObject(value, unit) {}
|
||||
|
||||
//! Init by int value converted to double
|
||||
CFrequency(int value, const CFrequencyUnit &unit) : CFrequency(double(value), unit) {}
|
||||
|
||||
//! \copydoc CPhysicalQuantity(const QString &unitString)
|
||||
CFrequency(const QString &unitString) : CValueObject(unitString) {}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(BlackMisc::PhysicalQuantities::CFrequency)
|
||||
|
||||
#endif // guard
|
||||
41
src/blackmisc/pq/length.h
Normal file
41
src/blackmisc/pq/length.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/* Copyright (C) 2013
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
|
||||
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
||||
* contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef BLACKMISC_PQ_LENGTH_H
|
||||
#define BLACKMISC_PQ_LENGTH_H
|
||||
|
||||
#include "blackmisc/pq/physicalquantity.h"
|
||||
|
||||
namespace BlackMisc
|
||||
{
|
||||
namespace PhysicalQuantities
|
||||
{
|
||||
|
||||
//! Physical unit length (length)
|
||||
class CLength : public CValueObject<CLength, CPhysicalQuantity<CLengthUnit, CLength>>
|
||||
{
|
||||
public:
|
||||
//! Default constructor
|
||||
CLength() : CValueObject(0, CLengthUnit::defaultUnit()) {}
|
||||
|
||||
//! Init by double value
|
||||
CLength(double value, const CLengthUnit &unit) : CValueObject(value, unit) {}
|
||||
|
||||
//! \copydoc CPhysicalQuantity(const QString &unitString)
|
||||
CLength(const QString &unitString) : CValueObject(unitString) {}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(BlackMisc::PhysicalQuantities::CLength)
|
||||
|
||||
#endif // guard
|
||||
43
src/blackmisc/pq/mass.h
Normal file
43
src/blackmisc/pq/mass.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/* Copyright (C) 2013
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
|
||||
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
||||
* contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef BLACKMISC_PQ_MASS_H
|
||||
#define BLACKMISC_PQ_MASS_H
|
||||
|
||||
#include "blackmisc/pq/physicalquantity.h"
|
||||
|
||||
namespace BlackMisc
|
||||
{
|
||||
namespace PhysicalQuantities
|
||||
{
|
||||
|
||||
/*!
|
||||
* Mass
|
||||
*/
|
||||
class CMass : public CValueObject<CMass, CPhysicalQuantity<CMassUnit, CMass>>
|
||||
{
|
||||
public:
|
||||
//! Default constructor
|
||||
CMass() : CValueObject(0, CMassUnit::defaultUnit()) {}
|
||||
|
||||
//! Init by double value
|
||||
CMass(double value, const CMassUnit &unit) : CValueObject(value, unit) {}
|
||||
|
||||
//! \copydoc CPhysicalQuantity(const QString &unitString)
|
||||
CMass(const QString &unitString) : CValueObject(unitString) {}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(BlackMisc::PhysicalQuantities::CMass)
|
||||
|
||||
#endif // guard
|
||||
60
src/blackmisc/pq/measurementunit.cpp
Normal file
60
src/blackmisc/pq/measurementunit.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
/* Copyright (C) 2013
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
|
||||
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
||||
* contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#include "blackmisc/pq/measurementunit.h"
|
||||
#include "blackmisc/math/mathutils.h"
|
||||
|
||||
using namespace BlackMisc::Math;
|
||||
|
||||
namespace BlackMisc
|
||||
{
|
||||
namespace PhysicalQuantities
|
||||
{
|
||||
|
||||
bool CMeasurementUnit::operator ==(const CMeasurementUnit &other) const
|
||||
{
|
||||
if (this == &other) return true;
|
||||
return this->m_name == other.m_name;
|
||||
}
|
||||
|
||||
bool CMeasurementUnit::operator !=(const CMeasurementUnit &other) const
|
||||
{
|
||||
return !(other == *this);
|
||||
}
|
||||
|
||||
double CMeasurementUnit::convertFrom(double value, const CMeasurementUnit &unit) const
|
||||
{
|
||||
if (this->isNull() || unit.isNull()) return 0;
|
||||
if (this->m_converter == unit.m_converter) return value;
|
||||
return this->m_converter->fromDefault(unit.m_converter->toDefault(value));
|
||||
}
|
||||
|
||||
QString CMeasurementUnit::makeRoundedQStringWithUnit(double value, int digits, bool i18n) const
|
||||
{
|
||||
return this->makeRoundedQString(value, digits).append(this->getSymbol(i18n));
|
||||
}
|
||||
|
||||
double CMeasurementUnit::roundValue(double value, int digits) const
|
||||
{
|
||||
if (digits < 0) digits = this->m_displayDigits;
|
||||
return CMathUtils::round(value, digits);
|
||||
}
|
||||
|
||||
QString CMeasurementUnit::makeRoundedQString(double value, int digits, bool /* i18n */) const
|
||||
{
|
||||
if (digits < 0) digits = this->m_displayDigits;
|
||||
double v = CMathUtils::round(value, digits);
|
||||
QString s = QLocale::system().toString(v, 'f', digits);
|
||||
return s;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
387
src/blackmisc/pq/measurementunit.h
Normal file
387
src/blackmisc/pq/measurementunit.h
Normal file
@@ -0,0 +1,387 @@
|
||||
/* Copyright (C) 2013
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
|
||||
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
||||
* contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef BLACKMISC_PQ_MEASUREMENTUNIT_H
|
||||
#define BLACKMISC_PQ_MEASUREMENTUNIT_H
|
||||
|
||||
#include "blackmisc/valueobject.h"
|
||||
#include "blackmisc/math/mathutils.h"
|
||||
#include "blackmisc/blackmiscfreefunctions.h"
|
||||
#include <QCoreApplication>
|
||||
#include <QtDBus/QDBusArgument>
|
||||
#include <QString>
|
||||
#include <QtGlobal>
|
||||
#include <QDebug>
|
||||
#include <QSharedData>
|
||||
#include <QSharedDataPointer>
|
||||
#include <QHash>
|
||||
#include <cstddef>
|
||||
|
||||
namespace BlackMisc
|
||||
{
|
||||
namespace PhysicalQuantities { class CMeasurementUnit; }
|
||||
|
||||
//! \private
|
||||
template <> struct CValueObjectPolicy<PhysicalQuantities::CMeasurementUnit> : public CValueObjectPolicy<>
|
||||
{
|
||||
using MetaType = Policy::MetaType::DefaultAndQList;
|
||||
using Equals = Policy::Equals::None;
|
||||
using LessThan = Policy::LessThan::None;
|
||||
using Compare = Policy::Compare::None;
|
||||
using Hash = Policy::Hash::Own;
|
||||
using DBus = Policy::DBus::Own;
|
||||
using Json = Policy::Json::None;
|
||||
};
|
||||
|
||||
namespace PhysicalQuantities
|
||||
{
|
||||
/*!
|
||||
* Base class for all units, such as meter, hertz.
|
||||
*/
|
||||
class CMeasurementUnit : public CValueObject<CMeasurementUnit>
|
||||
{
|
||||
protected:
|
||||
/*!
|
||||
* Abstract strategy pattern that encapsulates a unit conversion strategy.
|
||||
*/
|
||||
class Converter : public QSharedData
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
* Virtual destructor.
|
||||
*/
|
||||
virtual ~Converter() {}
|
||||
/*!
|
||||
* Convert from this unit to default unit.
|
||||
*/
|
||||
virtual double toDefault(double factor) const = 0;
|
||||
/*!
|
||||
* Convert from default unit to this unit.
|
||||
*/
|
||||
virtual double fromDefault(double factor) const = 0;
|
||||
};
|
||||
|
||||
/*!
|
||||
* Converter for default values, such as None, used with public constructor
|
||||
*/
|
||||
struct NilConverter : public Converter
|
||||
{
|
||||
virtual double toDefault(double) const override { return 0.0; }
|
||||
virtual double fromDefault(double) const override { return 0.0; }
|
||||
};
|
||||
|
||||
/*!
|
||||
* Concrete strategy pattern for converting unit that does nothing.
|
||||
*/
|
||||
struct IdentityConverter : public Converter
|
||||
{
|
||||
virtual double toDefault(double factor) const override { return factor; }
|
||||
virtual double fromDefault(double factor) const override { return factor; }
|
||||
};
|
||||
|
||||
/*!
|
||||
* Concrete strategy pattern for converting unit with linear conversion.
|
||||
* \tparam Policy a policy class with static method factor() returning double
|
||||
*/
|
||||
template <class Policy>
|
||||
struct LinearConverter : public Converter
|
||||
{
|
||||
virtual double toDefault(double factor) const override { return factor * Policy::factor(); }
|
||||
virtual double fromDefault(double factor) const override { return factor / Policy::factor(); }
|
||||
};
|
||||
|
||||
/*!
|
||||
* Concrete strategy pattern for converting unit with offset linear conversion.
|
||||
* \tparam Policy a policy class with static methods factor() and offset() returning double
|
||||
*/
|
||||
template <class Policy>
|
||||
struct AffineConverter : public Converter
|
||||
{
|
||||
virtual double toDefault(double factor) const override { return (factor - Policy::offset()) * Policy::factor(); }
|
||||
virtual double fromDefault(double factor) const override { return factor / Policy::factor() + Policy::offset(); }
|
||||
};
|
||||
|
||||
/*!
|
||||
* Concrete strategy pattern for converting unit with one subdivision conversion.
|
||||
* \tparam FactorPolicy a policy class with static method factor() returning double
|
||||
* \tparam SubdivPolicy a policy class with static methods fraction() and subfactor() returning double
|
||||
*/
|
||||
template <class FactorPolicy, class SubdivPolicy>
|
||||
struct SubdivisionConverter : public Converter
|
||||
{
|
||||
virtual double toDefault(double factor) const override
|
||||
{
|
||||
using BlackMisc::Math::CMathUtils;
|
||||
double part2 = CMathUtils::fract(factor) * SubdivPolicy::fraction();
|
||||
factor = CMathUtils::trunc(factor) + part2 / SubdivPolicy::subfactor();
|
||||
return factor * FactorPolicy::factor();
|
||||
}
|
||||
virtual double fromDefault(double factor) const override
|
||||
{
|
||||
using BlackMisc::Math::CMathUtils;
|
||||
factor /= FactorPolicy::factor();
|
||||
double part2 = CMathUtils::fract(factor) * SubdivPolicy::subfactor();
|
||||
return CMathUtils::trunc(factor) + part2 / SubdivPolicy::fraction();
|
||||
}
|
||||
};
|
||||
|
||||
/*!
|
||||
* Concrete strategy pattern for converting unit with two subdivision conversions.
|
||||
* \tparam FactorPolicy a policy class with static method factor() returning double
|
||||
* \tparam SubdivPolicy a policy class with static methods fraction() and subfactor() returning double
|
||||
*/
|
||||
template <class FactorPolicy, class SubdivPolicy>
|
||||
struct SubdivisionConverter2 : public Converter
|
||||
{
|
||||
virtual double toDefault(double factor) const override
|
||||
{
|
||||
using BlackMisc::Math::CMathUtils;
|
||||
double part2 = CMathUtils::fract(factor) * SubdivPolicy::fraction();
|
||||
double part3 = CMathUtils::fract(part2) * SubdivPolicy::fraction();
|
||||
factor = CMathUtils::trunc(factor) + (CMathUtils::trunc(part2) + part3 / SubdivPolicy::subfactor()) / SubdivPolicy::subfactor();
|
||||
return factor * FactorPolicy::factor();
|
||||
}
|
||||
virtual double fromDefault(double factor) const override
|
||||
{
|
||||
using BlackMisc::Math::CMathUtils;
|
||||
factor /= FactorPolicy::factor();
|
||||
double part2 = CMathUtils::fract(factor) * SubdivPolicy::subfactor();
|
||||
double part3 = CMathUtils::fract(part2) * SubdivPolicy::subfactor();
|
||||
return CMathUtils::trunc(factor) + (CMathUtils::trunc(part2) + part3 / SubdivPolicy::fraction()) / SubdivPolicy::fraction();
|
||||
}
|
||||
};
|
||||
|
||||
//! Metapolicy that can be used to modify template parameters of converters
|
||||
//! @{
|
||||
struct One
|
||||
{
|
||||
static double factor() { return 1; } //!< factor
|
||||
};
|
||||
//! 2 (two)
|
||||
template <class Policy>
|
||||
struct Two
|
||||
{
|
||||
static double factor() { return Policy::factor() * 2.0; } //!< factor
|
||||
};
|
||||
//! 10^-3
|
||||
template <class Policy>
|
||||
struct Milli
|
||||
{
|
||||
static double factor() { return Policy::factor() / 1000.0; } //!< factor
|
||||
};
|
||||
template <class Policy>
|
||||
//! 10^-2
|
||||
struct Centi
|
||||
{
|
||||
static double factor() { return Policy::factor() / 100.0; } //!< factor
|
||||
};
|
||||
//! 10^2
|
||||
template <class Policy>
|
||||
struct Hecto
|
||||
{
|
||||
static double factor() { return Policy::factor() * 100.0; } //!< factor
|
||||
};
|
||||
//! 10^3
|
||||
template <class Policy>
|
||||
struct Kilo
|
||||
{
|
||||
static double factor() { return Policy::factor() * 1000.0; } //!< factor
|
||||
};
|
||||
//! 10^6
|
||||
template <class Policy>
|
||||
struct Mega
|
||||
{
|
||||
static double factor() { return Policy::factor() * 1e+6; } //!< factor
|
||||
};
|
||||
//! 10^9
|
||||
template <class Policy>
|
||||
struct Giga
|
||||
{
|
||||
static double factor() { return Policy::factor() * 1e+9; } //!< factor
|
||||
};
|
||||
//! in each hundred
|
||||
template <int Subfactor>
|
||||
struct InEachHundred
|
||||
{
|
||||
static double fraction() { return 100.0f; } //!< fraction
|
||||
static double subfactor() { return float(Subfactor); } //!< subfactor
|
||||
};
|
||||
//! @}
|
||||
|
||||
private:
|
||||
QString m_name; //!< name, e.g. "meter"
|
||||
QString m_symbol; //!< unit name, e.g. "m"
|
||||
double m_epsilon; //!< values with differences below epsilon are the equal
|
||||
int m_displayDigits; //!< standard rounding for string conversions
|
||||
QSharedDataPointer<Converter> m_converter; //!< strategy pattern allows an arbitrary conversion method as per object
|
||||
|
||||
protected:
|
||||
/*!
|
||||
* Construct a unit with custom conversion
|
||||
*/
|
||||
template <class Converter>
|
||||
CMeasurementUnit(const QString &name, const QString &symbol, const Converter &, int displayDigits, double epsilon)
|
||||
: m_name(name), m_symbol(symbol), m_epsilon(epsilon), m_displayDigits(displayDigits), m_converter(new Converter)
|
||||
{}
|
||||
|
||||
/*!
|
||||
* Construct a null unit
|
||||
*/
|
||||
CMeasurementUnit(const QString &name, const QString &symbol, std::nullptr_t)
|
||||
: m_name(name), m_symbol(symbol), m_epsilon(0.0), m_displayDigits(0)
|
||||
{}
|
||||
|
||||
//! \copydoc CValueObject::stringForStreaming
|
||||
virtual QString stringForStreaming() const override
|
||||
{
|
||||
return this->getName(false);
|
||||
}
|
||||
|
||||
//! \copydoc CValueObject::convertToQString
|
||||
virtual QString convertToQString(bool i18n = false) const override
|
||||
{
|
||||
return this->getSymbol(i18n);
|
||||
}
|
||||
|
||||
//! \copydoc CValueObject::marshallToDbus
|
||||
virtual void marshallToDbus(QDBusArgument &argument) const override
|
||||
{
|
||||
argument << this->m_symbol;
|
||||
}
|
||||
|
||||
//! \copydoc CValueObject::unmarshallFromDbus
|
||||
virtual void unmarshallFromDbus(const QDBusArgument &) override
|
||||
{
|
||||
// the concrete implementations will override this default
|
||||
// this is required so I can also stream None
|
||||
(*this) = CMeasurementUnit::None();
|
||||
}
|
||||
|
||||
public:
|
||||
//! Default constructor for meta system
|
||||
//! \remarks Only public because the need, to use this with the metasystem
|
||||
CMeasurementUnit() : m_name("none"), m_symbol(""), m_epsilon(0), m_displayDigits(0)
|
||||
{}
|
||||
|
||||
//! Equal operator ==
|
||||
bool operator == (const CMeasurementUnit &other) const;
|
||||
|
||||
//! Unequal operator !=
|
||||
bool operator != (const CMeasurementUnit &other) const;
|
||||
|
||||
//! \copydoc CValueObject::getValueHash
|
||||
virtual uint getValueHash() const override
|
||||
{
|
||||
return qHash(this->getName());
|
||||
}
|
||||
|
||||
//! Name such as "meter"
|
||||
QString getName(bool i18n = false) const
|
||||
{
|
||||
return i18n ? QCoreApplication::translate("CMeasurementUnit", this->m_name.toStdString().c_str()) : this->m_name;
|
||||
}
|
||||
|
||||
//! Unit name such as "m"
|
||||
QString getSymbol(bool i18n = false) const
|
||||
{
|
||||
return i18n ? QCoreApplication::translate("CMeasurementUnit", this->m_symbol.toStdString().c_str()) : this->m_symbol;
|
||||
}
|
||||
|
||||
//! Rounded value
|
||||
double roundValue(double value, int digits = -1) const;
|
||||
|
||||
//! Rounded string utility method, virtual so units can have specialized formatting
|
||||
virtual QString makeRoundedQString(double value, int digits = -1, bool i18n = false) const;
|
||||
|
||||
//! Value rounded with unit, e.g. "5.00m", "30kHz"
|
||||
virtual QString makeRoundedQStringWithUnit(double value, int digits = -1, bool i18n = false) const;
|
||||
|
||||
//! Threshold for rounding
|
||||
double getEpsilon() const
|
||||
{
|
||||
return this->m_epsilon;
|
||||
}
|
||||
|
||||
//! Display digits
|
||||
int getDisplayDigits() const
|
||||
{
|
||||
return this->m_displayDigits;
|
||||
}
|
||||
|
||||
//! Convert from other unit to this unit.
|
||||
double convertFrom(double value, const CMeasurementUnit &unit) const;
|
||||
|
||||
//! Is given value <= epsilon?
|
||||
bool isEpsilon(double value) const
|
||||
{
|
||||
if (this->isNull()) return false;
|
||||
if (value == 0) return true;
|
||||
return abs(value) <= this->m_epsilon;
|
||||
}
|
||||
|
||||
//! Is unit null?
|
||||
bool isNull() const
|
||||
{
|
||||
return this->m_converter.data() == nullptr;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// -- static
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/*!
|
||||
* Unit from symbol
|
||||
* \param symbol must be a valid unit symbol (without i18n) or empty string (empty means default unit)
|
||||
* \param strict strict check means if unit is not found, program terminates
|
||||
*/
|
||||
template <class U> static const U &unitFromSymbol(const QString &symbol, bool strict = true)
|
||||
{
|
||||
if (symbol.isEmpty()) return U::defaultUnit();
|
||||
const QList<U> &units = U::allUnits();
|
||||
for (int i = 0; i < units.size(); ++i)
|
||||
{
|
||||
if (units.at(i).getSymbol() == symbol) return units.at(i);
|
||||
}
|
||||
if (strict) qFatal("Illegal unit name");
|
||||
return U::defaultUnit();
|
||||
}
|
||||
|
||||
/*!
|
||||
* Valid unit symbol?
|
||||
* \param symbol to be tested
|
||||
* \param caseSensitivity check case sensitiv?
|
||||
*/
|
||||
template <class U> static bool isValidUnitSymbol(const QString &symbol, Qt::CaseSensitivity caseSensitivity = Qt::CaseSensitive)
|
||||
{
|
||||
if (symbol.isEmpty()) return false;
|
||||
const QList<U> &units = U::allUnits();
|
||||
for (int i = 0; i < units.size(); ++i)
|
||||
{
|
||||
if (caseSensitivity == Qt::CaseSensitive && units.at(i).getSymbol() == symbol) return true;
|
||||
if (units.at(i).getSymbol().compare(symbol, Qt::CaseInsensitive) == 0) return 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//! Dimensionless unit
|
||||
static CMeasurementUnit &None()
|
||||
{
|
||||
static CMeasurementUnit none("none", "", NilConverter(), 0, 0);
|
||||
return none;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(BlackMisc::PhysicalQuantities::CMeasurementUnit)
|
||||
|
||||
#endif // guard
|
||||
292
src/blackmisc/pq/physicalquantity.cpp
Normal file
292
src/blackmisc/pq/physicalquantity.cpp
Normal file
@@ -0,0 +1,292 @@
|
||||
/* Copyright (C) 2013
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
|
||||
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
||||
* contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "blackmisc/pq/pq.h"
|
||||
#include "blackmisc/blackmiscfreefunctions.h"
|
||||
#include <QCoreApplication>
|
||||
|
||||
namespace BlackMisc
|
||||
{
|
||||
namespace PhysicalQuantities
|
||||
{
|
||||
|
||||
template <class MU, class PQ> CPhysicalQuantity<MU, PQ>::CPhysicalQuantity(double value, const MU &unit) :
|
||||
m_value(unit.isNull() ? 0.0 : value), m_unit(unit)
|
||||
{ }
|
||||
|
||||
template <class MU, class PQ> bool CPhysicalQuantity<MU, PQ>::operator ==(const CPhysicalQuantity<MU, PQ> &other) const
|
||||
{
|
||||
if (this == &other) return true;
|
||||
|
||||
if (this->isNull()) return other.isNull();
|
||||
if (other.isNull()) return false;
|
||||
|
||||
double diff = std::abs(this->m_value - other.value(this->m_unit));
|
||||
return diff <= this->m_unit.getEpsilon();
|
||||
}
|
||||
|
||||
template <class MU, class PQ> bool CPhysicalQuantity<MU, PQ>::operator !=(const CPhysicalQuantity<MU, PQ> &other) const
|
||||
{
|
||||
return !((*this) == other);
|
||||
}
|
||||
|
||||
template <class MU, class PQ> CPhysicalQuantity<MU, PQ> &CPhysicalQuantity<MU, PQ>::operator +=(const CPhysicalQuantity<MU, PQ> &other)
|
||||
{
|
||||
this->m_value += other.value(this->m_unit);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class MU, class PQ> PQ CPhysicalQuantity<MU, PQ>::operator +(const PQ &other) const
|
||||
{
|
||||
PQ copy(other);
|
||||
copy += *this;
|
||||
return copy;
|
||||
}
|
||||
|
||||
template <class MU, class PQ> void CPhysicalQuantity<MU, PQ>::addValueSameUnit(double value)
|
||||
{
|
||||
this->m_value += value;
|
||||
}
|
||||
|
||||
template <class MU, class PQ> void CPhysicalQuantity<MU, PQ>::substractValueSameUnit(double value)
|
||||
{
|
||||
this->m_value -= value;
|
||||
}
|
||||
|
||||
template <class MU, class PQ> CPhysicalQuantity<MU, PQ> &CPhysicalQuantity<MU, PQ>::operator -=(const CPhysicalQuantity<MU, PQ> &other)
|
||||
{
|
||||
this->m_value -= other.value(this->m_unit);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class MU, class PQ> PQ CPhysicalQuantity<MU, PQ>::operator -(const PQ &other) const
|
||||
{
|
||||
PQ copy = *derived();
|
||||
copy -= other;
|
||||
return copy;
|
||||
}
|
||||
|
||||
template <class MU, class PQ> void CPhysicalQuantity<MU, PQ>::marshallToDbus(QDBusArgument &argument) const
|
||||
{
|
||||
argument << this->value(UnitClass::defaultUnit());
|
||||
argument << this->m_value;
|
||||
argument << this->m_unit;
|
||||
}
|
||||
|
||||
template <class MU, class PQ> void CPhysicalQuantity<MU, PQ>::unmarshallFromDbus(const QDBusArgument &argument)
|
||||
{
|
||||
double ignore;
|
||||
argument >> ignore;
|
||||
argument >> this->m_value;
|
||||
argument >> this->m_unit;
|
||||
}
|
||||
|
||||
template <class MU, class PQ> CPhysicalQuantity<MU, PQ> &CPhysicalQuantity<MU, PQ>::operator *=(double factor)
|
||||
{
|
||||
this->m_value *= factor;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class MU, class PQ> PQ CPhysicalQuantity<MU, PQ>::operator *(double factor) const
|
||||
{
|
||||
PQ copy = *derived();
|
||||
copy *= factor;
|
||||
return copy;
|
||||
}
|
||||
|
||||
template <class MU, class PQ> CPhysicalQuantity<MU, PQ> &CPhysicalQuantity<MU, PQ>::operator /=(double divisor)
|
||||
{
|
||||
this->m_value /= divisor;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class MU, class PQ> PQ CPhysicalQuantity<MU, PQ>::operator /(double divisor) const
|
||||
{
|
||||
PQ copy = *derived();
|
||||
copy /= divisor;
|
||||
return copy;
|
||||
}
|
||||
|
||||
template <class MU, class PQ> bool CPhysicalQuantity<MU, PQ>::operator <(const CPhysicalQuantity<MU, PQ> &other) const
|
||||
{
|
||||
if (*this == other) return false;
|
||||
if (this->isNull() || other.isNull()) return false;
|
||||
|
||||
return (this->m_value < other.value(this->m_unit));
|
||||
}
|
||||
|
||||
template <class MU, class PQ> bool CPhysicalQuantity<MU, PQ>::operator >(const CPhysicalQuantity<MU, PQ> &other) const
|
||||
{
|
||||
return other < *this;
|
||||
}
|
||||
|
||||
template <class MU, class PQ> bool CPhysicalQuantity<MU, PQ>::operator >=(const CPhysicalQuantity<MU, PQ> &other) const
|
||||
{
|
||||
if (*this == other) return true;
|
||||
return *this > other;
|
||||
}
|
||||
|
||||
template <class MU, class PQ> bool CPhysicalQuantity<MU, PQ>::operator <=(const CPhysicalQuantity<MU, PQ> &other) const
|
||||
{
|
||||
if (*this == other) return true;
|
||||
return *this < other;
|
||||
}
|
||||
|
||||
template <class MU, class PQ> PQ &CPhysicalQuantity<MU, PQ>::switchUnit(const MU &newUnit)
|
||||
{
|
||||
if (this->m_unit != newUnit)
|
||||
{
|
||||
this->m_value = newUnit.convertFrom(this->m_value, this->m_unit);
|
||||
this->m_unit = newUnit;
|
||||
}
|
||||
return *derived();
|
||||
}
|
||||
|
||||
template <class MU, class PQ> void CPhysicalQuantity<MU, PQ>::setValueSameUnit(double baseValue)
|
||||
{
|
||||
this->m_value = baseValue;
|
||||
}
|
||||
|
||||
template <class MU, class PQ> QString CPhysicalQuantity<MU, PQ>::valueRoundedWithUnit(const MU &unit, int digits, bool i18n) const
|
||||
{
|
||||
return unit.makeRoundedQStringWithUnit(this->value(unit), digits, i18n);
|
||||
}
|
||||
|
||||
template <class MU, class PQ> double CPhysicalQuantity<MU, PQ>::valueRounded(const MU &unit, int digits) const
|
||||
{
|
||||
return unit.roundValue(this->value(unit), digits);
|
||||
}
|
||||
|
||||
template <class MU, class PQ> int CPhysicalQuantity<MU, PQ>::valueInteger(const MU &unit) const
|
||||
{
|
||||
double v = unit.roundValue(this->value(unit), 0);
|
||||
return static_cast<int>(v);
|
||||
}
|
||||
|
||||
template <class MU, class PQ> double CPhysicalQuantity<MU, PQ>::valueRounded(int digits) const
|
||||
{
|
||||
return this->valueRounded(this->m_unit, digits);
|
||||
}
|
||||
|
||||
template <class MU, class PQ> double CPhysicalQuantity<MU, PQ>::value(const MU &unit) const
|
||||
{
|
||||
return unit.convertFrom(this->m_value, this->m_unit);
|
||||
}
|
||||
|
||||
template <class MU, class PQ> QString CPhysicalQuantity<MU, PQ>::convertToQString(bool i18n) const
|
||||
{
|
||||
if (this->isNull())
|
||||
{
|
||||
return i18n ? QCoreApplication::translate("CPhysicalQuantity", "undefined") : "undefined";
|
||||
}
|
||||
return this->valueRoundedWithUnit(this->getUnit(), -1, i18n);
|
||||
}
|
||||
|
||||
template <class MU, class PQ> uint CPhysicalQuantity<MU, PQ>::getValueHash() const
|
||||
{
|
||||
QList<uint> hashs;
|
||||
// there is no double qHash
|
||||
// also unit and rounding has to be considered
|
||||
hashs << qHash(this->valueRoundedWithUnit(MU::defaultUnit()));
|
||||
return BlackMisc::calculateHash(hashs, "PQ");
|
||||
}
|
||||
|
||||
template <class MU, class PQ> QJsonObject CPhysicalQuantity<MU, PQ>::toJson() const
|
||||
{
|
||||
QJsonObject json;
|
||||
json.insert("value", QJsonValue(this->m_value));
|
||||
json.insert("unit", QJsonValue(this->m_unit.getSymbol()));
|
||||
return json;
|
||||
}
|
||||
|
||||
template <class MU, class PQ> void CPhysicalQuantity<MU, PQ>::convertFromJson(const QJsonObject &json)
|
||||
{
|
||||
const QString unitSymbol = json.value("unit").toString();
|
||||
this->setUnitBySymbol(unitSymbol);
|
||||
this->m_value = json.value("value").toDouble();
|
||||
}
|
||||
|
||||
template <class MU, class PQ> CVariant CPhysicalQuantity<MU, PQ>::propertyByIndex(const CPropertyIndex &index) const
|
||||
{
|
||||
if (index.isMyself()) { return this->toCVariant(); }
|
||||
ColumnIndex i = index.frontCasted<ColumnIndex>();
|
||||
switch (i)
|
||||
{
|
||||
case IndexValue:
|
||||
return CVariant::from(this->m_value);
|
||||
case IndexUnit:
|
||||
return this->m_unit.toCVariant();
|
||||
case IndexValueRounded0DigitsWithUnit:
|
||||
return CVariant::from(this->valueRoundedWithUnit(0));
|
||||
case IndexValueRounded1DigitsWithUnit:
|
||||
return CVariant::from(this->valueRoundedWithUnit(1));
|
||||
case IndexValueRounded2DigitsWithUnit:
|
||||
return CVariant::from(this->valueRoundedWithUnit(2));
|
||||
case IndexValueRounded3DigitsWithUnit:
|
||||
return CVariant::from(this->valueRoundedWithUnit(3));
|
||||
case IndexValueRounded6DigitsWithUnit:
|
||||
return CVariant::from(this->valueRoundedWithUnit(6));
|
||||
default:
|
||||
return CValueObject<CPhysicalQuantity<MU, PQ>>::propertyByIndex(index);
|
||||
}
|
||||
}
|
||||
|
||||
template <class MU, class PQ> void CPhysicalQuantity<MU, PQ>::setPropertyByIndex(const CVariant &variant, const CPropertyIndex &index)
|
||||
{
|
||||
if (index.isMyself())
|
||||
{
|
||||
this->convertFromCVariant(variant);
|
||||
return;
|
||||
}
|
||||
ColumnIndex i = index.frontCasted<ColumnIndex>();
|
||||
switch (i)
|
||||
{
|
||||
case IndexValue:
|
||||
this->m_value = variant.toDouble();
|
||||
break;
|
||||
case IndexUnit:
|
||||
this->m_unit.convertFromCVariant(variant);
|
||||
break;
|
||||
case IndexValueRounded0DigitsWithUnit:
|
||||
case IndexValueRounded1DigitsWithUnit:
|
||||
case IndexValueRounded2DigitsWithUnit:
|
||||
case IndexValueRounded3DigitsWithUnit:
|
||||
case IndexValueRounded6DigitsWithUnit:
|
||||
this->parseFromString(variant.toQString());
|
||||
break;
|
||||
default:
|
||||
CValueObject<CPhysicalQuantity<MU, PQ>>::setPropertyByIndex(variant, index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template <class MU, class PQ> int CPhysicalQuantity<MU, PQ>::compareImpl(const PQ &a, const PQ &b)
|
||||
{
|
||||
if (a.isNull() > b.isNull()) { return -1; }
|
||||
if (a.isNull() < b.isNull()) { return 1; }
|
||||
|
||||
if (a < b) { return -1; }
|
||||
else if (a > b) { return 1; }
|
||||
else { return 0; }
|
||||
}
|
||||
|
||||
// see here for the reason of thess forward instantiations
|
||||
// http://www.parashift.com/c++-faq/separate-template-class-defn-from-decl.html
|
||||
template class CPhysicalQuantity<CLengthUnit, CLength>;
|
||||
template class CPhysicalQuantity<CPressureUnit, CPressure>;
|
||||
template class CPhysicalQuantity<CFrequencyUnit, CFrequency>;
|
||||
template class CPhysicalQuantity<CMassUnit, CMass>;
|
||||
template class CPhysicalQuantity<CTemperatureUnit, CTemperature>;
|
||||
template class CPhysicalQuantity<CSpeedUnit, CSpeed>;
|
||||
template class CPhysicalQuantity<CAngleUnit, CAngle>;
|
||||
template class CPhysicalQuantity<CTimeUnit, CTime>;
|
||||
template class CPhysicalQuantity<CAccelerationUnit, CAcceleration>;
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
279
src/blackmisc/pq/physicalquantity.h
Normal file
279
src/blackmisc/pq/physicalquantity.h
Normal file
@@ -0,0 +1,279 @@
|
||||
/* Copyright (C) 2013
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
|
||||
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
||||
* contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef BLACKMISC_PQ_PHYSICALQUANTITY_H
|
||||
#define BLACKMISC_PQ_PHYSICALQUANTITY_H
|
||||
|
||||
#include "blackmisc/pq/measurementunit.h"
|
||||
#include "blackmisc/pq/units.h"
|
||||
#include "blackmisc/propertyindex.h"
|
||||
#include "blackmisc/math/mathutils.h"
|
||||
#include "blackmisc/pq/pqstring.h"
|
||||
#include "blackmisc/blackmiscfreefunctions.h"
|
||||
#include <QtDBus/QDBusMetaType>
|
||||
#include <QtGlobal>
|
||||
#include <QString>
|
||||
#include <QLocale>
|
||||
#include <typeinfo>
|
||||
|
||||
namespace BlackMisc
|
||||
{
|
||||
namespace PhysicalQuantities { template <class, class> class CPhysicalQuantity; }
|
||||
|
||||
//! \private
|
||||
template <class MU, class PQ> struct CValueObjectPolicy<PhysicalQuantities::CPhysicalQuantity<MU, PQ>> : public CValueObjectPolicy<>
|
||||
{
|
||||
using MetaType = Policy::MetaType::DefaultAndQList;
|
||||
using Equals = Policy::Equals::None;
|
||||
using LessThan = Policy::LessThan::None;
|
||||
using Compare = Policy::Compare::None;
|
||||
using Hash = Policy::Hash::Own;
|
||||
using DBus = Policy::DBus::Own;
|
||||
using Json = Policy::Json::Own;
|
||||
};
|
||||
|
||||
namespace PhysicalQuantities
|
||||
{
|
||||
/*!
|
||||
* A physical quantity such as "5m", "20s", "1500ft/s"
|
||||
*/
|
||||
template <class MU, class PQ> class CPhysicalQuantity : public CValueObject<CPhysicalQuantity<MU, PQ>>
|
||||
{
|
||||
//! \copydoc CValueObject::compare
|
||||
friend int compare(const PQ &a, const PQ &b) { return compareImpl(a, b); }
|
||||
|
||||
public:
|
||||
//! Index
|
||||
enum ColumnIndex
|
||||
{
|
||||
IndexUnit = BlackMisc::CPropertyIndex::GlobalIndexCPhysicalQuantity,
|
||||
IndexValue,
|
||||
IndexValueRounded0DigitsWithUnit,
|
||||
IndexValueRounded1DigitsWithUnit,
|
||||
IndexValueRounded2DigitsWithUnit,
|
||||
IndexValueRounded3DigitsWithUnit,
|
||||
IndexValueRounded6DigitsWithUnit
|
||||
};
|
||||
|
||||
//! Unit
|
||||
MU getUnit() const { return this->m_unit; }
|
||||
|
||||
/*!
|
||||
* \brief Simply set unit, do no calclulate conversion
|
||||
* \sa switchUnit
|
||||
*/
|
||||
void setUnit(const MU &unit) { this->m_unit = unit; }
|
||||
|
||||
//! Set unit by string
|
||||
void setUnitBySymbol(const QString &unitName)
|
||||
{
|
||||
this->m_unit = CMeasurementUnit::unitFromSymbol<MU>(unitName);
|
||||
}
|
||||
|
||||
//! Unit
|
||||
QString getUnitSymbol() const { return this->m_unit.getSymbol(true); }
|
||||
|
||||
//! Change unit, and convert value to maintain the same quantity
|
||||
PQ &switchUnit(const MU &newUnit);
|
||||
|
||||
//! Is quantity null?
|
||||
bool isNull() const { return this->m_unit.isNull(); }
|
||||
|
||||
//! Set null
|
||||
void setNull() { this->m_unit = MU::nullUnit(); }
|
||||
|
||||
//! Value in given unit
|
||||
double value(const MU &unit) const;
|
||||
|
||||
//! Value in current unit
|
||||
double value() const
|
||||
{
|
||||
if (this->isNull())
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
return this->m_value;
|
||||
}
|
||||
|
||||
//! Set value in current unit
|
||||
void setCurrentUnitValue(double value)
|
||||
{
|
||||
if (!this->isNull())
|
||||
{
|
||||
this->m_value = value;
|
||||
}
|
||||
}
|
||||
|
||||
//! Rounded value in given unit
|
||||
double valueRounded(const MU &unit, int digits = -1) const;
|
||||
|
||||
//! As integer value
|
||||
int valueInteger(const MU &unit) const;
|
||||
|
||||
//! Rounded value in current unit
|
||||
double valueRounded(int digits = -1) const;
|
||||
|
||||
//! Value to QString with the given unit, e.g. "5.00m"
|
||||
QString valueRoundedWithUnit(const MU &unit, int digits = -1, bool i18n = false) const;
|
||||
|
||||
//! Value to QString with the current unit, e.g. "5.00m"
|
||||
QString valueRoundedWithUnit(int digits = -1, bool i18n = false) const
|
||||
{
|
||||
return this->valueRoundedWithUnit(this->m_unit, digits, i18n);
|
||||
}
|
||||
|
||||
//! Change value without changing unit
|
||||
void setValueSameUnit(double value);
|
||||
|
||||
//! Add to the value in the current unit.
|
||||
void addValueSameUnit(double value);
|
||||
|
||||
//! Substract from the value in the current unit.
|
||||
void substractValueSameUnit(double value);
|
||||
|
||||
//! Multiply operator *=
|
||||
CPhysicalQuantity &operator *=(double multiply);
|
||||
|
||||
//! Divide operator /=
|
||||
CPhysicalQuantity &operator /=(double divide);
|
||||
|
||||
//! Operator *
|
||||
PQ operator *(double multiply) const;
|
||||
|
||||
//! Operator to support commutative multiplication
|
||||
friend PQ operator *(double factor, const PQ &other) { return other * factor; }
|
||||
|
||||
//! Operator /
|
||||
PQ operator /(double divide) const;
|
||||
|
||||
//! Equal operator ==
|
||||
bool operator==(const CPhysicalQuantity &other) const;
|
||||
|
||||
//! Not equal operator !=
|
||||
bool operator!=(const CPhysicalQuantity &other) const;
|
||||
|
||||
//! Plus operator +=
|
||||
CPhysicalQuantity &operator +=(const CPhysicalQuantity &other);
|
||||
|
||||
//! Minus operator-=
|
||||
CPhysicalQuantity &operator -=(const CPhysicalQuantity &other);
|
||||
|
||||
//! Greater operator >
|
||||
bool operator >(const CPhysicalQuantity &other) const;
|
||||
|
||||
//! Less operator <
|
||||
bool operator <(const CPhysicalQuantity &other) const;
|
||||
|
||||
//! Less equal operator <=
|
||||
bool operator <=(const CPhysicalQuantity &other) const;
|
||||
|
||||
//! Greater equal operator >=
|
||||
bool operator >=(const CPhysicalQuantity &other) const;
|
||||
|
||||
//! Plus operator +
|
||||
PQ operator +(const PQ &other) const;
|
||||
|
||||
//! Minus operator -
|
||||
PQ operator -(const PQ &other) const;
|
||||
|
||||
//! Quantity value <= epsilon
|
||||
bool isZeroEpsilonConsidered() const { return this->m_unit.isEpsilon(this->m_value); }
|
||||
|
||||
//! Value >= 0 epsilon considered
|
||||
bool isPositiveWithEpsilonConsidered() const
|
||||
{
|
||||
return !this->isZeroEpsilonConsidered() && this->m_value > 0;
|
||||
}
|
||||
|
||||
//! Value <= 0 epsilon considered
|
||||
bool isNegativeWithEpsilonConsidered() const
|
||||
{
|
||||
return !this->isZeroEpsilonConsidered() && this->m_value < 0;
|
||||
}
|
||||
|
||||
//! Make value always positive
|
||||
void makePositive()
|
||||
{
|
||||
if (this->m_value < 0) { this->m_value *= -1.0; }
|
||||
}
|
||||
|
||||
//! Make value always negative
|
||||
void makeNegative()
|
||||
{
|
||||
if (this->m_value > 0) { this->m_value *= -1.0; }
|
||||
}
|
||||
|
||||
//! \copydoc CValueObject::marshallToDbus
|
||||
virtual void marshallToDbus(QDBusArgument &argument) const override;
|
||||
|
||||
//! \copydoc CValueObject::unmarshallFromDbus
|
||||
virtual void unmarshallFromDbus(const QDBusArgument &argument) override;
|
||||
|
||||
//! \copydoc CValueObject::getValueHash
|
||||
virtual uint getValueHash() const override;
|
||||
|
||||
//! \copydoc CValueObject::toJson
|
||||
virtual QJsonObject toJson() const override;
|
||||
|
||||
//! \copydoc CValueObject::convertFromJson
|
||||
virtual void convertFromJson(const QJsonObject &json) override;
|
||||
|
||||
//! Parse to string, with specified separator
|
||||
virtual void parseFromString(const QString &value, CPqString::SeparatorMode mode)
|
||||
{
|
||||
*this = CPqString::parse<PQ>(value, mode);
|
||||
}
|
||||
|
||||
//! \copydoc CValueObject::parseFromString
|
||||
virtual void parseFromString(const QString &value) override
|
||||
{
|
||||
*this = CPqString::parse<PQ>(value, CPqString::SeparatorsCLocale);
|
||||
}
|
||||
|
||||
//! \copydoc CValueObject::propertyByIndex
|
||||
virtual CVariant propertyByIndex(const BlackMisc::CPropertyIndex &index) const override;
|
||||
|
||||
//! \copydoc CValueObject::setPropertyByIndex
|
||||
virtual void setPropertyByIndex(const CVariant &variant, const BlackMisc::CPropertyIndex &index) override;
|
||||
|
||||
protected:
|
||||
//! Constructor with double
|
||||
CPhysicalQuantity(double value, const MU &unit);
|
||||
|
||||
//! Constructor by parsed string, e.g. 10m
|
||||
CPhysicalQuantity(const QString &unitString) : m_value(0.0), m_unit(MU::nullUnit())
|
||||
{
|
||||
this->parseFromString(unitString);
|
||||
}
|
||||
|
||||
//! \copydoc CValueObject::convertToQString
|
||||
virtual QString convertToQString(bool i18n = false) const override;
|
||||
|
||||
private:
|
||||
double m_value; //!< numeric part
|
||||
MU m_unit; //!< unit part
|
||||
|
||||
//! Which subclass of CMeasurementUnit is used?
|
||||
typedef MU UnitClass;
|
||||
|
||||
//! Implementation of compare
|
||||
static int compareImpl(const PQ &, const PQ &);
|
||||
|
||||
//! Easy access to derived class (CRTP template parameter)
|
||||
PQ const *derived() const { return static_cast<PQ const *>(this); }
|
||||
|
||||
//! Easy access to derived class (CRTP template parameter)
|
||||
PQ *derived() { return static_cast<PQ *>(this); }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // guard
|
||||
34
src/blackmisc/pq/pq.h
Normal file
34
src/blackmisc/pq/pq.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/* Copyright (C) 2013
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
|
||||
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
||||
* contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef BLACKMISC_PQ_PQ_H
|
||||
#define BLACKMISC_PQ_PQ_H
|
||||
|
||||
/*!
|
||||
* \namespace BlackMisc::PhysicalQuantities
|
||||
* \brief Classes for physical quantities and units such as length, mass, speed.
|
||||
*/
|
||||
|
||||
// All units / quantities, required for the instantiations of the template
|
||||
// especially as CRTP (Curiously recurring template pattern) is used.
|
||||
// http://www.parashift.com/c++-faq-lite/separate-template-fn-defn-from-decl.html
|
||||
// http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
|
||||
|
||||
#include "blackmisc/pq/length.h"
|
||||
#include "blackmisc/pq/frequency.h"
|
||||
#include "blackmisc/pq/pressure.h"
|
||||
#include "blackmisc/pq/mass.h"
|
||||
#include "blackmisc/pq/speed.h"
|
||||
#include "blackmisc/pq/temperature.h"
|
||||
#include "blackmisc/pq/angle.h"
|
||||
#include "blackmisc/pq/time.h"
|
||||
#include "blackmisc/pq/acceleration.h"
|
||||
#include "blackmisc/pq/pqstring.h"
|
||||
|
||||
#endif // guard
|
||||
128
src/blackmisc/pq/pqstring.cpp
Normal file
128
src/blackmisc/pq/pqstring.cpp
Normal file
@@ -0,0 +1,128 @@
|
||||
/* Copyright (C) 2013
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
|
||||
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
||||
* contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "blackmisc/pq/pqstring.h"
|
||||
#include "blackmisc/tuple.h"
|
||||
#include "blackmisc/pq/pq.h"
|
||||
#include <QThreadStorage>
|
||||
|
||||
namespace BlackMisc
|
||||
{
|
||||
namespace PhysicalQuantities
|
||||
{
|
||||
|
||||
QString CPqString::convertToQString(bool /** i18n **/) const
|
||||
{
|
||||
return this->m_string;
|
||||
}
|
||||
|
||||
CVariant CPqString::parseToVariant(const QString &value, SeparatorMode mode)
|
||||
{
|
||||
CVariant v;
|
||||
|
||||
// fine tuning of the string
|
||||
QString vs = value.trimmed().simplified();
|
||||
|
||||
// check
|
||||
if (vs.isEmpty()) { return v; }
|
||||
|
||||
static QThreadStorage<QRegExp> tsRegex;
|
||||
if (! tsRegex.hasLocalData()) { tsRegex.setLocalData(QRegExp("([-+]?[0-9]*[\\.,]?[0-9]+)\\s*(\\D*)$")); }
|
||||
const auto ®ex = tsRegex.localData();
|
||||
|
||||
if (regex.indexIn(value) < 0) { return v; } // not a valid number
|
||||
QString unit = regex.cap(2).trimmed();
|
||||
QString number = QString(value).replace(unit, "");
|
||||
unit = unit.trimmed(); // trim after replace, not before
|
||||
|
||||
if (unit.isEmpty() || number.isEmpty()) { return v; }
|
||||
bool success;
|
||||
double numberD = parseNumber(number, success, mode);
|
||||
if (!success) {return v; }
|
||||
|
||||
if (CMeasurementUnit::isValidUnitSymbol<CAccelerationUnit>(unit))
|
||||
{
|
||||
CAcceleration pq(numberD, CMeasurementUnit::unitFromSymbol<CAccelerationUnit>(unit, false));
|
||||
return pq.toCVariant();
|
||||
}
|
||||
|
||||
if (CMeasurementUnit::isValidUnitSymbol<CAngleUnit>(unit))
|
||||
{
|
||||
CAngle pq(numberD, CMeasurementUnit::unitFromSymbol<CAngleUnit>(unit, false));
|
||||
return pq.toCVariant();
|
||||
}
|
||||
|
||||
if (CMeasurementUnit::isValidUnitSymbol<CFrequencyUnit>(unit))
|
||||
{
|
||||
CFrequency pq(numberD, CMeasurementUnit::unitFromSymbol<CFrequencyUnit>(unit, false));
|
||||
return pq.toCVariant();
|
||||
}
|
||||
|
||||
if (CMeasurementUnit::isValidUnitSymbol<CLengthUnit>(unit))
|
||||
{
|
||||
CLength pq(numberD, CMeasurementUnit::unitFromSymbol<CLengthUnit>(unit, false));
|
||||
return pq.toCVariant();
|
||||
}
|
||||
|
||||
if (CMeasurementUnit::isValidUnitSymbol<CMassUnit>(unit))
|
||||
{
|
||||
CMass pq(numberD, CMeasurementUnit::unitFromSymbol<CMassUnit>(unit, false));
|
||||
return pq.toCVariant();
|
||||
}
|
||||
|
||||
if (CMeasurementUnit::isValidUnitSymbol<CPressureUnit>(unit))
|
||||
{
|
||||
CPressure pq(numberD, CMeasurementUnit::unitFromSymbol<CPressureUnit>(unit, false));
|
||||
return pq.toCVariant();
|
||||
}
|
||||
|
||||
if (CMeasurementUnit::isValidUnitSymbol<CSpeedUnit>(unit))
|
||||
{
|
||||
CSpeed pq(numberD, CMeasurementUnit::unitFromSymbol<CSpeedUnit>(unit, false));
|
||||
return pq.toCVariant();
|
||||
}
|
||||
|
||||
if (CMeasurementUnit::isValidUnitSymbol<CTimeUnit>(unit))
|
||||
{
|
||||
CTime pq(numberD, CMeasurementUnit::unitFromSymbol<CTimeUnit>(unit, false));
|
||||
return pq.toCVariant();
|
||||
}
|
||||
|
||||
if (CMeasurementUnit::isValidUnitSymbol<CTemperatureUnit>(unit))
|
||||
{
|
||||
CTemperature pq(numberD, CMeasurementUnit::unitFromSymbol<CTemperatureUnit>(unit, false));
|
||||
return pq.toCVariant();
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
double CPqString::parseNumber(const QString &number, bool &success, CPqString::SeparatorMode mode)
|
||||
{
|
||||
double numberD = -1;
|
||||
switch (mode)
|
||||
{
|
||||
case SeparatorsLocale:
|
||||
numberD = QLocale::system().toDouble(number, &success);
|
||||
break;
|
||||
case SeparatorsCLocale:
|
||||
numberD = number.toDouble(&success);
|
||||
break;
|
||||
case SeparatorsBestGuess:
|
||||
numberD = number.toDouble(&success);
|
||||
if (!success) { numberD = QLocale::system().toDouble(number, &success); }
|
||||
break;
|
||||
default:
|
||||
qFatal("Wrong mode");
|
||||
break;
|
||||
}
|
||||
return numberD;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
88
src/blackmisc/pq/pqstring.h
Normal file
88
src/blackmisc/pq/pqstring.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/* Copyright (C) 2013
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
|
||||
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
||||
* contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef BLACKMISC_PQ_PQSTRING_H
|
||||
#define BLACKMISC_PQ_PQSTRING_H
|
||||
|
||||
#include "blackmisc/valueobject.h"
|
||||
#include "blackmisc/blackmiscfreefunctions.h"
|
||||
#include "blackmisc/variant.h"
|
||||
|
||||
namespace BlackMisc
|
||||
{
|
||||
namespace PhysicalQuantities
|
||||
{
|
||||
|
||||
/*!
|
||||
* \brief Represents a physical quantity by a string
|
||||
* \details Used to parse strings into physical quantities, validate strings
|
||||
* \sa BlackMisc::PhysicalQuantity
|
||||
*/
|
||||
class CPqString : public CValueObject<CPqString>
|
||||
{
|
||||
protected:
|
||||
//! \copydoc CValueObject::convertToQString
|
||||
virtual QString convertToQString(bool i18n = false) const override;
|
||||
|
||||
public:
|
||||
//! Number separators / group separators
|
||||
enum SeparatorMode
|
||||
{
|
||||
SeparatorsCLocale, //!< 100,000.00
|
||||
SeparatorsLocale, //!< depending on QLocale, e.g. 100.000,00 in Germany
|
||||
SeparatorsBestGuess //!< try to figure out
|
||||
};
|
||||
|
||||
//! Group and digit separator
|
||||
enum SeparatorIndex
|
||||
{
|
||||
Group,
|
||||
Digit
|
||||
};
|
||||
|
||||
//! Default constructor
|
||||
CPqString() = default;
|
||||
|
||||
//! Constructor, for values such as 10km/h
|
||||
CPqString(const QString &value) : m_string(value) {}
|
||||
|
||||
//! Parse a string value like "100m", "10.3Mhz"
|
||||
static CVariant parseToVariant(const QString &value, SeparatorMode mode = SeparatorsCLocale);
|
||||
|
||||
//! Parse into concrete type
|
||||
template <class PQ> static PQ parse(const QString &value, SeparatorMode mode = SeparatorsCLocale)
|
||||
{
|
||||
PQ invalid;
|
||||
invalid.setNull();
|
||||
if (value.isEmpty()) return invalid;
|
||||
CVariant qv = parseToVariant(value, mode);
|
||||
if (!qv.isNull() && qv.canConvert<PQ>())
|
||||
{
|
||||
return qv.value<PQ>();
|
||||
}
|
||||
return invalid;
|
||||
}
|
||||
|
||||
//! Locale aware parsing
|
||||
static double parseNumber(const QString &number, bool &success, SeparatorMode mode = SeparatorsCLocale);
|
||||
|
||||
private:
|
||||
BLACK_ENABLE_TUPLE_CONVERSION(CPqString)
|
||||
QString m_string;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
BLACK_DECLARE_TUPLE_CONVERSION(BlackMisc::PhysicalQuantities::CPqString, (o.m_string))
|
||||
Q_DECLARE_METATYPE(BlackMisc::PhysicalQuantities::CPqString)
|
||||
|
||||
#endif // guard
|
||||
43
src/blackmisc/pq/pressure.h
Normal file
43
src/blackmisc/pq/pressure.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/* Copyright (C) 2013
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
|
||||
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
||||
* contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef BLACKMISC_PQ_PRESSURE_H
|
||||
#define BLACKMISC_PQ_PRESSURE_H
|
||||
|
||||
#include "blackmisc/pq/physicalquantity.h"
|
||||
|
||||
namespace BlackMisc
|
||||
{
|
||||
namespace PhysicalQuantities
|
||||
{
|
||||
|
||||
/*!
|
||||
* Physical unit distance
|
||||
*/
|
||||
class CPressure : public CValueObject<CPressure, CPhysicalQuantity<CPressureUnit, CPressure>>
|
||||
{
|
||||
public:
|
||||
//! Default constructor
|
||||
CPressure() : CValueObject(0, CPressureUnit::defaultUnit()) {}
|
||||
|
||||
//! Init by double value
|
||||
CPressure(double value, const CPressureUnit &unit) : CValueObject(value, unit) {}
|
||||
|
||||
//! \copydoc CPhysicalQuantity(const QString &unitString)
|
||||
CPressure(const QString &unitString) : CValueObject(unitString) {}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(BlackMisc::PhysicalQuantities::CPressure)
|
||||
|
||||
#endif // BLACKMISC_PQPRESSURE_H
|
||||
43
src/blackmisc/pq/speed.h
Normal file
43
src/blackmisc/pq/speed.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/* Copyright (C) 2013
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
|
||||
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
||||
* contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef BLACKMISC_PQ_SPEED_H
|
||||
#define BLACKMISC_PQ_SPEED_H
|
||||
|
||||
#include "blackmisc/pq/physicalquantity.h"
|
||||
|
||||
namespace BlackMisc
|
||||
{
|
||||
namespace PhysicalQuantities
|
||||
{
|
||||
|
||||
/*!
|
||||
* Speed class, e.g. "m/s", "NM/h", "km/h", "ft/s"
|
||||
*/
|
||||
class CSpeed : public CValueObject<CSpeed, CPhysicalQuantity<CSpeedUnit, CSpeed>>
|
||||
{
|
||||
public:
|
||||
//! Default constructor
|
||||
CSpeed() : CValueObject(0, CSpeedUnit::defaultUnit()) {}
|
||||
|
||||
//! Init by double value
|
||||
CSpeed(double value, const CSpeedUnit &unit) : CValueObject(value, unit) {}
|
||||
|
||||
//! \copydoc CPhysicalQuantity(const QString &unitString)
|
||||
CSpeed(const QString &unitString) : CValueObject(unitString) {}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(BlackMisc::PhysicalQuantities::CSpeed)
|
||||
|
||||
#endif // guard
|
||||
43
src/blackmisc/pq/temperature.h
Normal file
43
src/blackmisc/pq/temperature.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/* Copyright (C) 2013
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
|
||||
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
||||
* contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef BLACKMISC_PQ_TEMPERATURE_H
|
||||
#define BLACKMISC_PQ_TEMPERATURE_H
|
||||
|
||||
#include "blackmisc/pq/physicalquantity.h"
|
||||
|
||||
namespace BlackMisc
|
||||
{
|
||||
namespace PhysicalQuantities
|
||||
{
|
||||
|
||||
/*!
|
||||
* Physical unit temperature
|
||||
*/
|
||||
class CTemperature : public CValueObject<CTemperature, CPhysicalQuantity<CTemperatureUnit, CTemperature>>
|
||||
{
|
||||
public:
|
||||
//! Default constructor
|
||||
CTemperature() : CValueObject(0, CTemperatureUnit::defaultUnit()) {}
|
||||
|
||||
//! Init by double value
|
||||
CTemperature(double value, const CTemperatureUnit &unit): CValueObject(value, unit) {}
|
||||
|
||||
//! \copydoc CPhysicalQuantity(const QString &unitString)
|
||||
CTemperature(const QString &unitString) : CValueObject(unitString) {}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(BlackMisc::PhysicalQuantities::CTemperature)
|
||||
|
||||
#endif // guard
|
||||
141
src/blackmisc/pq/time.cpp
Normal file
141
src/blackmisc/pq/time.cpp
Normal file
@@ -0,0 +1,141 @@
|
||||
/* Copyright (C) 2013
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
|
||||
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
||||
* contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "blackmisc/pq/time.h"
|
||||
|
||||
namespace BlackMisc
|
||||
{
|
||||
namespace PhysicalQuantities
|
||||
{
|
||||
CTime::CTime(int hours, int minutes, int seconds) : CValueObject(0, CTimeUnit::nullUnit())
|
||||
{
|
||||
bool negative = (hours < 0);
|
||||
double value = qAbs(hours) + minutes / 100.0 + seconds / 10000.0;
|
||||
if (minutes == 0 && seconds == 0)
|
||||
{
|
||||
(*this) = CTime(hours, CTimeUnit::h());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (seconds == 0)
|
||||
(*this) = CTime(value, CTimeUnit::hrmin());
|
||||
else
|
||||
(*this) = CTime(value, CTimeUnit::hms());
|
||||
}
|
||||
if (negative)
|
||||
{
|
||||
this->makeNegative();
|
||||
}
|
||||
}
|
||||
|
||||
CTime::CTime(const QTime &time, bool negative) : CValueObject(0, CTimeUnit::nullUnit())
|
||||
{
|
||||
CTime converted(time.hour(), time.minute(), time.second());
|
||||
(*this) = converted;
|
||||
if (negative)
|
||||
{
|
||||
this->makeNegative();
|
||||
}
|
||||
}
|
||||
|
||||
void CTime::parseFromString(const QString &time)
|
||||
{
|
||||
QTime t;
|
||||
QString ts = time.trimmed();
|
||||
|
||||
// deal with sign
|
||||
double factor = 1.0;
|
||||
if (ts.startsWith('+'))
|
||||
{
|
||||
ts.remove(0, 1);
|
||||
}
|
||||
else if (ts.startsWith('-'))
|
||||
{
|
||||
factor = -1.0;
|
||||
ts.remove(0, 1);
|
||||
}
|
||||
|
||||
if (ts.contains(":") && (ts.length() == 8 || ts.length() == 5))
|
||||
{
|
||||
if (ts.length() == 5)
|
||||
t = QTime::fromString(ts, "hh:mm");
|
||||
else if (ts.length() == 8)
|
||||
t = QTime::fromString(ts, "hh:mm:ss");
|
||||
(*this) = CTime(t);
|
||||
|
||||
// fix sign if required
|
||||
if (factor < 0)
|
||||
{
|
||||
this->setValueSameUnit(this->value() * factor);
|
||||
}
|
||||
}
|
||||
else
|
||||
CPhysicalQuantity::parseFromString(time);
|
||||
}
|
||||
|
||||
QTime CTime::toQTime() const
|
||||
{
|
||||
CTime copy(*this);
|
||||
copy.setUnit(CTimeUnit::hms());
|
||||
|
||||
// QTime is not defined for negative numbers
|
||||
// so we use the absolute value here
|
||||
copy.makePositive();
|
||||
|
||||
// convert
|
||||
QString s = copy.toQString(false).replace('h', ':').replace('m', ':').replace('s', "");
|
||||
QTime t = s.length() == 8 ?
|
||||
QTime::fromString(s, "hh:mm:ss") :
|
||||
QTime::fromString(s, "hh:mm");
|
||||
return t;
|
||||
}
|
||||
|
||||
QList<int> CTime::getHrsMinSecParts() const
|
||||
{
|
||||
QTime t = this->toQTime();
|
||||
QList<int> parts;
|
||||
parts << t.hour() << t.minute() << t.second();
|
||||
return parts;
|
||||
}
|
||||
|
||||
QString CTime::formattedHrsMinSec() const
|
||||
{
|
||||
QList<int> parts = getHrsMinSecParts();
|
||||
QString h = QString("00%1").arg(QString::number(parts.at(0))).right(2);
|
||||
QString m = QString("00%1").arg(QString::number(parts.at(1))).right(2);
|
||||
QString s = QString("00%1").arg(QString::number(parts.at(2))).right(2);
|
||||
|
||||
QString fs = QString("%1:%2:%3").arg(h).arg(m).arg(s);
|
||||
if (this->isNegativeWithEpsilonConsidered())
|
||||
{
|
||||
return QString("-").append(fs);
|
||||
}
|
||||
else
|
||||
{
|
||||
return fs;
|
||||
}
|
||||
}
|
||||
|
||||
QString CTime::formattedHrsMin() const
|
||||
{
|
||||
QList<int> parts = getHrsMinSecParts();
|
||||
QString h = QString("00%1").arg(QString::number(parts.at(0))).right(2);
|
||||
QString m = QString("00%1").arg(QString::number(parts.at(1))).right(2);
|
||||
QString fs = QString("%1:%2").arg(h).arg(m);
|
||||
if (this->isNegativeWithEpsilonConsidered())
|
||||
{
|
||||
return QString("-").append(fs);
|
||||
}
|
||||
else
|
||||
{
|
||||
return fs;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
74
src/blackmisc/pq/time.h
Normal file
74
src/blackmisc/pq/time.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/* Copyright (C) 2013
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
|
||||
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
||||
* contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef BLACKMISC_PQ_TIME_H
|
||||
#define BLACKMISC_PQ_TIME_H
|
||||
|
||||
#include "blackmisc/pq/physicalquantity.h"
|
||||
|
||||
namespace BlackMisc
|
||||
{
|
||||
namespace PhysicalQuantities
|
||||
{
|
||||
|
||||
/*!
|
||||
* Time class, e.g. "ms", "hour", "s", "day"
|
||||
*/
|
||||
class CTime : public CValueObject<CTime, CPhysicalQuantity<CTimeUnit, CTime>>
|
||||
{
|
||||
public:
|
||||
//! Parts
|
||||
enum Parts
|
||||
{
|
||||
Hours = 0,
|
||||
Minutes,
|
||||
Seconds
|
||||
};
|
||||
|
||||
//! Default constructor
|
||||
CTime() : CValueObject(0, CTimeUnit::defaultUnit()) {}
|
||||
|
||||
//! Init by double value
|
||||
CTime(double value, const CTimeUnit &unit) : CValueObject(value, unit) {}
|
||||
|
||||
//! By hours, minutes, seconds
|
||||
CTime(int hours, int minutes, int seconds = 0);
|
||||
|
||||
//! By Qt time
|
||||
CTime(const QTime &time, bool negative = false);
|
||||
|
||||
//! \copydoc CPhysicalQuantity(const QString &unitString)
|
||||
CTime(const QString &unitString) : CValueObject(0, CTimeUnit::nullUnit()) { this->parseFromString(unitString); }
|
||||
|
||||
//! From string hh:mm, or hh:mm:ss, or time units such as s, min
|
||||
virtual void parseFromString(const QString &time) override;
|
||||
|
||||
//! To Qt time
|
||||
//! \warning sign not considered
|
||||
QTime toQTime() const;
|
||||
|
||||
//! Parts hh, mm, ss
|
||||
//! \warning sign not considered
|
||||
QList<int> getHrsMinSecParts() const;
|
||||
|
||||
//! Formatted as hh:mm:ss
|
||||
QString formattedHrsMinSec() const;
|
||||
|
||||
//! Formatted as hh:mm
|
||||
QString formattedHrsMin() const;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(BlackMisc::PhysicalQuantities::CTime)
|
||||
|
||||
#endif // guard
|
||||
93
src/blackmisc/pq/units.cpp
Normal file
93
src/blackmisc/pq/units.cpp
Normal file
@@ -0,0 +1,93 @@
|
||||
/* Copyright (C) 2013
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
|
||||
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
||||
* contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "blackmisc/pq/units.h"
|
||||
|
||||
namespace BlackMisc
|
||||
{
|
||||
namespace PhysicalQuantities
|
||||
{
|
||||
using BlackMisc::Math::CMathUtils;
|
||||
|
||||
QString CAngleUnit::makeRoundedQStringWithUnit(double value, int digits, bool i18n) const
|
||||
{
|
||||
if (digits < 0) digits = this->getDisplayDigits();
|
||||
QString s;
|
||||
if ((*this) == CAngleUnit::sexagesimalDeg())
|
||||
{
|
||||
digits -= 4;
|
||||
Q_ASSERT(digits >= 0);
|
||||
double de = CMathUtils::trunc(value);
|
||||
double mi = CMathUtils::trunc((value - de) * 100.0);
|
||||
double se = CMathUtils::trunc((value - de - mi / 100.0) * 1000000) / 100.0;
|
||||
const char *fmt = value < 0 ? "-%L1 %L2 %L3" : "%L1 %L2 %L3";
|
||||
s = i18n ? QCoreApplication::translate("CMeasurementUnit", fmt) : fmt;
|
||||
s = s.arg(fabs(de), 0, 'f', 0).arg(fabs(mi), 2, 'f', 0, '0').arg(fabs(se), 2, 'f', digits, '0');
|
||||
}
|
||||
else if ((*this) == CAngleUnit::sexagesimalDegMin())
|
||||
{
|
||||
digits -= 2;
|
||||
Q_ASSERT(digits >= 0);
|
||||
double de = CMathUtils::trunc(value);
|
||||
double mi = CMathUtils::trunc((value - de) * 100.0);
|
||||
const char *fmt = value < 0 ? "-%L1 %L2" : "%L1 %L2";
|
||||
s = i18n ? QCoreApplication::translate("CMeasurementUnit", fmt) : fmt;
|
||||
s = s.arg(fabs(de), 0, 'f', 0).arg(fabs(mi), 2, 'f', digits, '0');
|
||||
}
|
||||
else
|
||||
{
|
||||
s = this->CMeasurementUnit::makeRoundedQStringWithUnit(value, digits, i18n);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
QString CTimeUnit::makeRoundedQStringWithUnit(double value, int digits, bool i18n) const
|
||||
{
|
||||
if (digits < 0) digits = this->getDisplayDigits();
|
||||
QString s;
|
||||
if ((*this) == CTimeUnit::hms())
|
||||
{
|
||||
digits -= 4;
|
||||
Q_ASSERT(digits >= 0);
|
||||
double hr = CMathUtils::trunc(value);
|
||||
double mi = CMathUtils::trunc((value - hr) * 100.0);
|
||||
double se = CMathUtils::trunc((value - hr - mi / 100.0) * 1000000) / 100.0;
|
||||
const char *fmt = value < 0 ? "-%L1h%L2m%L3s" : "%L1h%L2m%L3s";
|
||||
s = i18n ? QCoreApplication::translate("CMeasurementUnit", fmt) : fmt;
|
||||
s = s.arg(fabs(hr), 2, 'f', 0, '0').arg(fabs(mi), 2, 'f', 0, '0').arg(fabs(se), 2, 'f', digits, '0');
|
||||
}
|
||||
else if ((*this) == CTimeUnit::hrmin())
|
||||
{
|
||||
digits -= 2;
|
||||
Q_ASSERT(digits >= 0);
|
||||
double hr = CMathUtils::trunc(value);
|
||||
double mi = CMathUtils::trunc((value - hr) * 100.0);
|
||||
const char *fmt = value < 0 ? "-%L1h%L2m" : "%L1h%L2m";
|
||||
s = i18n ? QCoreApplication::translate("CMeasurementUnit", fmt) : fmt;
|
||||
s = s.arg(fabs(hr), 2, 'f', 0, '0').arg(fabs(mi), 2, 'f', digits, '0');
|
||||
}
|
||||
else if ((*this) == CTimeUnit::minsec())
|
||||
{
|
||||
digits -= 2;
|
||||
Q_ASSERT(digits >= 0);
|
||||
double mi = CMathUtils::trunc(value);
|
||||
double se = CMathUtils::trunc((value - mi) * 100.0);
|
||||
const char *fmt = value < 0 ? "-%L2m%L3s" : "%L2m%L3s";
|
||||
s = i18n ? QCoreApplication::translate("CMeasurementUnit", fmt) : fmt;
|
||||
s = s.arg(fabs(mi), 2, 'f', 0, '0').arg(fabs(se), 2, 'f', digits, '0');
|
||||
}
|
||||
else
|
||||
{
|
||||
s = this->CMeasurementUnit::makeRoundedQStringWithUnit(value, digits, i18n);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
911
src/blackmisc/pq/units.h
Normal file
911
src/blackmisc/pq/units.h
Normal file
@@ -0,0 +1,911 @@
|
||||
/* Copyright (C) 2013
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
|
||||
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
||||
* contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef BLACKMISC_PQ_UNITS_H
|
||||
#define BLACKMISC_PQ_UNITS_H
|
||||
|
||||
#pragma push_macro("min")
|
||||
#undef min
|
||||
|
||||
#include "blackmisc/pq/measurementunit.h"
|
||||
#include "blackmisc/blackmiscfreefunctions.h"
|
||||
#include <QtDBus/QDBusArgument>
|
||||
#include <QList>
|
||||
#include <QtCore/qmath.h>
|
||||
#include <QTranslator>
|
||||
|
||||
//
|
||||
// Used with the template for quantities. This is the reason for
|
||||
// having all units in one file, since template requires concrete instantiations
|
||||
//
|
||||
// I18N: http://qt-project.org/doc/qt-4.8/linguist-programmers.html#translating-text-that-is-outside-of-a-qobject-subclass
|
||||
//
|
||||
namespace BlackMisc
|
||||
{
|
||||
namespace PhysicalQuantities
|
||||
{
|
||||
|
||||
//! Specialized class for distance units (meter, foot, nautical miles).
|
||||
class CLengthUnit : public CValueObject<CLengthUnit, CMeasurementUnit>
|
||||
{
|
||||
private:
|
||||
template <class Converter>
|
||||
CLengthUnit(const QString &name, const QString &symbol, const Converter &converter, int displayDigits = 2, double epsilon = 1E-9) :
|
||||
CValueObject(name, symbol, converter, displayDigits, epsilon)
|
||||
{}
|
||||
|
||||
//! null constructor
|
||||
CLengthUnit(const QString &name, const QString &symbol, std::nullptr_t) :
|
||||
CValueObject(name, symbol, nullptr)
|
||||
{}
|
||||
|
||||
struct NauticalMilesToMeters { static double factor() { return 1852.0; } };
|
||||
struct FeetToMeters { static double factor() { return 0.3048; } };
|
||||
struct MilesToMeters { static double factor() { return 1609.344; } };
|
||||
struct StatuteMilesToMeters { static double factor() { return 1609.3472; } };
|
||||
typedef One MetersToMeters;
|
||||
|
||||
public:
|
||||
//! Default constructor, required for Qt Metasystem
|
||||
CLengthUnit() : CValueObject(defaultUnit()) {}
|
||||
|
||||
//! Default unit
|
||||
static const CLengthUnit &defaultUnit() { return m(); }
|
||||
|
||||
//! Null unit
|
||||
static const CLengthUnit &nullUnit()
|
||||
{
|
||||
static CLengthUnit nu("null", "null", nullptr);
|
||||
return nu;
|
||||
}
|
||||
|
||||
//! Meter m
|
||||
static const CLengthUnit &m()
|
||||
{
|
||||
static CLengthUnit m(QT_TRANSLATE_NOOP("CMeasurementUnit", "meter"), "m", IdentityConverter());
|
||||
return m;
|
||||
}
|
||||
|
||||
//! Nautical miles NM
|
||||
static const CLengthUnit &NM()
|
||||
{
|
||||
static CLengthUnit NM(QT_TRANSLATE_NOOP("CMeasurementUnit", "nautical mile"), "NM", LinearConverter<NauticalMilesToMeters>(), 3);
|
||||
return NM;
|
||||
}
|
||||
|
||||
//! Foot ft
|
||||
static const CLengthUnit &ft()
|
||||
{
|
||||
static CLengthUnit ft(QT_TRANSLATE_NOOP("CMeasurementUnit", "foot"), "ft", LinearConverter<FeetToMeters>(), 1);
|
||||
return ft;
|
||||
}
|
||||
|
||||
//! Kilometer km
|
||||
static const CLengthUnit &km()
|
||||
{
|
||||
static CLengthUnit km(QT_TRANSLATE_NOOP("CMeasurementUnit", "kilometer"), "km", LinearConverter<Kilo<MetersToMeters> >(), 3);
|
||||
return km;
|
||||
}
|
||||
|
||||
//! Centimeter cm
|
||||
static const CLengthUnit &cm()
|
||||
{
|
||||
static CLengthUnit cm(QT_TRANSLATE_NOOP("CMeasurementUnit", "centimeter"), "cm", LinearConverter<Centi<MetersToMeters> >(), 1);
|
||||
return cm;
|
||||
}
|
||||
|
||||
//! International mile
|
||||
static const CLengthUnit &mi()
|
||||
{
|
||||
static CLengthUnit mi(QT_TRANSLATE_NOOP("CMeasurementUnit", "mile"), "mi", LinearConverter<MilesToMeters>(), 3);
|
||||
return mi;
|
||||
}
|
||||
|
||||
//! Statute mile
|
||||
static const CLengthUnit &SM()
|
||||
{
|
||||
static CLengthUnit sm(QT_TRANSLATE_NOOP("CMeasurementUnit", "statute mile"), "SM", LinearConverter<StatuteMilesToMeters>(), 3);
|
||||
return sm;
|
||||
}
|
||||
|
||||
//! All units
|
||||
static const QList<CLengthUnit> &allUnits()
|
||||
{
|
||||
static QList<CLengthUnit> u;
|
||||
if (u.isEmpty())
|
||||
{
|
||||
u.append(CLengthUnit::nullUnit());
|
||||
u.append(CLengthUnit::cm());
|
||||
u.append(CLengthUnit::ft());
|
||||
u.append(CLengthUnit::km());
|
||||
u.append(CLengthUnit::m());
|
||||
u.append(CLengthUnit::mi());
|
||||
u.append(CLengthUnit::SM());
|
||||
u.append(CLengthUnit::NM());
|
||||
}
|
||||
return u;
|
||||
}
|
||||
|
||||
protected:
|
||||
//! \copydoc CValueObject::unmarshallFromDbus
|
||||
virtual void unmarshallFromDbus(const QDBusArgument &argument) override
|
||||
{
|
||||
QString unitName;
|
||||
argument >> unitName;
|
||||
(*this) = CMeasurementUnit::unitFromSymbol<CLengthUnit>(unitName);
|
||||
}
|
||||
};
|
||||
|
||||
//! Specialized class for angles (degrees, radian).
|
||||
class CAngleUnit : public CValueObject<CAngleUnit, CMeasurementUnit>
|
||||
{
|
||||
private:
|
||||
template <class Converter>
|
||||
CAngleUnit(const QString &name, const QString &symbol, const Converter &converter, int displayDigits = 2, double epsilon = 1E-9) :
|
||||
CValueObject(name, symbol, converter, displayDigits, epsilon)
|
||||
{}
|
||||
|
||||
CAngleUnit(const QString &name, const QString &symbol, std::nullptr_t) :
|
||||
CValueObject(name, symbol, nullptr)
|
||||
{}
|
||||
|
||||
struct RadiansToDegrees { static double factor() { return 180.0 / M_PI; } };
|
||||
typedef One DegreesToDegrees;
|
||||
|
||||
public:
|
||||
//! Default constructor, required for Qt Metasystem
|
||||
CAngleUnit() : CValueObject(defaultUnit()) {}
|
||||
|
||||
//! Default unit
|
||||
static const CAngleUnit &defaultUnit() { return deg(); }
|
||||
|
||||
//! Null unit
|
||||
static const CAngleUnit &nullUnit()
|
||||
{
|
||||
static CAngleUnit nu("null", "null", nullptr);
|
||||
return nu;
|
||||
}
|
||||
|
||||
//! \copydoc CMeasurementUnit::makeRoundedQStringWithUnit
|
||||
virtual QString makeRoundedQStringWithUnit(double value, int digits = -1, bool i18n = false) const override;
|
||||
|
||||
//! Radians
|
||||
static const CAngleUnit &rad()
|
||||
{
|
||||
static CAngleUnit rad(QT_TRANSLATE_NOOP("CMeasurementUnit", "radian"), "rad", LinearConverter<RadiansToDegrees>());
|
||||
return rad;
|
||||
}
|
||||
|
||||
//! Degrees
|
||||
static const CAngleUnit °()
|
||||
{
|
||||
static CAngleUnit deg(QT_TRANSLATE_NOOP("CMeasurementUnit", "degree"), QT_TRANSLATE_NOOP("CMeasurementUnit", "deg"), IdentityConverter());
|
||||
return deg;
|
||||
}
|
||||
|
||||
//! Sexagesimal degree (degrees, minutes, seconds, decimal seconds)
|
||||
static const CAngleUnit &sexagesimalDeg()
|
||||
{
|
||||
static CAngleUnit deg(QT_TRANSLATE_NOOP("CMeasurementUnit", "degree, minute, second"), "DMS", SubdivisionConverter2<DegreesToDegrees, InEachHundred<60> >(), 4);
|
||||
return deg;
|
||||
(void)QT_TRANSLATE_NOOP("CMeasurementUnit", "%L1 %L2 %L3");
|
||||
(void)QT_TRANSLATE_NOOP("CMeasurementUnit", "-%L1 %L2 %L3");
|
||||
}
|
||||
|
||||
|
||||
//! Sexagesimal degree (degrees, minutes, decimal minutes)
|
||||
static const CAngleUnit &sexagesimalDegMin()
|
||||
{
|
||||
static CAngleUnit deg(QT_TRANSLATE_NOOP("CMeasurementUnit", "degree, minute"), "MinDec", SubdivisionConverter<DegreesToDegrees, InEachHundred<60> >(), 4);
|
||||
return deg;
|
||||
(void)QT_TRANSLATE_NOOP("CMeasurementUnit", "%L1 %L2");
|
||||
(void)QT_TRANSLATE_NOOP("CMeasurementUnit", "-%L1 %L2");
|
||||
}
|
||||
|
||||
//! All units
|
||||
static const QList<CAngleUnit> &allUnits()
|
||||
{
|
||||
static QList<CAngleUnit> u;
|
||||
if (u.isEmpty())
|
||||
{
|
||||
u.append(CAngleUnit::nullUnit());
|
||||
u.append(CAngleUnit::deg());
|
||||
u.append(CAngleUnit::rad());
|
||||
u.append(CAngleUnit::sexagesimalDeg());
|
||||
u.append(CAngleUnit::sexagesimalDegMin());
|
||||
}
|
||||
return u;
|
||||
}
|
||||
|
||||
protected:
|
||||
//! \copydoc CValueObject::unmarshallFromDbus
|
||||
virtual void unmarshallFromDbus(const QDBusArgument &argument) override
|
||||
{
|
||||
QString unitName;
|
||||
argument >> unitName;
|
||||
(*this) = CMeasurementUnit::unitFromSymbol<CAngleUnit>(unitName);
|
||||
}
|
||||
};
|
||||
|
||||
//! Specialized class for frequency (hertz, mega hertz, kilo hertz).
|
||||
class CFrequencyUnit : public CValueObject<CFrequencyUnit, CMeasurementUnit>
|
||||
{
|
||||
private:
|
||||
template <class Converter>
|
||||
CFrequencyUnit(const QString &name, const QString &symbol, const Converter &converter, int displayDigits = 2, double epsilon = 1E-9) :
|
||||
CValueObject(name, symbol, converter, displayDigits, epsilon)
|
||||
{}
|
||||
|
||||
CFrequencyUnit(const QString &name, const QString &symbol, std::nullptr_t) :
|
||||
CValueObject(name, symbol, nullptr)
|
||||
{}
|
||||
|
||||
typedef One HertzToHertz;
|
||||
|
||||
public:
|
||||
//! Default constructor, required for Qt Metasystem
|
||||
CFrequencyUnit() : CValueObject(defaultUnit()) {}
|
||||
|
||||
//! Default unit
|
||||
static const CFrequencyUnit &defaultUnit() { return Hz(); }
|
||||
|
||||
//! Null unit
|
||||
static const CFrequencyUnit &nullUnit()
|
||||
{
|
||||
static CFrequencyUnit nu("null", "null", nullptr);
|
||||
return nu;
|
||||
}
|
||||
|
||||
//! Hertz
|
||||
static const CFrequencyUnit &Hz()
|
||||
{
|
||||
static CFrequencyUnit Hz(QT_TRANSLATE_NOOP("CMeasurementUnit", "hertz"), "Hz", IdentityConverter());
|
||||
return Hz;
|
||||
}
|
||||
|
||||
//! Kilohertz
|
||||
static const CFrequencyUnit &kHz()
|
||||
{
|
||||
static CFrequencyUnit kHz(QT_TRANSLATE_NOOP("CMeasurementUnit", "kilohertz"), "kHz", LinearConverter<Kilo<HertzToHertz> >(), 1);
|
||||
return kHz;
|
||||
}
|
||||
|
||||
//! Megahertz
|
||||
static const CFrequencyUnit &MHz()
|
||||
{
|
||||
static CFrequencyUnit MHz(QT_TRANSLATE_NOOP("CMeasurementUnit", "megahertz"), "MHz", LinearConverter<Mega<HertzToHertz> >(), 2);
|
||||
return MHz;
|
||||
}
|
||||
|
||||
//! Gigahertz
|
||||
static const CFrequencyUnit &GHz()
|
||||
{
|
||||
static CFrequencyUnit GHz(QT_TRANSLATE_NOOP("CMeasurementUnit", "gigahertz"), "GHz", LinearConverter<Giga<HertzToHertz> >(), 2);
|
||||
return GHz;
|
||||
}
|
||||
|
||||
//! All units
|
||||
static const QList<CFrequencyUnit> &allUnits()
|
||||
{
|
||||
static QList<CFrequencyUnit> u;
|
||||
if (u.isEmpty())
|
||||
{
|
||||
u.append(CFrequencyUnit::nullUnit());
|
||||
u.append(CFrequencyUnit::GHz());
|
||||
u.append(CFrequencyUnit::Hz());
|
||||
u.append(CFrequencyUnit::kHz());
|
||||
u.append(CFrequencyUnit::MHz());
|
||||
}
|
||||
return u;
|
||||
}
|
||||
|
||||
protected:
|
||||
//! \copydoc CValueObject::unmarshallFromDbus
|
||||
virtual void unmarshallFromDbus(const QDBusArgument &argument) override
|
||||
{
|
||||
QString unitName;
|
||||
argument >> unitName;
|
||||
(*this) = CMeasurementUnit::unitFromSymbol<CFrequencyUnit>(unitName);
|
||||
}
|
||||
};
|
||||
|
||||
//! Specialized class for mass units (kg, lbs).
|
||||
class CMassUnit : public CValueObject<CMassUnit, CMeasurementUnit>
|
||||
{
|
||||
private:
|
||||
template <class Converter>
|
||||
CMassUnit(const QString &name, const QString &symbol, const Converter &converter, int displayDigits = 2, double epsilon = 1E-9) :
|
||||
CValueObject(name, symbol, converter, displayDigits, epsilon)
|
||||
{}
|
||||
|
||||
CMassUnit(const QString &name, const QString &symbol, std::nullptr_t) :
|
||||
CValueObject(name, symbol, nullptr)
|
||||
{}
|
||||
|
||||
typedef Milli<One> GramsToKilograms;
|
||||
struct PoundsToKilograms { static double factor() { return 0.45359237; } };
|
||||
|
||||
public:
|
||||
//! Default constructor, required for Qt Metasystem
|
||||
CMassUnit() : CValueObject(defaultUnit()) {}
|
||||
|
||||
//! Default unit
|
||||
static const CMassUnit &defaultUnit() { return kg(); }
|
||||
|
||||
//! Null unit
|
||||
static const CMassUnit &nullUnit()
|
||||
{
|
||||
static CMassUnit nu("null", "null", nullptr);
|
||||
return nu;
|
||||
}
|
||||
|
||||
//! Kilogram, SI base unit
|
||||
static const CMassUnit &kg()
|
||||
{
|
||||
static CMassUnit kg(QT_TRANSLATE_NOOP("CMeasurementUnit", "kilogram"), "kg", IdentityConverter(), 1);
|
||||
return kg;
|
||||
}
|
||||
|
||||
//! Gram, SI unit
|
||||
static const CMassUnit &g()
|
||||
{
|
||||
static CMassUnit g(QT_TRANSLATE_NOOP("CMeasurementUnit", "gram"), "g", LinearConverter<GramsToKilograms>(), 0);
|
||||
return g;
|
||||
}
|
||||
|
||||
//! Tonne, aka metric ton (1000kg)
|
||||
static const CMassUnit &tonne()
|
||||
{
|
||||
static CMassUnit t(QT_TRANSLATE_NOOP("CMeasurementUnit", "tonne"), "t", LinearConverter<Mega<GramsToKilograms> >(), 3);
|
||||
return t;
|
||||
}
|
||||
|
||||
//! Short ton (2000lb) used in the United States
|
||||
static const CMassUnit &shortTon()
|
||||
{
|
||||
static CMassUnit ton(QT_TRANSLATE_NOOP("CMeasurementUnit", "short ton"), "ton", LinearConverter<Two<Kilo<PoundsToKilograms> > >(), 3);
|
||||
return ton;
|
||||
}
|
||||
|
||||
//! Pound, aka mass pound
|
||||
static const CMassUnit &lb()
|
||||
{
|
||||
static CMassUnit lbs(QT_TRANSLATE_NOOP("CMeasurementUnit", "pound"), "lb", LinearConverter<PoundsToKilograms>(), 1);
|
||||
return lbs;
|
||||
}
|
||||
|
||||
//! All units
|
||||
static const QList<CMassUnit> &allUnits()
|
||||
{
|
||||
static QList<CMassUnit> u;
|
||||
if (u.isEmpty())
|
||||
{
|
||||
u.append(CMassUnit::nullUnit());
|
||||
u.append(CMassUnit::g());
|
||||
u.append(CMassUnit::kg());
|
||||
u.append(CMassUnit::lb());
|
||||
u.append(CMassUnit::tonne());
|
||||
u.append(CMassUnit::shortTon());
|
||||
}
|
||||
return u;
|
||||
}
|
||||
|
||||
protected:
|
||||
//! \copydoc CValueObject::unmarshallFromDbus
|
||||
virtual void unmarshallFromDbus(const QDBusArgument &argument) override
|
||||
{
|
||||
QString unitName;
|
||||
argument >> unitName;
|
||||
(*this) = CMeasurementUnit::unitFromSymbol<CMassUnit>(unitName);
|
||||
}
|
||||
};
|
||||
|
||||
//! Specialized class for pressure (psi, hPa, bar).
|
||||
class CPressureUnit : public CValueObject<CPressureUnit, CMeasurementUnit>
|
||||
{
|
||||
private:
|
||||
template <class Converter>
|
||||
CPressureUnit(const QString &name, const QString &symbol, const Converter &converter, int displayDigits = 2, double epsilon = 1E-9) :
|
||||
CValueObject(name, symbol, converter, displayDigits, epsilon)
|
||||
{}
|
||||
|
||||
CPressureUnit(const QString &name, const QString &symbol, std::nullptr_t) :
|
||||
CValueObject(name, symbol, nullptr)
|
||||
{}
|
||||
|
||||
typedef Centi<One> PascalsToHectopascals;
|
||||
struct PsiToHectopascals { static double factor() { return 68.948; } };
|
||||
struct InchesToHectopascals { static double factor() { return 33.86389; } };
|
||||
struct MillimetersToHectopascals { static double factor() { return 860.142806; } };
|
||||
|
||||
public:
|
||||
//! Default constructor, required for Qt Metasystem
|
||||
CPressureUnit() : CValueObject(defaultUnit()) {}
|
||||
|
||||
//! Default unit
|
||||
static const CPressureUnit &defaultUnit() { return hPa(); }
|
||||
|
||||
//! Null unit
|
||||
static const CPressureUnit &nullUnit()
|
||||
{
|
||||
static CPressureUnit nu("null", "null", nullptr);
|
||||
return nu;
|
||||
}
|
||||
|
||||
//! Pascal
|
||||
static const CPressureUnit &Pa()
|
||||
{
|
||||
static CPressureUnit Pa(QT_TRANSLATE_NOOP("CMeasurementUnit", "pascal"), "Pa", LinearConverter<PascalsToHectopascals>());
|
||||
return Pa;
|
||||
}
|
||||
|
||||
//! Hectopascal
|
||||
static const CPressureUnit &hPa()
|
||||
{
|
||||
static CPressureUnit hPa(QT_TRANSLATE_NOOP("CMeasurementUnit", "hectopascal"), "hPa", IdentityConverter());
|
||||
return hPa;
|
||||
}
|
||||
|
||||
//! Pounds per square inch
|
||||
static const CPressureUnit &psi()
|
||||
{
|
||||
static CPressureUnit psi(QT_TRANSLATE_NOOP("CMeasurementUnit", "pound per square inch"), "psi", LinearConverter<PsiToHectopascals>(), 2);
|
||||
return psi;
|
||||
}
|
||||
|
||||
//! Bar
|
||||
static const CPressureUnit &bar()
|
||||
{
|
||||
static CPressureUnit bar(QT_TRANSLATE_NOOP("CMeasurementUnit", "bar"), "bar", LinearConverter<Kilo<One> >(), 1);
|
||||
return bar;
|
||||
}
|
||||
|
||||
//! Millibar, actually the same as hPa
|
||||
static const CPressureUnit &mbar()
|
||||
{
|
||||
static CPressureUnit mbar(QT_TRANSLATE_NOOP("CMeasurementUnit", "millibar"), "mbar", IdentityConverter(), 1);
|
||||
return mbar;
|
||||
}
|
||||
|
||||
//! Inch of mercury at 0°C
|
||||
static const CPressureUnit &inHg()
|
||||
{
|
||||
static CPressureUnit inhg(QT_TRANSLATE_NOOP("CMeasurementUnit", "inch of mercury"), "inHg", LinearConverter<InchesToHectopascals>());
|
||||
return inhg;
|
||||
}
|
||||
|
||||
//! Millimeter of mercury
|
||||
static const CPressureUnit &mmHg()
|
||||
{
|
||||
static CPressureUnit mmhg(QT_TRANSLATE_NOOP("CMeasurementUnit", "millimeter of mercury"), "mmHg", LinearConverter<MillimetersToHectopascals>());
|
||||
return mmhg;
|
||||
}
|
||||
|
||||
//! All units
|
||||
static const QList<CPressureUnit> &allUnits()
|
||||
{
|
||||
static QList<CPressureUnit> u;
|
||||
if (u.isEmpty())
|
||||
{
|
||||
u.append(CPressureUnit::nullUnit());
|
||||
u.append(CPressureUnit::bar());
|
||||
u.append(CPressureUnit::hPa());
|
||||
u.append(CPressureUnit::inHg());
|
||||
u.append(CPressureUnit::mmHg());
|
||||
u.append(CPressureUnit::mbar());
|
||||
u.append(CPressureUnit::psi());
|
||||
}
|
||||
return u;
|
||||
}
|
||||
|
||||
protected:
|
||||
//! \copydoc CValueObject::unmarshallFromDbus
|
||||
virtual void unmarshallFromDbus(const QDBusArgument &argument) override
|
||||
{
|
||||
QString unitName;
|
||||
argument >> unitName;
|
||||
(*this) = CMeasurementUnit::unitFromSymbol<CPressureUnit>(unitName);
|
||||
}
|
||||
};
|
||||
|
||||
//! Specialized class for temperatur units (kelvin, centidegree).
|
||||
class CTemperatureUnit : public CValueObject<CTemperatureUnit, CMeasurementUnit>
|
||||
{
|
||||
private:
|
||||
template <class Converter>
|
||||
CTemperatureUnit(const QString &name, const QString &symbol, const Converter &converter, int displayDigits = 2, double epsilon = 1E-9) :
|
||||
CValueObject(name, symbol, converter, displayDigits, epsilon)
|
||||
{}
|
||||
|
||||
CTemperatureUnit(const QString &name, const QString &symbol, std::nullptr_t) :
|
||||
CValueObject(name, symbol, nullptr)
|
||||
{}
|
||||
|
||||
struct KelvinToCentigrade
|
||||
{
|
||||
static double factor() { return 1.0; }
|
||||
static double offset() { return 273.15; }
|
||||
};
|
||||
struct FahrenheitToCentigrade
|
||||
{
|
||||
static double factor() { return 5.0 / 9.0; }
|
||||
static double offset() { return 32.0; }
|
||||
};
|
||||
|
||||
public:
|
||||
//! Default constructor, required for Qt Metasystem
|
||||
CTemperatureUnit() : CValueObject(defaultUnit()) {}
|
||||
|
||||
//! Default unit
|
||||
static const CTemperatureUnit &defaultUnit() { return C(); }
|
||||
|
||||
//! Null unit
|
||||
static const CTemperatureUnit &nullUnit()
|
||||
{
|
||||
static CTemperatureUnit nu("null", "null", nullptr);
|
||||
return nu;
|
||||
}
|
||||
|
||||
//! Kelvin
|
||||
static const CTemperatureUnit &K()
|
||||
{
|
||||
static CTemperatureUnit K(QT_TRANSLATE_NOOP("CMeasurementUnit", "Kelvin"), "K", AffineConverter<KelvinToCentigrade>());
|
||||
return K;
|
||||
}
|
||||
|
||||
//! Centigrade C
|
||||
static const CTemperatureUnit &C()
|
||||
{
|
||||
static CTemperatureUnit C(QT_TRANSLATE_NOOP("CMeasurementUnit", "centigrade"), QT_TRANSLATE_NOOP("CMeasurementUnit", "C"), IdentityConverter());
|
||||
return C;
|
||||
}
|
||||
|
||||
//! Fahrenheit F
|
||||
static const CTemperatureUnit &F()
|
||||
{
|
||||
static CTemperatureUnit F(QT_TRANSLATE_NOOP("CMeasurementUnit", "Fahrenheit"), QT_TRANSLATE_NOOP("CMeasurementUnit", "F"), AffineConverter<FahrenheitToCentigrade>());
|
||||
return F;
|
||||
}
|
||||
|
||||
//! All units
|
||||
static const QList<CTemperatureUnit> &allUnits()
|
||||
{
|
||||
static QList<CTemperatureUnit> u;
|
||||
if (u.isEmpty())
|
||||
{
|
||||
u.append(CTemperatureUnit::nullUnit());
|
||||
u.append(CTemperatureUnit::C());
|
||||
u.append(CTemperatureUnit::F());
|
||||
u.append(CTemperatureUnit::K());
|
||||
}
|
||||
return u;
|
||||
}
|
||||
|
||||
protected:
|
||||
//! \copydoc CValueObject::unmarshallFromDbus
|
||||
virtual void unmarshallFromDbus(const QDBusArgument &argument) override
|
||||
{
|
||||
QString unitName;
|
||||
argument >> unitName;
|
||||
(*this) = CMeasurementUnit::unitFromSymbol<CTemperatureUnit>(unitName);
|
||||
}
|
||||
};
|
||||
|
||||
//! Specialized class for speed units (m/s, ft/s, NM/h).
|
||||
class CSpeedUnit : public CValueObject<CSpeedUnit, CMeasurementUnit>
|
||||
{
|
||||
private:
|
||||
template <class Converter>
|
||||
CSpeedUnit(const QString &name, const QString &symbol, const Converter &converter, int displayDigits = 2, double epsilon = 1E-9) :
|
||||
CValueObject(name, symbol, converter, displayDigits, epsilon)
|
||||
{}
|
||||
|
||||
CSpeedUnit(const QString &name, const QString &symbol, std::nullptr_t) :
|
||||
CValueObject(name, symbol, nullptr)
|
||||
{}
|
||||
|
||||
struct KnotsToMps { static double factor() { return 1852.0 / 3600.0; } };
|
||||
struct KphToMps { static double factor() { return 1.0 / 3.6; } };
|
||||
struct FtPerSecToMps { static double factor() { return 0.3048 ; } };
|
||||
struct FtPerMinToMps { static double factor() { return 0.3048 / 60.0; } };
|
||||
|
||||
public:
|
||||
|
||||
//! Default constructor, required for Qt Metasystem
|
||||
CSpeedUnit() : CValueObject(defaultUnit()) {}
|
||||
|
||||
//! Default unit
|
||||
static const CSpeedUnit &defaultUnit() { return m_s(); }
|
||||
|
||||
//! Null unit
|
||||
static const CSpeedUnit &nullUnit()
|
||||
{
|
||||
static CSpeedUnit nu("null", "null", nullptr);
|
||||
return nu;
|
||||
}
|
||||
|
||||
//! Meter/second m/s
|
||||
static const CSpeedUnit &m_s()
|
||||
{
|
||||
static CSpeedUnit ms(QT_TRANSLATE_NOOP("CMeasurementUnit", "meter per second"), "m/s", IdentityConverter());
|
||||
return ms;
|
||||
}
|
||||
|
||||
//! Knots
|
||||
static const CSpeedUnit &kts()
|
||||
{
|
||||
static CSpeedUnit kts(QT_TRANSLATE_NOOP("CMeasurementUnit", "knot"), "kts", LinearConverter<KnotsToMps>(), 1);
|
||||
return kts;
|
||||
}
|
||||
|
||||
//! Nautical miles per hour NM/h (same as kts)
|
||||
static const CSpeedUnit &NM_h()
|
||||
{
|
||||
static CSpeedUnit NMh(QT_TRANSLATE_NOOP("CMeasurementUnit", "nautical mile per hour"), "NM/h", LinearConverter<KnotsToMps>(), 1);
|
||||
return NMh;
|
||||
}
|
||||
|
||||
//! Feet/second ft/s
|
||||
static const CSpeedUnit &ft_s()
|
||||
{
|
||||
static CSpeedUnit fts(QT_TRANSLATE_NOOP("CMeasurementUnit", "foot per second"), "ft/s", LinearConverter<FtPerSecToMps>(), 0);
|
||||
return fts;
|
||||
}
|
||||
|
||||
//! Feet/min ft/min
|
||||
static const CSpeedUnit &ft_min()
|
||||
{
|
||||
static CSpeedUnit ftmin(QT_TRANSLATE_NOOP("CMeasurementUnit", "foot per minute"), "ft/min", LinearConverter<FtPerMinToMps>(), 0);
|
||||
return ftmin;
|
||||
}
|
||||
|
||||
//! Kilometer/hour km/h
|
||||
static const CSpeedUnit &km_h()
|
||||
{
|
||||
static CSpeedUnit kmh(QT_TRANSLATE_NOOP("CMeasurementUnit", "kilometer per hour"), "km/h", LinearConverter<KphToMps>(), 1);
|
||||
return kmh;
|
||||
}
|
||||
|
||||
//! All units
|
||||
static const QList<CSpeedUnit> &allUnits()
|
||||
{
|
||||
static QList<CSpeedUnit> u;
|
||||
if (u.isEmpty())
|
||||
{
|
||||
u.append(CSpeedUnit::nullUnit());
|
||||
u.append(CSpeedUnit::ft_min());
|
||||
u.append(CSpeedUnit::ft_s());
|
||||
u.append(CSpeedUnit::km_h());
|
||||
u.append(CSpeedUnit::kts());
|
||||
u.append(CSpeedUnit::m_s());
|
||||
u.append(CSpeedUnit::NM_h());
|
||||
}
|
||||
return u;
|
||||
}
|
||||
|
||||
protected:
|
||||
//! \copydoc CValueObject::unmarshallFromDbus
|
||||
virtual void unmarshallFromDbus(const QDBusArgument &argument) override
|
||||
{
|
||||
QString unitName;
|
||||
argument >> unitName;
|
||||
(*this) = CMeasurementUnit::unitFromSymbol<CSpeedUnit>(unitName);
|
||||
}
|
||||
};
|
||||
|
||||
//! Specialized class for time units (ms, hour, min).
|
||||
class CTimeUnit : public CValueObject<CTimeUnit, CMeasurementUnit>
|
||||
{
|
||||
private:
|
||||
template <class Converter>
|
||||
CTimeUnit(const QString &name, const QString &symbol, const Converter &converter, int displayDigits = 2, double epsilon = 1E-9) :
|
||||
CValueObject(name, symbol, converter, displayDigits, epsilon)
|
||||
{}
|
||||
|
||||
CTimeUnit(const QString &name, const QString &symbol, std::nullptr_t) :
|
||||
CValueObject(name, symbol, nullptr)
|
||||
{}
|
||||
|
||||
typedef One SecondsToSeconds;
|
||||
struct DaysToSeconds { static double factor() { return 60.0 * 60.0 * 24.0; } };
|
||||
struct HoursToSeconds { static double factor() { return 60.0 * 60.0; } };
|
||||
struct MinutesToSeconds { static double factor() { return 60.0; } };
|
||||
|
||||
public:
|
||||
|
||||
//! Default constructor, required for Qt Metasystem
|
||||
CTimeUnit() : CValueObject(defaultUnit()) {}
|
||||
|
||||
//! Default unit
|
||||
static const CTimeUnit &defaultUnit() { return s(); }
|
||||
|
||||
//! Null unit
|
||||
static const CTimeUnit &nullUnit()
|
||||
{
|
||||
static CTimeUnit nu("null", "null", nullptr);
|
||||
return nu;
|
||||
}
|
||||
|
||||
//! \copydoc CMeasurementUnit::makeRoundedQStringWithUnit
|
||||
virtual QString makeRoundedQStringWithUnit(double value, int digits = -1, bool i18n = false) const override;
|
||||
|
||||
//! Second s
|
||||
static const CTimeUnit &s()
|
||||
{
|
||||
static CTimeUnit s(QT_TRANSLATE_NOOP("CMeasurementUnit", "second"), "s", IdentityConverter(), 1);
|
||||
return s;
|
||||
}
|
||||
|
||||
//! Millisecond ms
|
||||
static const CTimeUnit &ms()
|
||||
{
|
||||
static CTimeUnit ms(QT_TRANSLATE_NOOP("CMeasurementUnit", "millisecond"), "ms", LinearConverter<Milli<SecondsToSeconds> >(), 0);
|
||||
return ms;
|
||||
}
|
||||
|
||||
//! Hour
|
||||
static const CTimeUnit &h()
|
||||
{
|
||||
static CTimeUnit h(QT_TRANSLATE_NOOP("CMeasurementUnit", "hour"), "h", LinearConverter<HoursToSeconds>(), 1);
|
||||
return h;
|
||||
}
|
||||
|
||||
//! Minute
|
||||
static const CTimeUnit &min()
|
||||
{
|
||||
static CTimeUnit minute(QT_TRANSLATE_NOOP("CMeasurementUnit", "minute"), "min", LinearConverter<MinutesToSeconds>(), 2);
|
||||
return minute;
|
||||
}
|
||||
|
||||
//! Day
|
||||
static const CTimeUnit &d()
|
||||
{
|
||||
static CTimeUnit day(QT_TRANSLATE_NOOP("CMeasurementUnit", "day"), "d", LinearConverter<DaysToSeconds>(), 1);
|
||||
return day;
|
||||
}
|
||||
|
||||
//! Hours, minutes, seconds
|
||||
static const CTimeUnit &hms()
|
||||
{
|
||||
static CTimeUnit hms(QT_TRANSLATE_NOOP("CMeasurementUnit", "hour, minute, second"), "hms", SubdivisionConverter2<HoursToSeconds, InEachHundred<60> >(), 4);
|
||||
return hms;
|
||||
(void)QT_TRANSLATE_NOOP("CMeasurementUnit", "%L1h%L2m%L3s");
|
||||
(void)QT_TRANSLATE_NOOP("CMeasurementUnit", "%-L1h%L2m%L3s");
|
||||
}
|
||||
|
||||
//! Hours, minutes
|
||||
static const CTimeUnit &hrmin()
|
||||
{
|
||||
static CTimeUnit hrmin(QT_TRANSLATE_NOOP("CMeasurementUnit", "hour, minute"), "hm", SubdivisionConverter<HoursToSeconds, InEachHundred<60> >(), 3);
|
||||
return hrmin;
|
||||
(void)QT_TRANSLATE_NOOP("CMeasurementUnit", "%L1h%L2m");
|
||||
(void)QT_TRANSLATE_NOOP("CMeasurementUnit", "-%L1h%L2m");
|
||||
}
|
||||
|
||||
//! Minutes, seconds
|
||||
static const CTimeUnit &minsec()
|
||||
{
|
||||
static CTimeUnit minsec(QT_TRANSLATE_NOOP("CMeasurementUnit", "minute, second"), "minsec", SubdivisionConverter<MinutesToSeconds, InEachHundred<60> >(), 2);
|
||||
return minsec;
|
||||
(void)QT_TRANSLATE_NOOP("CMeasurementUnit", "%L1m%L2s");
|
||||
(void)QT_TRANSLATE_NOOP("CMeasurementUnit", "-%L1m%L2s");
|
||||
}
|
||||
|
||||
//! All units
|
||||
static const QList<CTimeUnit> &allUnits()
|
||||
{
|
||||
static QList<CTimeUnit> u;
|
||||
if (u.isEmpty())
|
||||
{
|
||||
u.append(CTimeUnit::nullUnit());
|
||||
u.append(CTimeUnit::d());
|
||||
u.append(CTimeUnit::h());
|
||||
u.append(CTimeUnit::hms());
|
||||
u.append(CTimeUnit::hrmin());
|
||||
u.append(CTimeUnit::min());
|
||||
u.append(CTimeUnit::ms());
|
||||
u.append(CTimeUnit::s());
|
||||
}
|
||||
return u;
|
||||
}
|
||||
|
||||
protected:
|
||||
//! \copydoc CValueObject::unmarshallFromDbus
|
||||
virtual void unmarshallFromDbus(const QDBusArgument &argument) override
|
||||
{
|
||||
QString unitName;
|
||||
argument >> unitName;
|
||||
(*this) = CMeasurementUnit::unitFromSymbol<CTimeUnit>(unitName);
|
||||
}
|
||||
};
|
||||
|
||||
//! Specialized class for acceleration units (m/s2, ft/s2).
|
||||
class CAccelerationUnit : public CValueObject<CAccelerationUnit, CMeasurementUnit>
|
||||
{
|
||||
private:
|
||||
template <class Converter>
|
||||
CAccelerationUnit(const QString &name, const QString &symbol, const Converter &converter, int displayDigits = 2, double epsilon = 1E-9) :
|
||||
CValueObject(name, symbol, converter, displayDigits, epsilon)
|
||||
{}
|
||||
|
||||
CAccelerationUnit(const QString &name, const QString &symbol, std::nullptr_t) :
|
||||
CValueObject(name, symbol, nullptr)
|
||||
{}
|
||||
|
||||
struct FeetToMeters { static double factor() { return 0.3048; } };
|
||||
|
||||
public:
|
||||
//! Default constructor, required for Qt Metasystem
|
||||
CAccelerationUnit() : CValueObject(defaultUnit()) {}
|
||||
|
||||
//! Default unit
|
||||
static const CAccelerationUnit &defaultUnit() { return m_s2(); }
|
||||
|
||||
//! Null unit
|
||||
static const CAccelerationUnit &nullUnit()
|
||||
{
|
||||
static CAccelerationUnit nu("null", "null", nullptr);
|
||||
return nu;
|
||||
}
|
||||
|
||||
//! Meter/second^2 (m/s^2)
|
||||
static const CAccelerationUnit &m_s2()
|
||||
{
|
||||
static CAccelerationUnit ms2(QT_TRANSLATE_NOOP("CMeasurementUnit", "meter per second per second"), QT_TRANSLATE_NOOP("CMeasurementUnit", "m/s^2"), IdentityConverter(), 1);
|
||||
return ms2;
|
||||
}
|
||||
|
||||
//! Feet/second^2
|
||||
static const CAccelerationUnit &ft_s2()
|
||||
{
|
||||
static CAccelerationUnit fts2(QT_TRANSLATE_NOOP("CMeasurementUnit", "foot per second per second"), QT_TRANSLATE_NOOP("CMeasurementUnit", "ft/s^2"), LinearConverter<FeetToMeters>(), 0);
|
||||
return fts2;
|
||||
}
|
||||
|
||||
//! All units
|
||||
static const QList<CAccelerationUnit> &allUnits()
|
||||
{
|
||||
static QList<CAccelerationUnit> u;
|
||||
if (u.isEmpty())
|
||||
{
|
||||
u.append(CAccelerationUnit::nullUnit());
|
||||
u.append(CAccelerationUnit::ft_s2());
|
||||
u.append(CAccelerationUnit::m_s2());
|
||||
}
|
||||
return u;
|
||||
}
|
||||
|
||||
protected:
|
||||
//! \copydoc CValueObject::unmarshallFromDbus
|
||||
virtual void unmarshallFromDbus(const QDBusArgument &argument) override
|
||||
{
|
||||
QString unitName;
|
||||
argument >> unitName;
|
||||
(*this) = CMeasurementUnit::unitFromSymbol<CAccelerationUnit>(unitName);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
Q_DECLARE_METATYPE(BlackMisc::PhysicalQuantities::CLengthUnit)
|
||||
Q_DECLARE_METATYPE(BlackMisc::PhysicalQuantities::CAngleUnit)
|
||||
Q_DECLARE_METATYPE(BlackMisc::PhysicalQuantities::CFrequencyUnit)
|
||||
Q_DECLARE_METATYPE(BlackMisc::PhysicalQuantities::CMassUnit)
|
||||
Q_DECLARE_METATYPE(BlackMisc::PhysicalQuantities::CPressureUnit)
|
||||
Q_DECLARE_METATYPE(BlackMisc::PhysicalQuantities::CTemperatureUnit)
|
||||
Q_DECLARE_METATYPE(BlackMisc::PhysicalQuantities::CSpeedUnit)
|
||||
Q_DECLARE_METATYPE(BlackMisc::PhysicalQuantities::CTimeUnit)
|
||||
Q_DECLARE_METATYPE(BlackMisc::PhysicalQuantities::CAccelerationUnit)
|
||||
|
||||
#pragma pop_macro("min")
|
||||
|
||||
#endif // guard
|
||||
Reference in New Issue
Block a user