/* 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/pqallquantities.h" #include "blackmiscfreefunctions.h" #include namespace BlackMisc { namespace PhysicalQuantities { /* * Constructor by double */ template CPhysicalQuantity::CPhysicalQuantity(double value, const MU &unit) : m_value(unit.isNull() ? 0.0 : value), m_unit(unit) { // void } /* * Equal operator == */ template bool CPhysicalQuantity::operator ==(const CPhysicalQuantity &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(); } /* * Not equal */ template bool CPhysicalQuantity::operator !=(const CPhysicalQuantity &other) const { return !((*this) == other); } /* * Plus operator */ template CPhysicalQuantity &CPhysicalQuantity::operator +=(const CPhysicalQuantity &other) { this->m_value += other.value(this->m_unit); return *this; } /* * Plus operator */ template PQ CPhysicalQuantity::operator +(const PQ &other) const { PQ copy(other); copy += *this; return copy; } /* * Explicit plus */ template void CPhysicalQuantity::addValueSameUnit(double value) { this->m_value += value; } /* * Explicit minus */ template void CPhysicalQuantity::substractValueSameUnit(double value) { this->m_value -= value; } /* * Minus operator */ template CPhysicalQuantity &CPhysicalQuantity::operator -=(const CPhysicalQuantity &other) { this->m_value -= other.value(this->m_unit); return *this; } /* * Minus operator */ template PQ CPhysicalQuantity::operator -(const PQ &other) const { PQ copy = *derived(); copy -= other; return copy; } /* * Marshall */ template void CPhysicalQuantity::marshallToDbus(QDBusArgument &argument) const { argument << this->value(UnitClass::defaultUnit()); argument << this->m_value; argument << this->m_unit; } /* * Unmarshall */ template void CPhysicalQuantity::unmarshallFromDbus(const QDBusArgument &argument) { double ignore; argument >> ignore; argument >> this->m_value; argument >> this->m_unit; } /* * Multiply operator */ template CPhysicalQuantity &CPhysicalQuantity::operator *=(double factor) { this->m_value *= factor; return *this; } /* * Multiply operator */ template PQ CPhysicalQuantity::operator *(double factor) const { PQ copy = *derived(); copy *= factor; return copy; } /* * Divide operator /= */ template CPhysicalQuantity &CPhysicalQuantity::operator /=(double divisor) { this->m_value /= divisor; return *this; } /* * Divide operator / */ template PQ CPhysicalQuantity::operator /(double divisor) const { PQ copy = *derived(); copy /= divisor; return copy; } /* * Less operator < */ template bool CPhysicalQuantity::operator <(const CPhysicalQuantity &other) const { if (*this == other) return false; if (this->isNull() || other.isNull()) return false; return (this->m_value < other.value(this->m_unit)); } /* * Greater than */ template bool CPhysicalQuantity::operator >(const CPhysicalQuantity &other) const { return other < *this; } /* * Greater / Equal */ template bool CPhysicalQuantity::operator >=(const CPhysicalQuantity &other) const { if (*this == other) return true; return *this > other; } /* * Less equal */ template bool CPhysicalQuantity::operator <=(const CPhysicalQuantity &other) const { if (*this == other) return true; return *this < other; } /* * Switch to another unit */ template PQ &CPhysicalQuantity::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(); } /* * Init by double */ template void CPhysicalQuantity::setValueSameUnit(double baseValue) { this->m_value = baseValue; } /* * Value rounded in unit */ template QString CPhysicalQuantity::valueRoundedWithUnit(const MU &unit, int digits, bool i18n) const { return unit.makeRoundedQStringWithUnit(this->value(unit), digits, i18n); } /* * Value rounded in unit */ template double CPhysicalQuantity::valueRounded(const MU &unit, int digits) const { return unit.roundValue(this->value(unit), digits); } /* * Value in unit */ template double CPhysicalQuantity::value(const MU &unit) const { return unit.convertFrom(this->m_value, this->m_unit); } /* * Convert to string */ template QString CPhysicalQuantity::convertToQString(bool i18n) const { if (this->isNull()) { return i18n ? QCoreApplication::translate("CPhysicalQuantity", "undefined") : "undefined"; } return this->valueRoundedWithUnit(this->getUnit(), -1, i18n); } /* * Hash */ template uint CPhysicalQuantity::getValueHash() const { QList 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"); } /* * JSON Object */ template QJsonObject CPhysicalQuantity::toJson() const { QJsonObject json; json.insert("value", QJsonValue(this->m_value)); json.insert("unit", QJsonValue(this->m_unit.getSymbol())); return json; } /* * JSON Object */ template void CPhysicalQuantity::convertFromJson(const QJsonObject &json) { const QString unitSymbol = json.value("unit").toString(); this->setUnitBySymbol(unitSymbol); this->m_value = json.value("value").toDouble(); } /* * Property */ template CVariant CPhysicalQuantity::propertyByIndex(const CPropertyIndex &index) const { if (index.isMyself()) { return this->toCVariant(); } ColumnIndex i = index.frontCasted(); 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::propertyByIndex(index); } } /* * Property */ template void CPhysicalQuantity::setPropertyByIndex(const CVariant &variant, const CPropertyIndex &index) { if (index.isMyself()) { this->convertFromCVariant(variant); return; } ColumnIndex i = index.frontCasted(); 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::setPropertyByIndex(variant, index); break; } } /* * Compare */ template int CPhysicalQuantity::compareImpl(const CValueObject &otherBase) const { const auto &other = static_cast(otherBase); if (this->isNull() > other.isNull()) { return -1; } if (this->isNull() < other.isNull()) { return 1; } if (*this < other) { return -1; } else if (*this > other) { 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; template class CPhysicalQuantity; template class CPhysicalQuantity; template class CPhysicalQuantity; template class CPhysicalQuantity; template class CPhysicalQuantity; template class CPhysicalQuantity; template class CPhysicalQuantity; template class CPhysicalQuantity; } // namespace } // namespace