mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-29 20:55:42 +08:00
refs #247 Created a facility to register our own custom metatype metadata.
This commit is contained in:
@@ -17,6 +17,7 @@
|
|||||||
#include "json.h"
|
#include "json.h"
|
||||||
#include "variant.h"
|
#include "variant.h"
|
||||||
#include "blackmiscfreefunctions.h"
|
#include "blackmiscfreefunctions.h"
|
||||||
|
#include "valueobject_private.h"
|
||||||
#include "valueobject_policy.h"
|
#include "valueobject_policy.h"
|
||||||
#include <QtDBus/QDBusMetaType>
|
#include <QtDBus/QDBusMetaType>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
@@ -56,6 +57,24 @@ namespace BlackMisc
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* This registers the value type T with the BlackMisc meta type system,
|
||||||
|
* making it available for use with the extended feature set of BlackMisc::CVariant.
|
||||||
|
*
|
||||||
|
* The implementation (ab)uses the QMetaType converter function registration mechanism
|
||||||
|
* to store a type-erased representation of the set of operations supported by T.
|
||||||
|
* Unlike the singleton pattern, this approach means that CVariant can be used in plugins.
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
void registerMetaValueType()
|
||||||
|
{
|
||||||
|
if (QMetaType::hasRegisteredConverterFunction<T, Private::IValueObjectMetaInfo *>()) { return; }
|
||||||
|
auto converter = [](const T &) { static Private::CValueObjectMetaInfo<T> info; return &info; };
|
||||||
|
bool ok = QMetaType::registerConverter<T, Private::IValueObjectMetaInfo *>(converter);
|
||||||
|
Q_ASSERT(ok);
|
||||||
|
Q_UNUSED(ok);
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Base class for value types.
|
* Base class for value types.
|
||||||
*/
|
*/
|
||||||
@@ -194,6 +213,9 @@ namespace BlackMisc
|
|||||||
static const CValueObject *fromQVariant(const QVariant &variant);
|
static const CValueObject *fromQVariant(const QVariant &variant);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
template <typename T>
|
||||||
|
friend struct Private::CValueObjectMetaInfo;
|
||||||
|
|
||||||
//! Default constructor.
|
//! Default constructor.
|
||||||
CValueObject() = default;
|
CValueObject() = default;
|
||||||
|
|
||||||
@@ -238,6 +260,15 @@ namespace BlackMisc
|
|||||||
virtual void parseFromString(const QString &) { qFatal("Not implemented"); }
|
virtual void parseFromString(const QString &) { qFatal("Not implemented"); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//! \private FIXME defined out-of-line because it depends on CValueObject
|
||||||
|
template <typename T>
|
||||||
|
int Private::CValueObjectMetaInfo<T>::compare(const void *lhs, const void *rhs) const
|
||||||
|
{
|
||||||
|
// Casting to CValueObject here only because compareImpl is protected and CValueObjectMetaInfo is a friend of CValueObject.
|
||||||
|
// TODO: make compareImpl public (and typesafe), then this doesn't need to be defined out-of-line.
|
||||||
|
return static_cast<const CValueObject *>(lhs)->compareImpl(*static_cast<const CValueObject *>(rhs));
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Default policy classes for use by CValueObjectStdTuple.
|
* Default policy classes for use by CValueObjectStdTuple.
|
||||||
*
|
*
|
||||||
|
|||||||
106
src/blackmisc/valueobject_private.h
Normal file
106
src/blackmisc/valueobject_private.h
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
/* Copyright (C) 2014
|
||||||
|
* 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_VALUEOBJECT_PRIVATE_H
|
||||||
|
#define BLACKMISC_VALUEOBJECT_PRIVATE_H
|
||||||
|
|
||||||
|
#include <QMetaType>
|
||||||
|
#include <QDBusArgument>
|
||||||
|
#include <QJsonObject>
|
||||||
|
|
||||||
|
namespace BlackMisc
|
||||||
|
{
|
||||||
|
class CValueObject;
|
||||||
|
|
||||||
|
template <class T> typename std::enable_if<std::is_base_of<CValueObject, T>::value, QDBusArgument>::type const &
|
||||||
|
operator>>(const QDBusArgument &argument, T &valueObject);
|
||||||
|
|
||||||
|
namespace Private
|
||||||
|
{
|
||||||
|
//! \private Abstract base class representing the set of operations supported by a particular value type.
|
||||||
|
struct IValueObjectMetaInfo
|
||||||
|
{
|
||||||
|
virtual ~IValueObjectMetaInfo() = default;
|
||||||
|
virtual QString toQString(const void *object, bool i18n) const = 0;
|
||||||
|
virtual QJsonObject toJson(const void *object) const = 0;
|
||||||
|
virtual void convertFromJson(const QJsonObject &json, void *object) const = 0;
|
||||||
|
virtual void unmarshall(const QDBusArgument &arg, void *object) const = 0;
|
||||||
|
virtual uint getValueHash(const void *object) const = 0;
|
||||||
|
virtual int getMetaTypeId() const = 0;
|
||||||
|
virtual const void *upCastTo(const void *object, int metaTypeId) const = 0;
|
||||||
|
virtual int compare(const void *lhs, const void *rhs) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
//! \private Implementation of IValueObjectMetaInfo representing the set of operations supported by T.
|
||||||
|
template <typename T>
|
||||||
|
struct CValueObjectMetaInfo : public IValueObjectMetaInfo
|
||||||
|
{
|
||||||
|
virtual QString toQString(const void *object, bool i18n) const override
|
||||||
|
{
|
||||||
|
return cast(object).toQString(i18n);
|
||||||
|
}
|
||||||
|
virtual QJsonObject toJson(const void *object) const override
|
||||||
|
{
|
||||||
|
return cast(object).toJson();
|
||||||
|
}
|
||||||
|
virtual void convertFromJson(const QJsonObject &json, void *object) const override
|
||||||
|
{
|
||||||
|
cast(object).convertFromJson(json);
|
||||||
|
}
|
||||||
|
virtual void unmarshall(const QDBusArgument &arg, void *object) const override
|
||||||
|
{
|
||||||
|
// FIXME Using the usual >> operator syntax here attempts to call the Container<T> overload in QtDBus/qdbusargument.h
|
||||||
|
BlackMisc::operator >>(arg, cast(object));
|
||||||
|
}
|
||||||
|
virtual uint getValueHash(const void *object) const override
|
||||||
|
{
|
||||||
|
return cast(object).getValueHash();
|
||||||
|
}
|
||||||
|
virtual int getMetaTypeId() const override
|
||||||
|
{
|
||||||
|
return maybeGetMetaTypeId(std::integral_constant<bool, QMetaTypeId<T>::Defined>{});
|
||||||
|
}
|
||||||
|
virtual const void *upCastTo(const void *object, int metaTypeId) const override
|
||||||
|
{
|
||||||
|
const auto base = static_cast<const void *>(static_cast<const typename T::base_type *>(&cast(object)));
|
||||||
|
return metaTypeId == getMetaTypeId() ? object : CValueObjectMetaInfo<typename T::base_type>{}.upCastTo(base, metaTypeId);
|
||||||
|
}
|
||||||
|
virtual int compare(const void *lhs, const void *rhs) const override; // FIXME defined out-of-line in valueobject.h because it uses CValueObject
|
||||||
|
|
||||||
|
static const T &cast(const void *object) { return *static_cast<const T *>(object); }
|
||||||
|
static T &cast(void *object) { return *static_cast<T *>(object); }
|
||||||
|
|
||||||
|
static int maybeGetMetaTypeId(std::true_type) { return qMetaTypeId<T>(); }
|
||||||
|
static int maybeGetMetaTypeId(std::false_type) { return QMetaType::UnknownType; }
|
||||||
|
};
|
||||||
|
|
||||||
|
//! \private Explicit specialization for the terminating case of the recursive CValueObjectMetaInfo::upCastTo.
|
||||||
|
template <>
|
||||||
|
inline const void *CValueObjectMetaInfo<CValueObject>::upCastTo(const void *, int) const
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! \private Getter to obtain the IValueObjectMetaInfo which was stored by BlackMisc::registerMetaValueType.
|
||||||
|
IValueObjectMetaInfo *getValueObjectMetaInfo(int typeId);
|
||||||
|
|
||||||
|
//! \private Getter to obtain the IValueObjectMetaInfo which was stored by BlackMisc::registerMetaValueType.
|
||||||
|
IValueObjectMetaInfo *getValueObjectMetaInfo(const QVariant &);
|
||||||
|
|
||||||
|
//! \private Getter to obtain the IValueObjectMetaInfo which was stored by BlackMisc::registerMetaValueType.
|
||||||
|
template <typename T>
|
||||||
|
IValueObjectMetaInfo *getValueObjectMetaInfo() { return getValueObjectMetaInfo(qMetaTypeId<T>()); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(BlackMisc::Private::IValueObjectMetaInfo *)
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -16,6 +16,15 @@
|
|||||||
|
|
||||||
namespace BlackMisc
|
namespace BlackMisc
|
||||||
{
|
{
|
||||||
|
Private::IValueObjectMetaInfo *Private::getValueObjectMetaInfo(int typeId)
|
||||||
|
{
|
||||||
|
return getValueObjectMetaInfo(QVariant(typeId, nullptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
Private::IValueObjectMetaInfo *Private::getValueObjectMetaInfo(const QVariant &v)
|
||||||
|
{
|
||||||
|
return v.value<IValueObjectMetaInfo *>();
|
||||||
|
}
|
||||||
|
|
||||||
void CVariant::registerMetadata()
|
void CVariant::registerMetadata()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ class QDBusArgument;
|
|||||||
|
|
||||||
namespace BlackMisc
|
namespace BlackMisc
|
||||||
{
|
{
|
||||||
// KB: Would it make sense to turn CVariant into an CValueObject? #307
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Wrapper class for QVariant, for more natural and transparent DBus integration.
|
* Wrapper class for QVariant, for more natural and transparent DBus integration.
|
||||||
|
|||||||
Reference in New Issue
Block a user