From f9246cb5f953f58d834ccffc542f3a6f6bac9fb3 Mon Sep 17 00:00:00 2001 From: Klaus Basan Date: Mon, 17 Mar 2014 19:59:34 +0100 Subject: [PATCH] refs #189 , PQ string class which allows parsing strings like 100m/s. pqbase contains template method to determine a valid unit. --- src/blackmisc/blackmiscfreefunctions.cpp | 1 + src/blackmisc/pqallquantities.h | 1 + src/blackmisc/pqbase.h | 10 +- src/blackmisc/pqstring.cpp | 155 +++++++++++++++++++++++ src/blackmisc/pqstring.h | 103 +++++++++++++++ 5 files changed, 266 insertions(+), 4 deletions(-) create mode 100644 src/blackmisc/pqstring.cpp create mode 100644 src/blackmisc/pqstring.h diff --git a/src/blackmisc/blackmiscfreefunctions.cpp b/src/blackmisc/blackmiscfreefunctions.cpp index 0905e08d3..902f31ae9 100644 --- a/src/blackmisc/blackmiscfreefunctions.cpp +++ b/src/blackmisc/blackmiscfreefunctions.cpp @@ -30,6 +30,7 @@ void BlackMisc::PhysicalQuantities::registerMetadata() CSpeed::registerMetadata(); CTemperature::registerMetadata(); CTime::registerMetadata(); + CPqString::registerMetadata(); } /* diff --git a/src/blackmisc/pqallquantities.h b/src/blackmisc/pqallquantities.h index 1a402e504..bfd8af120 100644 --- a/src/blackmisc/pqallquantities.h +++ b/src/blackmisc/pqallquantities.h @@ -21,5 +21,6 @@ #include "blackmisc/pqtime.h" #include "blackmisc/pqacceleration.h" #include "blackmisc/pqunits.h" +#include "blackmisc/pqstring.h" #endif // guard diff --git a/src/blackmisc/pqbase.h b/src/blackmisc/pqbase.h index a45720bae..654527411 100644 --- a/src/blackmisc/pqbase.h +++ b/src/blackmisc/pqbase.h @@ -386,16 +386,18 @@ namespace BlackMisc } /*! - * \brief Valid unit symbol - * \param symbol must be a valid unit symbol (without i18n) or empty string (empty means default unit) + * \brief Valid unit symbol? + * \param symbol to be tested + * \param caseSensitivity check case sensitiv? */ - template static bool isValidUnitSymbol(const QString &symbol) + template static bool isValidUnitSymbol(const QString &symbol, Qt::CaseSensitivity caseSensitivity = Qt::CaseSensitive) { if (symbol.isEmpty()) return false; const QList &units = U::allUnits(); for (int i = 0; i < units.size(); ++i) { - if (units.at(i).getSymbol() == symbol) return true; + 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; } diff --git a/src/blackmisc/pqstring.cpp b/src/blackmisc/pqstring.cpp new file mode 100644 index 000000000..3ba1e84a6 --- /dev/null +++ b/src/blackmisc/pqstring.cpp @@ -0,0 +1,155 @@ +#include "pqstring.h" +#include "tuple.h" +#include "pqallquantities.h" + +namespace BlackMisc +{ + namespace PhysicalQuantities + { + /* + * Convert to string + */ + QString CPqString::convertToQString(bool /** i18n **/) const + { + return this->m_string; + } + + /* + * is a + */ + bool CPqString::isA(int metaTypeId) const + { + if (metaTypeId == qMetaTypeId()) { return true; } + return this->CValueObject::isA(metaTypeId); + } + + /* + * Compare + */ + int CPqString::compareImpl(const CValueObject &otherBase) const + { + const auto &other = static_cast(otherBase); + return compare(TupleConverter::toTuple(*this), TupleConverter::toTuple(other)); + } + + /* + * Marshall to DBus + */ + void CPqString::marshallToDbus(QDBusArgument &argument) const + { + argument << TupleConverter::toTuple(*this); + } + + /* + * Unmarshall from DBus + */ + void CPqString::unmarshallFromDbus(const QDBusArgument &argument) + { + argument >> TupleConverter::toTuple(*this); + } + + /* + * Equal? + */ + bool CPqString::operator ==(const CPqString &other) const + { + if (this == &other) return true; + return TupleConverter::toTuple(*this) == TupleConverter::toTuple(other); + } + + /* + * Unequal? + */ + bool CPqString::operator !=(const CPqString &other) const + { + return !((*this) == other); + } + + /* + * Hash + */ + uint CPqString::getValueHash() const + { + return qHash(TupleConverter::toTuple(*this)); + } + + /* + * Register metadata + */ + void CPqString::registerMetadata() + { + qRegisterMetaType(); + qDBusRegisterMetaType(); + } + + QVariant CPqString::parse(const QString &value) + { + QVariant v; + if (value.isEmpty()) return v; + QRegExp rx("^([-+]?[0-9]*\\.?[0-9]+)\\s*(\\D*)$"); + if (rx.indexIn(value) < 0) return v; + QString number = rx.cap(1); + QString unit = rx.cap(2); + if (unit.isEmpty() || number.isEmpty()) return v; + bool success; + double numberD = number.toDouble(&success); + if (!success) return v; + + if (CMeasurementUnit::isValidUnitSymbol(unit)) + { + CAcceleration pq(numberD, CMeasurementUnit::unitFromSymbol(unit, false)); + return pq.toQVariant(); + } + + if (CMeasurementUnit::isValidUnitSymbol(unit)) + { + CAngle pq(numberD, CMeasurementUnit::unitFromSymbol(unit, false)); + return pq.toQVariant(); + } + + if (CMeasurementUnit::isValidUnitSymbol(unit)) + { + CFrequency pq(numberD, CMeasurementUnit::unitFromSymbol(unit, false)); + return pq.toQVariant(); + } + + if (CMeasurementUnit::isValidUnitSymbol(unit)) + { + CLength pq(numberD, CMeasurementUnit::unitFromSymbol(unit, false)); + return pq.toQVariant(); + } + + if (CMeasurementUnit::isValidUnitSymbol(unit)) + { + CMass pq(numberD, CMeasurementUnit::unitFromSymbol(unit, false)); + return pq.toQVariant(); + } + + if (CMeasurementUnit::isValidUnitSymbol(unit)) + { + CPressure pq(numberD, CMeasurementUnit::unitFromSymbol(unit, false)); + return pq.toQVariant(); + } + + if (CMeasurementUnit::isValidUnitSymbol(unit)) + { + CSpeed pq(numberD, CMeasurementUnit::unitFromSymbol(unit, false)); + return pq.toQVariant(); + } + + if (CMeasurementUnit::isValidUnitSymbol(unit)) + { + CTime pq(numberD, CMeasurementUnit::unitFromSymbol(unit, false)); + return pq.toQVariant(); + } + + if (CMeasurementUnit::isValidUnitSymbol(unit)) + { + CTemperature pq(numberD, CMeasurementUnit::unitFromSymbol(unit, false)); + return pq.toQVariant(); + } + return v; + } + + } // namespace +} // namespace diff --git a/src/blackmisc/pqstring.h b/src/blackmisc/pqstring.h new file mode 100644 index 000000000..63c47de2f --- /dev/null +++ b/src/blackmisc/pqstring.h @@ -0,0 +1,103 @@ +/* Copyright (C) 2013 VATSIM Community / contributors + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef BLACKMISC_PQSTRING_H +#define BLACKMISC_PQSTRING_H + +#include "blackmisc/valueobject.h" +#include + +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 BlackMisc::CValueObject + { + public: + + private: + BLACK_ENABLE_TUPLE_CONVERSION(CPqString) + QString m_string; + + protected: + //! \copydoc CValueObject::convertToQString + virtual QString convertToQString(bool i18n = false) const override; + + //! \copydoc CValueObject::marshallFromDbus() + virtual void marshallToDbus(QDBusArgument &argument) const override; + + //! \copydoc CValueObject::unmarshallFromDbus() + virtual void unmarshallFromDbus(const QDBusArgument &argument) override; + + //! \copydoc CValueObject::compareImpl + virtual int compareImpl(const CValueObject &other) const override; + + //! \copydoc CValueObject::isA + virtual bool isA(int metaTypeId) const override; + + public: + //! \brief Default constructor + CPqString() {} + + /*! + * \brief Constructor + * \param value such as 10km/h + */ + CPqString(const QString &value) : m_string(value) {} + + //! \copydoc CValueObject::toQVariant + virtual QVariant toQVariant() const override + { + return QVariant::fromValue(*this); + } + + //! \copydoc CValueObject::getMetaTypeId + int getMetaTypeId() const + { + return qMetaTypeId(); + } + + //! \copydoc CValueObject::getValueHash + virtual uint getValueHash() const override; + + //! \brief Equal operator == + bool operator ==(const CPqString &other) const; + + //! \brief Unequal operator != + bool operator !=(const CPqString &other) const; + + //! \brief Register metadata + static void registerMetadata(); + + //! \brief parse a string value like "100m", "10.3Mhz" + static QVariant parse(const QString &value); + + //! \brief parse into concrete type + template static const PQ parse(const QString &symbol) + { + PQ invalid; + if (symbol.isEmpty()) return invalid; + QVariant qv = CPqString::parse(symbol); + if (!qv.isNull() && qv.canConvert()) + { + return qv.value(); + } + return invalid; + } + }; + + } // namespace +} // namespace + +BLACK_DECLARE_TUPLE_CONVERSION(BlackMisc::PhysicalQuantities::CPqString, (o.m_string)) +Q_DECLARE_METATYPE(BlackMisc::PhysicalQuantities::CPqString) + +#endif // guard