mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-21 04:45:31 +08:00
refs #413 To signal when contained object doesn't support an operation, throw exception in CValueObjectMetaInfo and catch in CVariant.
This commit is contained in:
@@ -19,6 +19,7 @@
|
|||||||
#include <QDBusMetaType>
|
#include <QDBusMetaType>
|
||||||
#include <QDBusArgument>
|
#include <QDBusArgument>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
namespace BlackMisc
|
namespace BlackMisc
|
||||||
{
|
{
|
||||||
@@ -57,17 +58,37 @@ namespace BlackMisc
|
|||||||
virtual void toIcon(const void *object, CIcon &o_icon) const = 0;
|
virtual void toIcon(const void *object, CIcon &o_icon) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//! \private Exception to signal that an unsupported operation was requested.
|
||||||
|
class CVariantException : public std::invalid_argument
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
template <class T>
|
||||||
|
CVariantException(const T &, const QString &operationName) : std::invalid_argument((blurb<T>(operationName)).toStdString()), m_operationName(operationName) {}
|
||||||
|
|
||||||
|
const QString &operationName() const { return m_operationName; }
|
||||||
|
|
||||||
|
~CVariantException() Q_DECL_NOEXCEPT {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString m_operationName;
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
static QString blurb(const QString &operationName)
|
||||||
|
{
|
||||||
|
return QString("CVariant requested unsupported operation of contained ") + QMetaType::typeName(qMetaTypeId<T>()) + " object: " + operationName;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
//! \private
|
//! \private
|
||||||
namespace Fallback
|
namespace Fallback
|
||||||
{
|
{
|
||||||
//! \private Fallback in case qHash is not defined for T.
|
//! \private Fallback in case qHash is not defined for T.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
uint qHash(const T &object) { return 0; }
|
uint qHash(const T &object) { throw CVariantException(object, "qHash"); }
|
||||||
|
|
||||||
//! \private Fallback in case compare is not defined for T.
|
//! \private Fallback in case compare is not defined for T.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
int compare(const T &a, const T &) { return 0; }
|
int compare(const T &a, const T &) { throw CVariantException(a, "compare"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \private Implementation of IValueObjectMetaInfo representing the set of operations supported by T.
|
//! \private Implementation of IValueObjectMetaInfo representing the set of operations supported by T.
|
||||||
@@ -80,20 +101,20 @@ namespace BlackMisc
|
|||||||
template <typename U> struct Derived : public U, public Fallback {};
|
template <typename U> struct Derived : public U, public Fallback {};
|
||||||
# define DISABLE_IF_HAS(MEMBER) typename int_t<&Derived<U>::MEMBER>::type
|
# define DISABLE_IF_HAS(MEMBER) typename int_t<&Derived<U>::MEMBER>::type
|
||||||
|
|
||||||
template <typename U> static QJsonObject toJsonHelper(const U &, DISABLE_IF_HAS(toJson)) { return {}; }
|
template <typename U> static QJsonObject toJsonHelper(const U &object, DISABLE_IF_HAS(toJson)) { throw CVariantException(object, "toJson"); }
|
||||||
template <typename U> static QJsonObject toJsonHelper(const U &object, ...) { return object.toJson(); }
|
template <typename U> static QJsonObject toJsonHelper(const U &object, ...) { return object.toJson(); }
|
||||||
template <typename U> static void convertFromJsonHelper(const QJsonObject &, U &, DISABLE_IF_HAS(convertFromJson)) {}
|
template <typename U> static void convertFromJsonHelper(const QJsonObject &, U &object, DISABLE_IF_HAS(convertFromJson)) { throw CVariantException(object, "convertFromJson"); }
|
||||||
template <typename U> static void convertFromJsonHelper(const QJsonObject &json, U &object, ...) { object.convertFromJson(json); }
|
template <typename U> static void convertFromJsonHelper(const QJsonObject &json, U &object, ...) { object.convertFromJson(json); }
|
||||||
template <typename U> static void setPropertyByIndexHelper(U &, const CVariant &, const CPropertyIndex &, DISABLE_IF_HAS(setPropertyByIndex)) {}
|
template <typename U> static void setPropertyByIndexHelper(U &object, const CVariant &, const CPropertyIndex &, DISABLE_IF_HAS(setPropertyByIndex)) { throw CVariantException(object, "setPropertyByIndex"); }
|
||||||
template <typename U> static void setPropertyByIndexHelper(U &object, const CVariant &variant, const CPropertyIndex &index, ...) { object.setPropertyByIndex(variant, index); }
|
template <typename U> static void setPropertyByIndexHelper(U &object, const CVariant &variant, const CPropertyIndex &index, ...) { object.setPropertyByIndex(variant, index); }
|
||||||
template <typename U> static void propertyByIndexHelper(CVariant &, const U &, const CPropertyIndex &, DISABLE_IF_HAS(propertyByIndex)) {}
|
template <typename U> static void propertyByIndexHelper(CVariant &, const U &object, const CPropertyIndex &, DISABLE_IF_HAS(propertyByIndex)) { throw CVariantException(object, "propertyByIndex"); }
|
||||||
template <typename U> static void propertyByIndexHelper(CVariant &o_variant, const U &object, const CPropertyIndex &index, ...) { assign(o_variant, object.propertyByIndex(index)); }
|
template <typename U> static void propertyByIndexHelper(CVariant &o_variant, const U &object, const CPropertyIndex &index, ...) { assign(o_variant, object.propertyByIndex(index)); }
|
||||||
template <typename U> static QString propertyByIndexAsStringHelper(const U &, const CPropertyIndex &, bool, DISABLE_IF_HAS(propertyByIndexAsString)) { return {}; }
|
template <typename U> static QString propertyByIndexAsStringHelper(const U &object, const CPropertyIndex &, bool, DISABLE_IF_HAS(propertyByIndexAsString)) { throw CVariantException(object, "propertyByIndexAsString"); }
|
||||||
template <typename U> static QString propertyByIndexAsStringHelper(const U &object, const CPropertyIndex &index, bool i18n, ...) { return object.propertyByIndexAsString(index, i18n); }
|
template <typename U> static QString propertyByIndexAsStringHelper(const U &object, const CPropertyIndex &index, bool i18n, ...) { return object.propertyByIndexAsString(index, i18n); }
|
||||||
template <typename U> static bool equalsPropertyByIndexHelper(const U &, const CVariant &, const CPropertyIndex &, DISABLE_IF_HAS(equalsPropertyByIndex)) { return false; }
|
template <typename U> static bool equalsPropertyByIndexHelper(const U &object, const CVariant &, const CPropertyIndex &, DISABLE_IF_HAS(equalsPropertyByIndex)) { throw CVariantException(object, "equalsPropertyByIndex"); }
|
||||||
template <typename U> static bool equalsPropertyByIndexHelper(const U &object, const CVariant &variant, const CPropertyIndex &index, ...) { return object.equalsPropertyByIndex(variant, index); }
|
template <typename U> static bool equalsPropertyByIndexHelper(const U &object, const CVariant &variant, const CPropertyIndex &index, ...) { return object.equalsPropertyByIndex(variant, index); }
|
||||||
template <typename U> static void toIconHelper(const U &, CIcon &, DISABLE_IF_HAS(toIcon)) {}
|
template <typename U> static void toIconHelper(const U &object, CIcon &, DISABLE_IF_HAS(toIcon)) { throw CVariantException(object, "toIcon"); }
|
||||||
template <typename U> static void toIconHelper(const U &, CIcon &, typename std::enable_if<std::is_same<U, CVariant>::value, int>::type) {} // CIcon is incomplete when CValueObjectMetaInfo<CVariant> is instantiated
|
template <typename U> static void toIconHelper(const U &object, CIcon &, typename std::enable_if<std::is_same<U, CVariant>::value, int>::type) { throw CVariantException(object, "toIcon"); } // CIcon is incomplete when CValueObjectMetaInfo<CVariant> is instantiated
|
||||||
template <typename U> static void toIconHelper(const U &object, CIcon &o_icon, ...) { assign(o_icon, object.toIcon()); }
|
template <typename U> static void toIconHelper(const U &object, CIcon &o_icon, ...) { assign(o_icon, object.toIcon()); }
|
||||||
|
|
||||||
# undef DISABLE_IF_HAS
|
# undef DISABLE_IF_HAS
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include "variant.h"
|
#include "variant.h"
|
||||||
#include "blackmiscfreefunctions.h"
|
#include "blackmiscfreefunctions.h"
|
||||||
#include "icon.h"
|
#include "icon.h"
|
||||||
|
#include "logmessage.h"
|
||||||
#include <QDBusArgument>
|
#include <QDBusArgument>
|
||||||
#include <QDBusMetaType>
|
#include <QDBusMetaType>
|
||||||
#include <QDBusVariant>
|
#include <QDBusVariant>
|
||||||
@@ -44,18 +45,26 @@ namespace BlackMisc
|
|||||||
auto *bMeta = b.getValueObjectMetaInfo();
|
auto *bMeta = b.getValueObjectMetaInfo();
|
||||||
if (aMeta && bMeta)
|
if (aMeta && bMeta)
|
||||||
{
|
{
|
||||||
const void *casted = nullptr;
|
try
|
||||||
if ((casted = aMeta->upCastTo(a.data(), bMeta->getMetaTypeId())))
|
|
||||||
{
|
{
|
||||||
return bMeta->compareImpl(casted, b.data());
|
const void *casted = nullptr;
|
||||||
|
if ((casted = aMeta->upCastTo(a.data(), bMeta->getMetaTypeId())))
|
||||||
|
{
|
||||||
|
return bMeta->compareImpl(casted, b.data());
|
||||||
|
}
|
||||||
|
else if ((casted = bMeta->upCastTo(b.data(), aMeta->getMetaTypeId())))
|
||||||
|
{
|
||||||
|
return aMeta->compareImpl(a.data(), casted);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qWarning() << "Comparing two CVariants containing unrelated value objects";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if ((casted = bMeta->upCastTo(b.data(), aMeta->getMetaTypeId())))
|
catch (const Private::CVariantException &ex)
|
||||||
{
|
{
|
||||||
return aMeta->compareImpl(a.data(), casted);
|
CLogMessage().debug() << ex.what();
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
qWarning() << "Comparing two CVariants containing unrelated value objects";
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -81,6 +90,7 @@ namespace BlackMisc
|
|||||||
case QVariant::Char: json.insert("value", m_v.toString());
|
case QVariant::Char: json.insert("value", m_v.toString());
|
||||||
case QVariant::ByteArray: json.insert("value", m_v.toString());
|
case QVariant::ByteArray: json.insert("value", m_v.toString());
|
||||||
default:
|
default:
|
||||||
|
try
|
||||||
{
|
{
|
||||||
auto *meta = getValueObjectMetaInfo();
|
auto *meta = getValueObjectMetaInfo();
|
||||||
if (meta)
|
if (meta)
|
||||||
@@ -96,6 +106,10 @@ namespace BlackMisc
|
|||||||
qWarning() << "Unsupported CVariant type for toJson";
|
qWarning() << "Unsupported CVariant type for toJson";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (const Private::CVariantException &ex)
|
||||||
|
{
|
||||||
|
CLogMessage().debug() << ex.what();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
@@ -117,6 +131,7 @@ namespace BlackMisc
|
|||||||
case QVariant::Char: m_v.setValue(json.value("value").toString().size() > 0 ? json.value("value").toString().at(0) : '\0');
|
case QVariant::Char: m_v.setValue(json.value("value").toString().size() > 0 ? json.value("value").toString().at(0) : '\0');
|
||||||
case QVariant::ByteArray: m_v.setValue(json.value("value").toString().toLatin1());
|
case QVariant::ByteArray: m_v.setValue(json.value("value").toString().toLatin1());
|
||||||
default:
|
default:
|
||||||
|
try
|
||||||
{
|
{
|
||||||
auto *meta = Private::getValueObjectMetaInfo(typeId);
|
auto *meta = Private::getValueObjectMetaInfo(typeId);
|
||||||
if (meta)
|
if (meta)
|
||||||
@@ -137,6 +152,10 @@ namespace BlackMisc
|
|||||||
qWarning() << "Unsupported CVariant type for fromJson";
|
qWarning() << "Unsupported CVariant type for fromJson";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (const Private::CVariantException &ex)
|
||||||
|
{
|
||||||
|
CLogMessage().debug() << ex.what();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,6 +173,7 @@ namespace BlackMisc
|
|||||||
case QVariant::Char: return qHash(m_v.toChar());
|
case QVariant::Char: return qHash(m_v.toChar());
|
||||||
case QVariant::ByteArray: return qHash(m_v.toByteArray());
|
case QVariant::ByteArray: return qHash(m_v.toByteArray());
|
||||||
default:
|
default:
|
||||||
|
try
|
||||||
{
|
{
|
||||||
auto *meta = getValueObjectMetaInfo();
|
auto *meta = getValueObjectMetaInfo();
|
||||||
if (meta)
|
if (meta)
|
||||||
@@ -170,6 +190,11 @@ namespace BlackMisc
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (const Private::CVariantException &ex)
|
||||||
|
{
|
||||||
|
CLogMessage().debug() << ex.what();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,39 +216,78 @@ namespace BlackMisc
|
|||||||
{
|
{
|
||||||
auto *meta = getValueObjectMetaInfo();
|
auto *meta = getValueObjectMetaInfo();
|
||||||
Q_ASSERT(meta);
|
Q_ASSERT(meta);
|
||||||
meta->setPropertyByIndex(data(), variant, index);
|
try
|
||||||
|
{
|
||||||
|
meta->setPropertyByIndex(data(), variant, index);
|
||||||
|
}
|
||||||
|
catch (const Private::CVariantException &ex)
|
||||||
|
{
|
||||||
|
CLogMessage().debug() << ex.what();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CVariant CVariant::propertyByIndex(const BlackMisc::CPropertyIndex &index) const
|
CVariant CVariant::propertyByIndex(const BlackMisc::CPropertyIndex &index) const
|
||||||
{
|
{
|
||||||
auto *meta = getValueObjectMetaInfo();
|
auto *meta = getValueObjectMetaInfo();
|
||||||
Q_ASSERT(meta);
|
Q_ASSERT(meta);
|
||||||
CVariant result;
|
try
|
||||||
meta->propertyByIndex(data(), result, index);
|
{
|
||||||
return result;
|
CVariant result;
|
||||||
|
meta->propertyByIndex(data(), result, index);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
catch (const Private::CVariantException &ex)
|
||||||
|
{
|
||||||
|
CLogMessage().debug() << ex.what();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString CVariant::propertyByIndexAsString(const CPropertyIndex &index, bool i18n) const
|
QString CVariant::propertyByIndexAsString(const CPropertyIndex &index, bool i18n) const
|
||||||
{
|
{
|
||||||
auto *meta = getValueObjectMetaInfo();
|
auto *meta = getValueObjectMetaInfo();
|
||||||
Q_ASSERT(meta);
|
Q_ASSERT(meta);
|
||||||
return meta->propertyByIndexAsString(data(), index, i18n);
|
try
|
||||||
|
{
|
||||||
|
return meta->propertyByIndexAsString(data(), index, i18n);
|
||||||
|
}
|
||||||
|
catch (const Private::CVariantException &ex)
|
||||||
|
{
|
||||||
|
CLogMessage().debug() << ex.what();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CVariant::equalsPropertyByIndex(const CVariant &compareValue, const CPropertyIndex &index) const
|
bool CVariant::equalsPropertyByIndex(const CVariant &compareValue, const CPropertyIndex &index) const
|
||||||
{
|
{
|
||||||
auto *meta = getValueObjectMetaInfo();
|
auto *meta = getValueObjectMetaInfo();
|
||||||
Q_ASSERT(meta);
|
Q_ASSERT(meta);
|
||||||
return meta->equalsPropertyByIndex(data(), compareValue, index);
|
try
|
||||||
|
{
|
||||||
|
return meta->equalsPropertyByIndex(data(), compareValue, index);
|
||||||
|
}
|
||||||
|
catch (const Private::CVariantException &ex)
|
||||||
|
{
|
||||||
|
CLogMessage().debug() << ex.what();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CIcon CVariant::toIcon() const
|
CIcon CVariant::toIcon() const
|
||||||
{
|
{
|
||||||
auto *meta = getValueObjectMetaInfo();
|
auto *meta = getValueObjectMetaInfo();
|
||||||
if (! meta) { return {}; }
|
if (! meta) { return {}; }
|
||||||
CIcon result;
|
try
|
||||||
meta->toIcon(data(), result);
|
{
|
||||||
return result;
|
CIcon result;
|
||||||
|
meta->toIcon(data(), result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
catch (const Private::CVariantException &ex)
|
||||||
|
{
|
||||||
|
CLogMessage().debug() << ex.what();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QPixmap CVariant::toPixmap() const
|
QPixmap CVariant::toPixmap() const
|
||||||
|
|||||||
Reference in New Issue
Block a user