refs #84 removed the CValueObject::compare method and added a friend function BlackMisc::compare to replace it.

The new compare is implemented using "multimethods" described in the book Advanced C++ Programming Styles and Idioms by James Coplien.

First, the isA method is used to determine which of the values being compared is the most general. (For example, CLength is more general than CAltitude.)
Then the compareImpl method is called on the most general value, with the other value as an argument.
If there is not a direct inheritance relation between the two values (or they are the same class) then the comparison is invalid and a assert is triggered.
This commit is contained in:
Mathew Sutcliffe
2014-01-14 00:45:19 +00:00
parent e40c93fe1b
commit db4c05dd9f
48 changed files with 1015 additions and 119 deletions

View File

@@ -124,15 +124,32 @@ namespace BlackMisc
return BlackMisc::calculateHash(hashs, "CAircraft");
}
/*
* metaTypeId
*/
int CAircraft::getMetaTypeId() const
{
return qMetaTypeId<CAircraft>();
}
/*
* is a
*/
bool CAircraft::isA(int metaTypeId) const
{
if (metaTypeId == qMetaTypeId<CAircraft>()) { return true; }
return this->CValueObject::isA(metaTypeId);
}
/*
* Compare
*/
int CAircraft::compare(const QVariant &qv) const
int CAircraft::compareImpl(const CValueObject &otherBase) const
{
Q_ASSERT(qv.canConvert<CAircraft>());
Q_ASSERT(!qv.isNull() && qv.isValid());
CAircraft aircraft = qv.value<CAircraft>();
return this->getCallsign().compare(aircraft.getCallsign());
const auto &other = static_cast<const CAircraft &>(otherBase);
return this->getCallsign().asString().compare(other.getCallsign().asString(), Qt::CaseInsensitive);
}
/*

View File

@@ -278,11 +278,6 @@ namespace BlackMisc
*/
virtual uint getValueHash() const;
/*!
* \copydoc BlackObject::compare
*/
virtual int compare(const QVariant &qv) const;
/*!
* \brief Register metadata
*/
@@ -337,6 +332,21 @@ namespace BlackMisc
*/
virtual QString convertToQString(bool i18n = false) const;
/*!
* \copydoc CValueObject::getMetaTypeId
*/
virtual int getMetaTypeId() const;
/*!
* \copydoc CValueObject::isA
*/
virtual bool isA(int metaTypeId) const;
/*!
* \copydoc CValueObject::compareImpl
*/
virtual int compareImpl(const CValueObject &other) const;
/*!
* \brief Stream to DBus <<
* \param argument

View File

@@ -1,5 +1,6 @@
#include "avaircrafticao.h"
#include "blackmisc/blackmiscfreefunctions.h"
#include <tuple>
namespace BlackMisc
{
@@ -19,6 +20,39 @@ namespace BlackMisc
return s;
}
/*
* metaTypeId
*/
int CAircraftIcao::getMetaTypeId() const
{
return qMetaTypeId<CAircraftIcao>();
}
/*
* is a
*/
bool CAircraftIcao::isA(int metaTypeId) const
{
if (metaTypeId == qMetaTypeId<CAircraftIcao>()) { return true; }
return this->CValueObject::isA(metaTypeId);
}
/*
* Compare
*/
int CAircraftIcao::compareImpl(const CValueObject &otherBase) const
{
const auto &other = static_cast<const CAircraftIcao &>(otherBase);
const auto lhs = std::tie(this->m_designator, this->m_color, this->m_airline, this->m_livery);
const auto rhs = std::tie(other.m_designator, other.m_color, other.m_airline, other.m_livery);
if (lhs < rhs) { return -1; }
if (lhs > rhs) { return 1; }
return 0;
}
/*
* Marshall to DBus
*/

View File

@@ -214,6 +214,21 @@ namespace BlackMisc
*/
virtual QString convertToQString(bool i18n = false) const;
/*!
* \copydoc CValueObject::getMetaTypeId
*/
virtual int getMetaTypeId() const;
/*!
* \copydoc CValueObject::isA
*/
virtual bool isA(int metaTypeId) const;
/*!
* \copydoc CValueObject::compareImpl
*/
virtual int compareImpl(const CValueObject &other) const;
/*!
* \brief Stream to DBus <<
* \param argument

View File

@@ -23,6 +23,33 @@ namespace BlackMisc
return s;
}
/*
* metaTypeId
*/
int CAircraftSituation::getMetaTypeId() const
{
return qMetaTypeId<CAircraftSituation>();
}
/*
* is a
*/
bool CAircraftSituation::isA(int metaTypeId) const
{
if (metaTypeId == qMetaTypeId<CAircraftSituation>()) { return true; }
return this->CValueObject::isA(metaTypeId);
}
/*
* Compare
*/
int CAircraftSituation::compareImpl(const CValueObject &/*otherBase*/) const
{
qFatal("not implemented");
return 0;
}
/*
* Marshall to DBus
*/

View File

@@ -233,6 +233,21 @@ namespace BlackMisc
*/
virtual QString convertToQString(bool i18n = false) const;
/*!
* \copydoc CValueObject::getMetaTypeId
*/
virtual int getMetaTypeId() const;
/*!
* \copydoc CValueObject::isA
*/
virtual bool isA(int metaTypeId) const;
/*!
* \copydoc CValueObject::compareImpl
*/
virtual int compareImpl(const CValueObject &other) const;
/*!
* \brief Stream to DBus <<
* \param argument

View File

@@ -58,26 +58,36 @@ namespace BlackMisc
return !((*this) == other);
}
/*
* metaTypeId
*/
int CAltitude::getMetaTypeId() const
{
return qMetaTypeId<CAltitude>();
}
/*
* is a
*/
bool CAltitude::isA(int metaTypeId) const
{
if (metaTypeId == qMetaTypeId<CAltitude>()) { return true; }
return this->CLength::isA(metaTypeId);
}
/*
* Compare
*/
int CAltitude::compare(const QVariant &qv) const
int CAltitude::compareImpl(const CValueObject &otherBase) const
{
Q_ASSERT(qv.canConvert<CAltitude>() || qv.canConvert<CLength>());
Q_ASSERT(qv.isValid() && !qv.isNull());
if (qv.canConvert<CAltitude>())
{
CAltitude other = qv.value<CAltitude>();
if (this->isMeanSeaLevel() && other.isAboveGroundLevel()) return 1;
if (this->isAboveGroundLevel() && other.isMeanSeaLevel()) return -1;
return this->compare(other);
}
else if (qv.canConvert<CLength>())
{
return this->compare(qv.value<CLength>());
}
qFatal("Invalid comparison");
return 0; // just for compiler
const auto &other = static_cast<const CAltitude &>(otherBase);
if (this->isMeanSeaLevel() && other.isAboveGroundLevel()) { return 1; }
if (this->isAboveGroundLevel() && other.isMeanSeaLevel()) { return -1; }
if (*this < other) { return -1; }
if (*this > other) { return 1; }
return 0;
}
/*

View File

@@ -39,6 +39,21 @@ namespace BlackMisc
*/
virtual QString convertToQString(bool i18n) const;
/*!
* \copydoc CValueObject::getMetaTypeId
*/
virtual int getMetaTypeId() const;
/*!
* \copydoc CValueObject::isA
*/
virtual bool isA(int metaTypeId) const;
/*!
* \copydoc CValueObject::compareImpl
*/
virtual int compareImpl(const CValueObject &other) const;
/*!
* \brief Stream to DBus <<
* \param argument
@@ -122,17 +137,6 @@ namespace BlackMisc
return m_datum;
}
/*!
* \copydoc BlackObject::compare
*/
virtual int compare(const QVariant &qv) const;
/*!
* \todo this is a hack, to avoid hiding inherited names in CPhysicalQuantity
* (see Effective C++ item 33) CPhysicalQuantity::compare is the real culprit
*/
int compare(const CLength &other) const { return static_cast<const CLength *>(this)->compare(other); }
/*!
* \brief Register metadata
*/

View File

@@ -429,15 +429,32 @@ namespace BlackMisc
}
}
/*
* metaTypeId
*/
int CAtcStation::getMetaTypeId() const
{
return qMetaTypeId<CAtcStation>();
}
/*
* is a
*/
bool CAtcStation::isA(int metaTypeId) const
{
if (metaTypeId == qMetaTypeId<CAtcStation>()) { return true; }
return this->CValueObject::isA(metaTypeId);
}
/*
* Compare
*/
int CAtcStation::compare(const QVariant &qv) const
int CAtcStation::compareImpl(const CValueObject &otherBase) const
{
Q_ASSERT(qv.canConvert<CAtcStation>());
Q_ASSERT(!qv.isNull() && qv.isValid());
CAtcStation atc = qv.value<CAtcStation>();
return this->getCallsign().compare(atc.getCallsign());
const auto &other = static_cast<const CAtcStation &>(otherBase);
return this->getCallsign().asString().compare(other.getCallsign().asString(), Qt::CaseInsensitive);
}
/*

View File

@@ -453,11 +453,6 @@ namespace BlackMisc
*/
static void registerMetadata();
/*!
* \copydoc BlackObject::compare
*/
virtual int compare(const QVariant &qv) const;
protected:
/*!
* \brief Meaningful string representation
@@ -466,6 +461,21 @@ namespace BlackMisc
*/
virtual QString convertToQString(bool i18n = false) const;
/*!
* \copydoc CValueObject::getMetaTypeId
*/
virtual int getMetaTypeId() const;
/*!
* \copydoc CValueObject::isA
*/
virtual bool isA(int metaTypeId) const;
/*!
* \copydoc CValueObject::compareImpl
*/
virtual int compareImpl(const CValueObject &other) const;
/*!
* \brief Stream to DBus <<
* \param argument

View File

@@ -98,21 +98,31 @@ namespace BlackMisc
}
/*
* Compare
* metaTypeId
*/
int CCallsign::compare(const QVariant &qv) const
int CCallsign::getMetaTypeId() const
{
Q_ASSERT(qv.canConvert<CCallsign>());
Q_ASSERT(!qv.isNull() && qv.isValid());
return this->compare(qv.value<CCallsign>());
return qMetaTypeId<CCallsign>();
}
/*
* is a
*/
bool CCallsign::isA(int metaTypeId) const
{
if (metaTypeId == qMetaTypeId<CCallsign>()) { return true; }
return this->CValueObject::isA(metaTypeId);
}
/*
* Compare
*/
int CCallsign::compare(const CCallsign &callsign) const
int CCallsign::compareImpl(const CValueObject &otherBase) const
{
return this->m_callsign.compare(callsign.asString(), Qt::CaseInsensitive);
const auto &other = static_cast<const CCallsign &>(otherBase);
return this->m_callsign.compare(other.asString(), Qt::CaseInsensitive);
}
/*

View File

@@ -121,17 +121,6 @@ namespace BlackMisc
*/
virtual uint getValueHash() const;
/*!
* \copydoc BlackObject::compare
*/
virtual int compare(const QVariant &qv) const;
/*!
* Compare with other callsign
* \return
*/
virtual int compare(const CCallsign &callsign) const;
/*!
* \brief Register metadata
*/
@@ -145,6 +134,21 @@ namespace BlackMisc
*/
virtual QString convertToQString(bool i18n = false) const;
/*!
* \copydoc CValueObject::getMetaTypeId
*/
virtual int getMetaTypeId() const;
/*!
* \copydoc CValueObject::isA
*/
virtual bool isA(int metaTypeId) const;
/*!
* \copydoc CValueObject::compareImpl
*/
virtual int compareImpl(const CValueObject &other) const;
/*!
* \brief Stream to DBus <<
* \param argument

View File

@@ -13,6 +13,36 @@ namespace BlackMisc
return this->m_message;
}
/*
* metaTypeId
*/
int CInformationMessage::getMetaTypeId() const
{
return qMetaTypeId<CInformationMessage>();
}
/*
* is a
*/
bool CInformationMessage::isA(int metaTypeId) const
{
if (metaTypeId == qMetaTypeId<CInformationMessage>()) { return true; }
return this->CValueObject::isA(metaTypeId);
}
/*
* Compare
*/
int CInformationMessage::compareImpl(const CValueObject &otherBase) const
{
const auto &other = static_cast<const CInformationMessage &>(otherBase);
if (this->m_type < other.m_type) { return -1; }
if (this->m_type > other.m_type) { return 1; }
return this->m_message.compare(other.m_message);
}
/*
* Marshall to DBus
*/

View File

@@ -164,6 +164,21 @@ namespace BlackMisc
*/
virtual QString convertToQString(bool i18n = false) const;
/*!
* \copydoc CValueObject::getMetaTypeId
*/
virtual int getMetaTypeId() const;
/*!
* \copydoc CValueObject::isA
*/
virtual bool isA(int metaTypeId) const;
/*!
* \copydoc CValueObject::compareImpl
*/
virtual int compareImpl(const CValueObject &other) const;
/*!
* \brief Stream to DBus <<
* \param argument

View File

@@ -58,6 +58,26 @@ namespace BlackMisc
return this->m_name == other.m_name;
}
/*!
* \copydoc CValueObject::getMetaTypeId
*/
virtual int getMetaTypeId() const { return 0; }
/*!
* \copydoc CValueObject::isA
*/
virtual bool isA(int metaTypeId) const { return this->CValueObject::isA(metaTypeId); }
/*!
* \copydoc CValueObject::compareImpl
*/
virtual int compareImpl(const CValueObject &other) const
{
Q_UNUSED(other);
qFatal("not implemented");
return 0;
}
/*!
* \brief Stream to DBus <<
* \param argument

View File

@@ -221,7 +221,7 @@ int BlackMisc:: compareQVariants(const QVariant &v1, const QVariant &v2)
const CValueObject *cs2 = CValueObject::fromQVariant(v2);
if (cs1 && cs2)
{
return cs1->compare(v2); // Note, that I have to compare against QVariant
return compare(*cs1, *cs2);
}
}

View File

@@ -152,6 +152,36 @@ namespace BlackMisc
return str += "}";
}
/*!
* \copydoc CValueObject::getMetaTypeId
*/
virtual int getMetaTypeId() const { return qMetaTypeId<C<T>>(); }
/*!
* \copydoc CValueObject::isA
*/
virtual bool isA(int metaTypeId) const
{
if (metaTypeId == qMetaTypeId<C<T>>()) { return true; }
return CValueObject::isA(metaTypeId);
}
/*!
* \copydoc CValueObject::compareImpl
*/
virtual int compareImpl(const CValueObject &/*other*/) const
{
//const auto &o = static_cast<const CContainerBase &>(other);
//if (derived().size() < o.derived().size()) { return -1; }
//if (derived().size() > o.derived().size()) { return 1; }
//for (auto i1 = derived().begin(), i2 = o.derived().begin(); i1 != derived().end() && i2 != o.derived().end(); ++i1, ++i2)
//{
// if (*i1 < *i2) { return -1; }
// if (*i1 > *i2) { return 1; }
//}
return 0;
}
virtual void marshallToDbus(QDBusArgument &argument) const
{
argument.beginArray(qMetaTypeId<T>());

View File

@@ -25,6 +25,38 @@ namespace BlackMisc
return s.arg(this->m_latitude.valueRoundedWithUnit(6, i18n)).arg(this->m_longitude.valueRoundedWithUnit(6, i18n)).arg(this->m_height.valueRoundedWithUnit(i18n));
}
/*
* metaTypeId
*/
int CCoordinateGeodetic::getMetaTypeId() const
{
return qMetaTypeId<CCoordinateGeodetic>();
}
/*
* is a
*/
bool CCoordinateGeodetic::isA(int metaTypeId) const
{
if (metaTypeId == qMetaTypeId<CCoordinateGeodetic>()) { return true; }
return this->CValueObject::isA(metaTypeId);
}
/*
* Compare
*/
int CCoordinateGeodetic::compareImpl(const CValueObject &otherBase) const
{
const auto &other = static_cast<const CCoordinateGeodetic &>(otherBase);
int cmp = compare(this->m_latitude, other.m_latitude);
if (cmp) { return cmp; }
cmp = compare(this->m_longitude, other.m_longitude);
if (cmp) { return cmp; }
return compare(this->m_height, other.m_height);
}
/*
* Marshall to Dbus
*/

View File

@@ -82,6 +82,21 @@ namespace BlackMisc
*/
virtual QString convertToQString(bool i18n = false) const;
/*!
* \copydoc CValueObject::getMetaTypeId
*/
virtual int getMetaTypeId() const;
/*!
* \copydoc CValueObject::isA
*/
virtual bool isA(int metaTypeId) const;
/*!
* \copydoc CValueObject::compareImpl
*/
virtual int compareImpl(const CValueObject &other) const;
/*!
* \brief Stream to DBus
* \param argument

View File

@@ -71,17 +71,34 @@ namespace BlackMisc
return LATorLON(a);
}
/*
* metaTypeId
*/
template <class LATorLON> int CEarthAngle<LATorLON>::getMetaTypeId() const
{
return qMetaTypeId<LATorLON>();
}
/*
* is a
*/
template <class LATorLON> bool CEarthAngle<LATorLON>::isA(int metaTypeId) const
{
if (metaTypeId == qMetaTypeId<LATorLON>()) { return true; }
return this->CAngle::isA(metaTypeId);
}
/*
* Compare
*/
template <class LATorLON> int CEarthAngle<LATorLON>::compare(const QVariant &qv) const
template <class LATorLON> int CEarthAngle<LATorLON>::compareImpl(const CValueObject &otherBase) const
{
Q_ASSERT(qv.canConvert<LATorLON>() || qv.canConvert<CAngle>());
Q_ASSERT(qv.isValid() && !qv.isNull());
if (qv.canConvert<LATorLON>())
return this->compare(qv.value<LATorLON>());
else
return this->compare(qv.value<CAngle>());
const auto &other = static_cast<const LATorLON &>(otherBase);
if (*this < other) { return -1; }
else if (*this > other) { return 1; }
else { return 0; }
}
// see here for the reason of thess forward instantiations

View File

@@ -45,6 +45,21 @@ namespace BlackMisc
return this->valueRoundedWithUnit(BlackMisc::PhysicalQuantities::CAngleUnit::deg(), 6, i18n);
}
/*!
* \copydoc CValueObject::getMetaTypeId
*/
virtual int getMetaTypeId() const;
/*!
* \copydoc CValueObject::isA
*/
virtual bool isA(int metaTypeId) const;
/*!
* \copydoc CValueObject::compareImpl
*/
virtual int compareImpl(const CValueObject &other) const;
/*!
* \brief Stream to DBus <<
* \param argument
@@ -175,20 +190,6 @@ namespace BlackMisc
return l;
}
/*!
* Compare
*/
int compare(const QVariant &qv) const;
/*!
* \todo this is a hack, to avoid hiding inherited names in CPhysicalQuantity
* (see Effective C++ item 33) CPhysicalQuantity::compare is the real culprit
*/
int compare(const CEarthAngle &other) const
{
return static_cast<const CPhysicalQuantity<BlackMisc::PhysicalQuantities::CAngleUnit, BlackMisc::PhysicalQuantities::CAngle> *>(this)->compare(other);
}
/*!
* Register metadata
*/

View File

@@ -138,6 +138,42 @@ namespace BlackMisc
return s;
}
/*
* metaTypeId
*/
template <class ImplMatrix, int Rows, int Columns> int CMatrixBase<ImplMatrix, Rows, Columns>::getMetaTypeId() const
{
return qMetaTypeId<ImplMatrix>();
}
/*
* is a
*/
template <class ImplMatrix, int Rows, int Columns> bool CMatrixBase<ImplMatrix, Rows, Columns>::isA(int metaTypeId) const
{
if (metaTypeId == qMetaTypeId<ImplMatrix>()) { return true; }
return this->CValueObject::isA(metaTypeId);
}
/*
* Compare
*/
template <class ImplMatrix, int Rows, int Columns> int CMatrixBase<ImplMatrix, Rows, Columns>::compareImpl(const CValueObject &otherBase) const
{
const auto &other = static_cast<const CMatrixBase &>(otherBase);
for (int r = 0; r < Rows; ++r)
{
for (int c = 0; c < Columns; ++c)
{
if (this->m_matrix(r, c) < other.m_matrix(r, c)) { return -1; }
if (this->m_matrix(r, c) > other.m_matrix(r, c)) { return 1; }
}
}
return 0;
}
/*
* Hash
*/

View File

@@ -51,6 +51,21 @@ namespace BlackMisc
*/
QString convertToQString(bool i18n = false) const;
/*!
* \copydoc CValueObject::getMetaTypeId
*/
virtual int getMetaTypeId() const;
/*!
* \copydoc CValueObject::isA
*/
virtual bool isA(int metaTypeId) const;
/*!
* \copydoc CValueObject::compareImpl
*/
virtual int compareImpl(const CValueObject &other) const;
/*!
* \brief Stream to DBus
* \param argument

View File

@@ -8,6 +8,7 @@
#include "blackmisc/coordinateecef.h"
#include "blackmisc/coordinatened.h"
#include "blackmisc/blackmiscfreefunctions.h"
#include <tuple>
namespace BlackMisc
{
@@ -26,6 +27,39 @@ namespace BlackMisc
return s;
}
/*
* metaTypeId
*/
template <class ImplVector> int CVector3DBase<ImplVector>::getMetaTypeId() const
{
return qMetaTypeId<ImplVector>();
}
/*
* is a
*/
template <class ImplVector> bool CVector3DBase<ImplVector>::isA(int metaTypeId) const
{
if (metaTypeId == qMetaTypeId<ImplVector>()) { return true; }
return this->CValueObject::isA(metaTypeId);
}
/*
* Compare
*/
template <class ImplVector> int CVector3DBase<ImplVector>::compareImpl(const CValueObject &otherBase) const
{
const auto &other = static_cast<const CVector3DBase &>(otherBase);
const auto lhs = std::tie(this->m_i, this->m_j, this->m_k);
const auto rhs = std::tie(other.m_i, other.m_j, other.m_k);
if (lhs < rhs) { return -1; }
if (lhs > rhs) { return 1; }
return 0;
}
/*
* Vector to zero
*/

View File

@@ -80,6 +80,21 @@ namespace BlackMisc
*/
virtual QString convertToQString(bool i18n = false) const;
/*!
* \copydoc CValueObject::getMetaTypeId
*/
virtual int getMetaTypeId() const;
/*!
* \copydoc CValueObject::isA
*/
virtual bool isA(int metaTypeId) const;
/*!
* \copydoc CValueObject::compareImpl
*/
virtual int compareImpl(const CValueObject &other) const;
/*!
* \brief Unmarshall from Dbus
* \param argument

View File

@@ -1,5 +1,6 @@
#include "nwserver.h"
#include "blackmisc/blackmiscfreefunctions.h"
#include <tuple>
namespace BlackMisc
{
@@ -18,6 +19,39 @@ namespace BlackMisc
return s;
}
/*
* metaTypeId
*/
int CServer::getMetaTypeId() const
{
return qMetaTypeId<CServer>();
}
/*
* is a
*/
bool CServer::isA(int metaTypeId) const
{
if (metaTypeId == qMetaTypeId<CServer>()) { return true; }
return this->CValueObject::isA(metaTypeId);
}
/*
* Compare
*/
int CServer::compareImpl(const CValueObject &otherBase) const
{
const auto &other = static_cast<const CServer &>(otherBase);
const auto lhs = std::tie(this->m_name, this->m_description, this->m_address, this->m_port);
const auto rhs = std::tie(other.m_name, other.m_description, other.m_address, other.m_port);
if (lhs < rhs) { return -1; }
if (lhs > rhs) { return 1; }
return compare(this->m_user, other.m_user);
}
/*
* Marshall to DBus
*/

View File

@@ -181,6 +181,21 @@ namespace BlackMisc
*/
virtual QString convertToQString(bool i18n = false) const;
/*!
* \copydoc CValueObject::getMetaTypeId
*/
virtual int getMetaTypeId() const;
/*!
* \copydoc CValueObject::isA
*/
virtual bool isA(int metaTypeId) const;
/*!
* \copydoc CValueObject::compareImpl
*/
virtual int compareImpl(const CValueObject &other) const;
/*!
* \brief Stream to DBus <<
* \param argument

View File

@@ -28,6 +28,34 @@ namespace BlackMisc
return s;
}
/*
* metaTypeId
*/
int CTextMessage::getMetaTypeId() const
{
return qMetaTypeId<CTextMessage>();
}
/*
* is a
*/
bool CTextMessage::isA(int metaTypeId) const
{
if (metaTypeId == qMetaTypeId<CTextMessage>()) { return true; }
return this->CValueObject::isA(metaTypeId);
}
/*
* Compare
*/
int CTextMessage::compareImpl(const CValueObject &otherBase) const
{
const auto &other = static_cast<const CTextMessage &>(otherBase);
return this->m_message.compare(other.m_message);
}
/*
* Marshall to DBus
*/

View File

@@ -234,6 +234,21 @@ namespace BlackMisc
*/
virtual QString convertToQString(bool i18n = false) const;
/*!
* \copydoc CValueObject::getMetaTypeId
*/
virtual int getMetaTypeId() const;
/*!
* \copydoc CValueObject::isA
*/
virtual bool isA(int metaTypeId) const;
/*!
* \copydoc CValueObject::compareImpl
*/
virtual int compareImpl(const CValueObject &other) const;
/*!
* \brief Stream to DBus <<
* \param argument

View File

@@ -1,5 +1,6 @@
#include "nwuser.h"
#include "blackmisc/blackmiscfreefunctions.h"
#include <tuple>
namespace BlackMisc
{
@@ -19,6 +20,39 @@ namespace BlackMisc
return s;
}
/*
* metaTypeId
*/
int CUser::getMetaTypeId() const
{
return qMetaTypeId<CUser>();
}
/*
* is a
*/
bool CUser::isA(int metaTypeId) const
{
if (metaTypeId == qMetaTypeId<CUser>()) { return true; }
return this->CValueObject::isA(metaTypeId);
}
/*
* Compare
*/
int CUser::compareImpl(const CValueObject &otherBase) const
{
const auto &other = static_cast<const CUser &>(otherBase);
const auto lhs = std::tie(this->m_id, this->m_realname, this->m_email, this->m_password);
const auto rhs = std::tie(other.m_id, other.m_realname, other.m_email, other.m_password);
if (lhs < rhs) { return -1; }
if (lhs > rhs) { return 1; }
return 0;
}
/*
* Marshall to DBus
*/

View File

@@ -185,6 +185,21 @@ namespace BlackMisc
*/
virtual QString convertToQString(bool i18n = false) const;
/*!
* \copydoc CValueObject::getMetaTypeId
*/
virtual int getMetaTypeId() const;
/*!
* \copydoc CValueObject::isA
*/
virtual bool isA(int metaTypeId) const;
/*!
* \copydoc CValueObject::compareImpl
*/
virtual int compareImpl(const CValueObject &other) const;
/*!
* \brief Stream to DBus <<
* \param argument

View File

@@ -74,6 +74,33 @@ namespace BlackMisc
return s;
}
/*
* metaTypeId
*/
int CMeasurementUnit::getMetaTypeId() const
{
return qMetaTypeId<CMeasurementUnit>();
}
/*
* is a
*/
bool CMeasurementUnit::isA(int metaTypeId) const
{
if (metaTypeId == qMetaTypeId<CMeasurementUnit>()) { return true; }
return this->CValueObject::isA(metaTypeId);
}
/*
* Compare
*/
int CMeasurementUnit::compareImpl(const CValueObject &/*otherBase*/) const
{
qFatal("not implemented");
return 0;
}
/*!
* \brief Register metadata of unit and quantity
*/

View File

@@ -230,6 +230,21 @@ namespace BlackMisc
return this->getSymbol(i18n);
}
/*!
* \copydoc CValueObject::getMetaTypeId
*/
virtual int getMetaTypeId() const;
/*!
* \copydoc CValueObject::isA
*/
virtual bool isA(int metaTypeId) const;
/*!
* \copydoc CValueObject::compareImpl
*/
virtual int compareImpl(const CValueObject &other) const;
/*!
* \brief Stream to DBus
* \param argument

View File

@@ -266,22 +266,33 @@ namespace BlackMisc
}
/*
* Compare
* metaTypeId
*/
template <class MU, class PQ> int CPhysicalQuantity<MU, PQ>::compare(const QVariant &qv) const
template <class MU, class PQ> int CPhysicalQuantity<MU, PQ>::getMetaTypeId() const
{
Q_ASSERT(qv.canConvert<PQ>());
Q_ASSERT(!qv.isNull() && qv.isValid());
return this->compare(qv.value<PQ>());
return qMetaTypeId<PQ>();
}
/*
* is a
*/
template <class MU, class PQ> bool CPhysicalQuantity<MU, PQ>::isA(int metaTypeId) const
{
if (metaTypeId == qMetaTypeId<PQ>()) { return true; }
return this->CValueObject::isA(metaTypeId);
}
/*
* Compare
*/
template <class MU, class PQ> int CPhysicalQuantity<MU, PQ>::compare(const PQ &other) const
template <class MU, class PQ> int CPhysicalQuantity<MU, PQ>::compareImpl(const CValueObject &otherBase) const
{
if (other == (*this)) return 0;
return ((*this) < other) ? -1 : 1;
const auto &other = static_cast<const CPhysicalQuantity &>(otherBase);
if (*this < other) { return -1; }
else if (*this > other) { return 1; }
else { return 0; }
}
// see here for the reason of thess forward instantiations

View File

@@ -68,6 +68,21 @@ namespace BlackMisc
*/
virtual QString convertToQString(bool i18n = false) const;
/*!
* \copydoc CValueObject::getMetaTypeId
*/
virtual int getMetaTypeId() const;
/*!
* \copydoc CValueObject::isA
*/
virtual bool isA(int metaTypeId) const;
/*!
* \copydoc CValueObject::compareImpl
*/
virtual int compareImpl(const CValueObject &other) const;
public:
/*!
* \brief Virtual destructor
@@ -357,16 +372,6 @@ namespace BlackMisc
* \brief Register metadata of unit and quantity
*/
static void registerMetadata();
/*!
* \copydoc BlackObject::compare
*/
virtual int compare(const QVariant &qv) const;
/*!
* \copydoc BlackObject::compare
*/
virtual int compare(const PQ &other) const;
};
} // namespace

View File

@@ -34,6 +34,33 @@ namespace BlackMisc
return s;
}
/*
* metaTypeId
*/
int CSettingsNetwork::getMetaTypeId() const
{
return qMetaTypeId<CSettingsNetwork>();
}
/*
* is a
*/
bool CSettingsNetwork::isA(int metaTypeId) const
{
if (metaTypeId == qMetaTypeId<CSettingsNetwork>()) { return true; }
return this->CValueObject::isA(metaTypeId);
}
/*
* Compare
*/
int CSettingsNetwork::compareImpl(const CValueObject &/*otherBase*/) const
{
qFatal("not implemented");
return 0;
}
/*
* Marshall to DBus
*/

View File

@@ -132,6 +132,21 @@ namespace BlackMisc
*/
virtual QString convertToQString(bool i18n = false) const;
/*!
* \copydoc CValueObject::getMetaTypeId
*/
virtual int getMetaTypeId() const;
/*!
* \copydoc CValueObject::isA
*/
virtual bool isA(int metaTypeId) const;
/*!
* \copydoc CValueObject::compareImpl
*/
virtual int compareImpl(const CValueObject &other) const;
/*!
* \brief Stream to DBus <<
* \param argument

View File

@@ -33,6 +33,36 @@ namespace BlackMisc
return s;
}
/*
* metaTypeId
*/
int CStatusMessage::getMetaTypeId() const
{
return qMetaTypeId<CStatusMessage>();
}
/*
* is a
*/
bool CStatusMessage::isA(int metaTypeId) const
{
if (metaTypeId == qMetaTypeId<CStatusMessage>()) { return true; }
return this->CValueObject::isA(metaTypeId);
}
/*
* Compare
*/
int CStatusMessage::compareImpl(const CValueObject &otherBase) const
{
const auto &other = static_cast<const CStatusMessage &>(otherBase);
if (this->m_type < other.m_type) { return -1; }
if (this->m_type > other.m_type) { return 1; }
return this->m_message.compare(other.m_message);
}
/*
* Metadata
*/

View File

@@ -147,6 +147,21 @@ namespace BlackMisc
* \return
*/
virtual QString convertToQString(bool i18n = false) const;
/*!
* \copydoc CValueObject::getMetaTypeId
*/
virtual int getMetaTypeId() const;
/*!
* \copydoc CValueObject::isA
*/
virtual bool isA(int metaTypeId) const;
/*!
* \copydoc CValueObject::compareImpl
*/
virtual int compareImpl(const CValueObject &other) const;
};
}

View File

@@ -38,6 +38,33 @@ namespace BlackMisc
return s;
}
/*
* metaTypeId
*/
int CValueMap::getMetaTypeId() const
{
return qMetaTypeId<CValueMap>();
}
/*
* is a
*/
bool CValueMap::isA(int metaTypeId) const
{
if (metaTypeId == qMetaTypeId<CValueMap>()) { return true; }
return this->CValueObject::isA(metaTypeId);
}
/*
* Compare
*/
int CValueMap::compareImpl(const CValueObject &/*otherBase*/) const
{
qFatal("not implemented");
return 0;
}
/*
* Marshall to DBus
*/

View File

@@ -131,6 +131,21 @@ namespace BlackMisc
*/
virtual QString convertToQString(bool i18n = false) const;
/*!
* \copydoc CValueObject::getMetaTypeId
*/
virtual int getMetaTypeId() const;
/*!
* \copydoc CValueObject::isA
*/
virtual bool isA(int metaTypeId) const;
/*!
* \copydoc CValueObject::compareImpl
*/
virtual int compareImpl(const CValueObject &other) const;
/*!
* \brief Stream to DBus <<
* \param argument

View File

@@ -87,11 +87,21 @@ namespace BlackMisc
/*
* Compare
*/
int CValueObject::compare(const QVariant & /** qv **/) const
int compare(const CValueObject &v1, const CValueObject &v2)
{
// not all classes have to implement this
qFatal("Property by index as string not implemented");
return -1; // avoid compiler warning
if (v1.isA(v2.getMetaTypeId()))
{
return v2.compareImpl(v1) * -1;
}
else if (v2.isA(v1.getMetaTypeId()))
{
return v1.compareImpl(v2);
}
else
{
Q_ASSERT_X(false, Q_FUNC_INFO, "Attempt to compare between instances of unrelated classes");
return 0;
}
}
/*!

View File

@@ -141,6 +141,15 @@ namespace BlackMisc
*/
friend bool operator!=(const CValueObject &uc, const CValueMap &valueMap);
/*!
* Compares two instances of related classes
* and returns an integer less than, equal to, or greater than zero
* if v1 is less than, equal to, or greater than v2.
* \return
* \pre The runtime types of the two objects must be the same or related by inheritance.
*/
friend int compare(const CValueObject &v1, const CValueObject &v2);
public:
/*!
* \brief Virtual destructor
@@ -179,15 +188,6 @@ namespace BlackMisc
*/
virtual uint getValueHash() const = 0;
/*!
* Compares with QVariant with this object
* and returns an integer less than, equal to, or greater than zero
* if this is less than, equal to, or greater than QVariant.
* \remarks allows sorting among QVariants, not all classes implement this
* \return
*/
virtual int compare(const QVariant &qv) const;
/*!
* \brief Virtual method to return QVariant, used with DBUS QVariant lists
* \return
@@ -257,6 +257,30 @@ namespace BlackMisc
*/
virtual QString convertToQString(bool i18n = false) const = 0;
/*!
* \brief Returns the Qt meta type ID of this object.
* \return
*/
virtual int getMetaTypeId() const = 0;
/*!
* \brief Returns true if this object is an instance of the class with the given meta type ID,
* or one of its subclasses.
* \param metaTypeId
* \return
*/
virtual bool isA(int metaTypeId) const { Q_UNUSED(metaTypeId); return false; }
/*!
* \brief Compare this value with another value of the same type
* \param other
* \return Less than, equal to, or greater than zero if this is
* less than, equal to, or greather than other.
* \pre Other must have the same runtime type as the this object.
* \remark It is usually safer to use the friend function compare() instead.
*/
virtual int compareImpl(const CValueObject &other) const = 0;
/*!
* \brief Marshall to DBus
* \param argument

View File

@@ -10,6 +10,7 @@
#include "vaudiodevice.h"
#include "blackmisc/blackmiscfreefunctions.h"
#include <QtNetwork/QHostInfo>
#include <tuple>
namespace BlackMisc
{
@@ -90,6 +91,39 @@ namespace BlackMisc
return s;
}
/*
* metaTypeId
*/
int CAudioDevice::getMetaTypeId() const
{
return qMetaTypeId<CAudioDevice>();
}
/*
* is a
*/
bool CAudioDevice::isA(int metaTypeId) const
{
if (metaTypeId == qMetaTypeId<CAudioDevice>()) { return true; }
return this->CValueObject::isA(metaTypeId);
}
/*
* Compare
*/
int CAudioDevice::compareImpl(const CValueObject &otherBase) const
{
const auto &other = static_cast<const CAudioDevice &>(otherBase);
const auto lhs = std::tie(this->m_type, this->m_deviceIndex, this->m_deviceName, this->m_hostName);
const auto rhs = std::tie(other.m_type, other.m_deviceIndex, other.m_deviceName, other.m_hostName);
if (lhs < rhs) { return -1; }
if (lhs > rhs) { return 1; }
return 0;
}
/*
* Marshall to DBus
*/

View File

@@ -126,6 +126,21 @@ namespace BlackMisc
*/
virtual QString convertToQString(bool i18n = false) const;
/*!
* \copydoc CValueObject::getMetaTypeId
*/
virtual int getMetaTypeId() const;
/*!
* \copydoc CValueObject::isA
*/
virtual bool isA(int metaTypeId) const;
/*!
* \copydoc CValueObject::compareImpl
*/
virtual int compareImpl(const CValueObject &other) const;
/*!
* \brief Stream to DBus <<
* \param argument

View File

@@ -9,9 +9,9 @@
#include "vvoiceroom.h"
#include "blackmisc/blackmiscfreefunctions.h"
#include <QChar>
#include <QStringList>
#include <tuple>
namespace BlackMisc
{
@@ -85,6 +85,39 @@ namespace BlackMisc
return s;
}
/*
* metaTypeId
*/
int CVoiceRoom::getMetaTypeId() const
{
return qMetaTypeId<CVoiceRoom>();
}
/*
* is a
*/
bool CVoiceRoom::isA(int metaTypeId) const
{
if (metaTypeId == qMetaTypeId<CVoiceRoom>()) { return true; }
return CValueObject::isA(metaTypeId);
}
/*
* Compare
*/
int CVoiceRoom::compareImpl(const CValueObject &otherBase) const
{
const auto &other = static_cast<const CVoiceRoom &>(otherBase);
const auto lhs = std::tie(m_hostname, m_channel, m_connected, m_audioPlaying);
const auto rhs = std::tie(other.m_hostname, other.m_channel, other.m_connected, other.m_audioPlaying);
if (lhs < rhs) { return -1; }
if (lhs > rhs) { return 1; }
return 0;
}
/*
* Marshall to DBus
*/

View File

@@ -166,6 +166,21 @@ namespace BlackMisc
*/
virtual QString convertToQString(bool i18n = false) const;
/*!
* \copydoc CValueObject::getMetaTypeId
*/
virtual int getMetaTypeId() const;
/*!
* \copydoc CValueObject::isA
*/
virtual bool isA(int metaTypeId) const;
/*!
* \copydoc CValueObject::compareImpl
*/
virtual int compareImpl(const CValueObject &other) const;
/*!
* \brief Stream to DBus <<
* \param argument

View File

@@ -46,6 +46,10 @@ namespace BlackMiscTest
QVERIFY2(station1 == station1qv, "Station should be equal (QVariant)");
QVERIFY2(station2 == station1qv, "Station should be equal (QVariant)");
QVERIFY2(station3 != station1qv, "Station should be equal (QVariant)");
QVERIFY2(compare(station1, station1) == 0, "Station should be equal");
QVERIFY2(compare(station1, station2) == 0, "Station should be equal");
QVERIFY2(compare(station1, station3) != 0, "Station should not be equal");
}
/*