Automatically register data/debug stream operations in QMetaType
And remove the old manual registration code for those operators. Add some special handling for long/ulong, as these types could be streamed as a QVariant so far, but are not directly streamable through QDataStream. [ChangeLog][QtCore][QMetaType] The QMetaType::registerStreamOperators() and QMetaType::registerDebugStreamOperator() methods have been removed. The streaming operators for a type are now automatically registered together with the type registration. This implies that the operators should be visible wherever the type is visible and being used. [ChangeLog][Behavior Incompatible Changes] Because the QDataStream and QDebug serialization operators are automatically registered with QMetaType, the declarations of those functions must be present at any point where the type is used with QMetaType and QVariant. Change-Id: I4a0732651b20319af4a8397ff90b848ca4580d99 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
parent
5282545589
commit
ed8acbeb7c
@ -232,8 +232,6 @@ void CborDiagnosticDumper::saveFile(QIODevice *f, const QVariant &contents, cons
|
|||||||
CborConverter::CborConverter()
|
CborConverter::CborConverter()
|
||||||
{
|
{
|
||||||
qRegisterMetaType<QCborTag>();
|
qRegisterMetaType<QCborTag>();
|
||||||
qRegisterMetaTypeStreamOperators<QCborTag>();
|
|
||||||
QMetaType::registerDebugStreamOperator<QCborTag>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString CborConverter::name()
|
QString CborConverter::name()
|
||||||
|
@ -171,7 +171,6 @@ void DataStreamDumper::saveFile(QIODevice *f, const QVariant &contents, const QS
|
|||||||
DataStreamConverter::DataStreamConverter()
|
DataStreamConverter::DataStreamConverter()
|
||||||
{
|
{
|
||||||
qRegisterMetaType<VariantOrderedMap>();
|
qRegisterMetaType<VariantOrderedMap>();
|
||||||
qRegisterMetaTypeStreamOperators<VariantOrderedMap>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString DataStreamConverter::name()
|
QString DataStreamConverter::name()
|
||||||
|
@ -71,6 +71,7 @@ qt_add_tool(${target_name}
|
|||||||
../src/corelib/plugin/quuid.cpp ../src/corelib/plugin/quuid.h
|
../src/corelib/plugin/quuid.cpp ../src/corelib/plugin/quuid.h
|
||||||
../src/corelib/serialization/qcborstreamwriter.cpp ../src/corelib/serialization/qcborstreamwriter.h
|
../src/corelib/serialization/qcborstreamwriter.cpp ../src/corelib/serialization/qcborstreamwriter.h
|
||||||
../src/corelib/serialization/qcborvalue.cpp ../src/corelib/serialization/qcborvalue.h ../src/corelib/serialization/qcborvalue_p.h
|
../src/corelib/serialization/qcborvalue.cpp ../src/corelib/serialization/qcborvalue.h ../src/corelib/serialization/qcborvalue_p.h
|
||||||
|
../src/corelib/serialization/qdatastream.cpp ../src/corelib/serialization/qdatastream.h
|
||||||
../src/corelib/serialization/qjson_p.h
|
../src/corelib/serialization/qjson_p.h
|
||||||
../src/corelib/serialization/qjsonarray.cpp ../src/corelib/serialization/qjsonarray.h
|
../src/corelib/serialization/qjsonarray.cpp ../src/corelib/serialization/qjsonarray.h
|
||||||
../src/corelib/serialization/qjsoncbor.cpp
|
../src/corelib/serialization/qjsoncbor.cpp
|
||||||
|
@ -97,11 +97,6 @@ qRegisterMetaType<MyClass>("MyClass");
|
|||||||
//! [4]
|
//! [4]
|
||||||
|
|
||||||
|
|
||||||
//! [5]
|
|
||||||
qRegisterMetaTypeStreamOperators<MyClass>("MyClass");
|
|
||||||
//! [5]
|
|
||||||
|
|
||||||
|
|
||||||
//! [6]
|
//! [6]
|
||||||
QDataStream &operator<<(QDataStream &out, const MyClass &myObj);
|
QDataStream &operator<<(QDataStream &out, const MyClass &myObj);
|
||||||
QDataStream &operator>>(QDataStream &in, MyClass &myObj);
|
QDataStream &operator>>(QDataStream &in, MyClass &myObj);
|
||||||
|
@ -1979,8 +1979,9 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile,
|
|||||||
|
|
||||||
\snippet code/src_corelib_io_qsettings.cpp 1
|
\snippet code/src_corelib_io_qsettings.cpp 1
|
||||||
|
|
||||||
Custom types registered using qRegisterMetaType() and
|
Custom types registered using qRegisterMetaType() that have
|
||||||
qRegisterMetaTypeStreamOperators() can be stored using QSettings.
|
operators for streaming to and from a QDataStream can be stored
|
||||||
|
using QSettings.
|
||||||
|
|
||||||
\section1 Section and Key Syntax
|
\section1 Section and Key Syntax
|
||||||
|
|
||||||
|
@ -105,14 +105,6 @@ struct QMetaTypeCustomRegistry
|
|||||||
QReadWriteLock lock;
|
QReadWriteLock lock;
|
||||||
QList<QtPrivate::QMetaTypeInterface *> registry;
|
QList<QtPrivate::QMetaTypeInterface *> registry;
|
||||||
QHash<QByteArray, QtPrivate::QMetaTypeInterface *> aliases;
|
QHash<QByteArray, QtPrivate::QMetaTypeInterface *> aliases;
|
||||||
#ifndef QT_NO_DATASTREAM
|
|
||||||
struct DataStreamOps
|
|
||||||
{
|
|
||||||
QMetaType::SaveOperator saveOp;
|
|
||||||
QMetaType::LoadOperator loadOp;
|
|
||||||
};
|
|
||||||
QHash<int, DataStreamOps> dataStreamOp;
|
|
||||||
#endif
|
|
||||||
// index of first empty (unregistered) type in registry, if any.
|
// index of first empty (unregistered) type in registry, if any.
|
||||||
int firstEmpty = 0;
|
int firstEmpty = 0;
|
||||||
|
|
||||||
@ -246,6 +238,15 @@ Q_GLOBAL_STATIC(QMetaTypeCustomRegistry, customTypeRegistry)
|
|||||||
\li Classes that have a Q_GADGET macro
|
\li Classes that have a Q_GADGET macro
|
||||||
\endlist
|
\endlist
|
||||||
|
|
||||||
|
\note This method also registers the stream and debug operators for the type if they
|
||||||
|
are visible at registration time. As this is done automatically in some places,
|
||||||
|
it is strongly recommended to declare the stream operators for a type directly
|
||||||
|
after the type itself.
|
||||||
|
|
||||||
|
The stream operators should have the following signatures:
|
||||||
|
|
||||||
|
\snippet code/src_corelib_kernel_qmetatype.cpp 6
|
||||||
|
|
||||||
\sa qRegisterMetaType()
|
\sa qRegisterMetaType()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -902,11 +903,8 @@ private:
|
|||||||
|
|
||||||
typedef QMetaTypeFunctionRegistry<QtPrivate::AbstractConverterFunction,QPair<int,int> >
|
typedef QMetaTypeFunctionRegistry<QtPrivate::AbstractConverterFunction,QPair<int,int> >
|
||||||
QMetaTypeConverterRegistry;
|
QMetaTypeConverterRegistry;
|
||||||
typedef QMetaTypeFunctionRegistry<QtPrivate::AbstractDebugStreamFunction,int>
|
|
||||||
QMetaTypeDebugStreamRegistry;
|
|
||||||
|
|
||||||
Q_GLOBAL_STATIC(QMetaTypeConverterRegistry, customTypesConversionRegistry)
|
Q_GLOBAL_STATIC(QMetaTypeConverterRegistry, customTypesConversionRegistry)
|
||||||
Q_GLOBAL_STATIC(QMetaTypeDebugStreamRegistry, customTypesDebugStreamRegistry)
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\fn bool QMetaType::registerConverter()
|
\fn bool QMetaType::registerConverter()
|
||||||
@ -939,15 +937,6 @@ Q_GLOBAL_STATIC(QMetaTypeDebugStreamRegistry, customTypesDebugStreamRegistry)
|
|||||||
to type To in the meta type system. Returns \c true if the registration succeeded, otherwise false.
|
to type To in the meta type system. Returns \c true if the registration succeeded, otherwise false.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef QT_NO_DEBUG_STREAM
|
|
||||||
/*!
|
|
||||||
\fn bool QMetaType::registerDebugStreamOperator()
|
|
||||||
Registers the debug stream operator for the user-registered type T. This requires T to have
|
|
||||||
an operator<<(QDebug dbg, T).
|
|
||||||
Returns \c true if the registration succeeded, otherwise false.
|
|
||||||
*/
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Registers function \a f as converter function from type id \a from to \a to.
|
Registers function \a f as converter function from type id \a from to \a to.
|
||||||
If there's already a conversion registered, this does nothing but deleting \a f.
|
If there's already a conversion registered, this does nothing but deleting \a f.
|
||||||
@ -978,30 +967,54 @@ void QMetaType::unregisterConverterFunction(int from, int to)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef QT_NO_DEBUG_STREAM
|
#ifndef QT_NO_DEBUG_STREAM
|
||||||
bool QMetaType::registerDebugStreamOperatorFunction(const QtPrivate::AbstractDebugStreamFunction *f,
|
|
||||||
int type)
|
/*!
|
||||||
|
Streams the object at \a rhs of type \a typeId to the debug stream \a dbg. Returns \c true
|
||||||
|
on success, otherwise false.
|
||||||
|
\since 5.2
|
||||||
|
*/
|
||||||
|
bool QMetaType::debugStream(QDebug& dbg, const void *rhs)
|
||||||
{
|
{
|
||||||
if (!customTypesDebugStreamRegistry()->insertIfNotContains(type, f)) {
|
if (!isValid() || !d_ptr->debugStream)
|
||||||
qWarning("Debug stream operator already registered for type %s", QMetaType::typeName(type));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
d_ptr->debugStream(d_ptr, dbg, rhs);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\fn bool QMetaType::debugStream(QDebug& dbg, const void *rhs, int typeId)
|
||||||
|
\overload
|
||||||
|
\obsolete
|
||||||
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\fn bool QMetaType::hasRegisteredDebugStreamOperator()
|
\fn bool QMetaType::hasRegisteredDebugStreamOperator()
|
||||||
Returns \c true, if the meta type system has a registered debug stream operator for type T.
|
\obsolete
|
||||||
\since 5.2
|
\since 5.2
|
||||||
|
|
||||||
|
Returns \c true, if the meta type system has a registered debug stream operator for type T.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
\fn bool QMetaType::hasRegisteredDebugStreamOperator(int typeId)
|
||||||
|
\obsolete
|
||||||
|
|
||||||
Returns \c true, if the meta type system has a registered debug stream operator for type
|
Returns \c true, if the meta type system has a registered debug stream operator for type
|
||||||
id \a typeId.
|
id \a typeId.
|
||||||
\since 5.2
|
\since 5.2
|
||||||
*/
|
*/
|
||||||
bool QMetaType::hasRegisteredDebugStreamOperator(int typeId)
|
|
||||||
|
/*!
|
||||||
|
\fn bool QMetaType::hasRegisteredDebugStreamOperator(int typeId)
|
||||||
|
\since 6.0
|
||||||
|
|
||||||
|
Returns \c true, if the meta type system has a registered debug stream operator for this
|
||||||
|
meta type.
|
||||||
|
*/
|
||||||
|
bool QMetaType::hasRegisteredDebugStreamOperator() const
|
||||||
|
|
||||||
{
|
{
|
||||||
return customTypesDebugStreamRegistry()->contains(typeId);
|
return d_ptr && d_ptr->debugStream != nullptr;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1017,20 +1030,6 @@ bool QMetaType::convert(const void *from, int fromTypeId, void *to, int toTypeId
|
|||||||
return f && f->convert(f, from, to);
|
return f && f->convert(f, from, to);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
|
||||||
Streams the object at \a rhs of type \a typeId to the debug stream \a dbg. Returns \c true
|
|
||||||
on success, otherwise false.
|
|
||||||
\since 5.2
|
|
||||||
*/
|
|
||||||
bool QMetaType::debugStream(QDebug& dbg, const void *rhs, int typeId)
|
|
||||||
{
|
|
||||||
const QtPrivate::AbstractDebugStreamFunction * const f = customTypesDebugStreamRegistry()->function(typeId);
|
|
||||||
if (!f)
|
|
||||||
return false;
|
|
||||||
f->stream(f, dbg, rhs);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\fn bool QMetaType::hasRegisteredConverterFunction()
|
\fn bool QMetaType::hasRegisteredConverterFunction()
|
||||||
Returns \c true, if the meta type system has a registered conversion from type From to type To.
|
Returns \c true, if the meta type system has a registered conversion from type From to type To.
|
||||||
@ -1048,32 +1047,6 @@ bool QMetaType::hasRegisteredConverterFunction(int fromTypeId, int toTypeId)
|
|||||||
return customTypesConversionRegistry()->contains(qMakePair(fromTypeId, toTypeId));
|
return customTypesConversionRegistry()->contains(qMakePair(fromTypeId, toTypeId));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef QT_NO_DATASTREAM
|
|
||||||
/*!
|
|
||||||
\internal
|
|
||||||
*/
|
|
||||||
void QMetaType::registerStreamOperators(const char *typeName, SaveOperator saveOp,
|
|
||||||
LoadOperator loadOp)
|
|
||||||
{
|
|
||||||
registerStreamOperators(type(typeName), saveOp, loadOp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\internal
|
|
||||||
*/
|
|
||||||
void QMetaType::registerStreamOperators(int idx, SaveOperator saveOp,
|
|
||||||
LoadOperator loadOp)
|
|
||||||
{
|
|
||||||
if (idx < User)
|
|
||||||
return; //builtin types should not be registered;
|
|
||||||
|
|
||||||
if (auto reg = customTypeRegistry()) {
|
|
||||||
QWriteLocker locker(®->lock);
|
|
||||||
reg->dataStreamOp[idx] = { saveOp, loadOp };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // QT_NO_DATASTREAM
|
|
||||||
|
|
||||||
// We don't officially support constexpr in MSVC 2015, but the limited support it
|
// We don't officially support constexpr in MSVC 2015, but the limited support it
|
||||||
// has is enough for the code below.
|
// has is enough for the code below.
|
||||||
|
|
||||||
@ -1315,218 +1288,90 @@ int QMetaType::type(const QT_PREPEND_NAMESPACE(QByteArray) &typeName)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef QT_NO_DATASTREAM
|
#ifndef QT_NO_DATASTREAM
|
||||||
namespace
|
|
||||||
{
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
class HasStreamOperator
|
|
||||||
{
|
|
||||||
struct Yes { char unused[1]; };
|
|
||||||
struct No { char unused[2]; };
|
|
||||||
static_assert(sizeof(Yes) != sizeof(No));
|
|
||||||
|
|
||||||
template<class C> static decltype(std::declval<QDataStream&>().operator>>(std::declval<C&>()), Yes()) load(int);
|
|
||||||
template<class C> static decltype(operator>>(std::declval<QDataStream&>(), std::declval<C&>()), Yes()) load(int);
|
|
||||||
template<class C> static No load(...);
|
|
||||||
template<class C> static decltype(operator<<(std::declval<QDataStream&>(), std::declval<const C&>()), Yes()) saveFunction(int);
|
|
||||||
template<class C> static decltype(std::declval<QDataStream&>().operator<<(std::declval<const C&>()), Yes()) saveMethod(int);
|
|
||||||
template<class C> static No saveMethod(...);
|
|
||||||
template<class C> static No saveFunction(...);
|
|
||||||
static constexpr bool LoadValue = QtMetaTypePrivate::TypeDefinition<T>::IsAvailable && (sizeof(load<T>(0)) == sizeof(Yes));
|
|
||||||
static constexpr bool SaveValue = QtMetaTypePrivate::TypeDefinition<T>::IsAvailable &&
|
|
||||||
((sizeof(saveMethod<T>(0)) == sizeof(Yes)) || (sizeof(saveFunction<T>(0)) == sizeof(Yes)));
|
|
||||||
public:
|
|
||||||
static constexpr bool Value = LoadValue && SaveValue;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Quick sanity checks
|
|
||||||
static_assert(HasStreamOperator<NS(QJsonDocument)>::Value);
|
|
||||||
static_assert(!HasStreamOperator<void*>::Value);
|
|
||||||
static_assert(HasStreamOperator<qint8>::Value);
|
|
||||||
|
|
||||||
template<typename T, bool IsAcceptedType = DefinedTypesFilter::Acceptor<T>::IsAccepted && HasStreamOperator<T>::Value>
|
|
||||||
struct FilteredOperatorSwitch
|
|
||||||
{
|
|
||||||
static bool load(QDataStream &stream, T *data, int)
|
|
||||||
{
|
|
||||||
stream >> *data;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
static bool save(QDataStream &stream, const T *data, int)
|
|
||||||
{
|
|
||||||
stream << *data;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
struct FilteredOperatorSwitch<T, /* IsAcceptedType = */ false>
|
|
||||||
{
|
|
||||||
static const QMetaTypeModuleHelper *getMetaTypeInterface()
|
|
||||||
{
|
|
||||||
if (QModulesPrivate::QTypeModuleInfo<T>::IsGui)
|
|
||||||
return qMetaTypeGuiHelper;
|
|
||||||
else if (QModulesPrivate::QTypeModuleInfo<T>::IsWidget)
|
|
||||||
return qMetaTypeWidgetsHelper;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
static bool save(QDataStream &stream, const T *data, int type)
|
|
||||||
{
|
|
||||||
if (auto interface = getMetaTypeInterface()) {
|
|
||||||
return interface->save(stream, type, data);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
static bool load(QDataStream &stream, T *data, int type)
|
|
||||||
{
|
|
||||||
if (auto interface = getMetaTypeInterface()) {
|
|
||||||
return interface->load(stream, type, data);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class SaveOperatorSwitch
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
QDataStream &stream;
|
|
||||||
int m_type;
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
bool delegate(const T *data)
|
|
||||||
{
|
|
||||||
return FilteredOperatorSwitch<T>::save(stream, data, m_type);
|
|
||||||
}
|
|
||||||
bool delegate(const char *data)
|
|
||||||
{
|
|
||||||
// force a char to be signed
|
|
||||||
stream << qint8(*data);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
bool delegate(const long *data)
|
|
||||||
{
|
|
||||||
stream << qlonglong(*data);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
bool delegate(const unsigned long *data)
|
|
||||||
{
|
|
||||||
stream << qulonglong(*data);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
bool delegate(const QMetaTypeSwitcher::NotBuiltinType *data)
|
|
||||||
{
|
|
||||||
auto ct = customTypeRegistry();
|
|
||||||
if (!ct)
|
|
||||||
return false;
|
|
||||||
QMetaType::SaveOperator op = nullptr;
|
|
||||||
{
|
|
||||||
QReadLocker lock(&ct->lock);
|
|
||||||
op = ct->dataStreamOp.value(m_type).saveOp;
|
|
||||||
}
|
|
||||||
if (!op)
|
|
||||||
return false;
|
|
||||||
op(stream, data);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
bool delegate(const void*) { return false; }
|
|
||||||
bool delegate(const QMetaTypeSwitcher::UnknownType*) { return false; }
|
|
||||||
};
|
|
||||||
class LoadOperatorSwitch
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
QDataStream &stream;
|
|
||||||
int m_type;
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
bool delegate(const T *data)
|
|
||||||
{
|
|
||||||
return FilteredOperatorSwitch<T>::load(stream, const_cast<T*>(data), m_type);
|
|
||||||
}
|
|
||||||
bool delegate(const char *data)
|
|
||||||
{
|
|
||||||
// force a char to be signed
|
|
||||||
qint8 c;
|
|
||||||
stream >> c;
|
|
||||||
*const_cast<char*>(data) = c;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
bool delegate(const long *data)
|
|
||||||
{
|
|
||||||
qlonglong l;
|
|
||||||
stream >> l;
|
|
||||||
*const_cast<long*>(data) = l;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
bool delegate(const unsigned long *data)
|
|
||||||
{
|
|
||||||
qlonglong l;
|
|
||||||
stream >> l;
|
|
||||||
*const_cast<unsigned long*>(data) = l;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
bool delegate(const QMetaTypeSwitcher::NotBuiltinType *data)
|
|
||||||
{
|
|
||||||
auto ct = customTypeRegistry();
|
|
||||||
if (!ct)
|
|
||||||
return false;
|
|
||||||
QMetaType::LoadOperator op = nullptr;
|
|
||||||
{
|
|
||||||
QReadLocker lock(&ct->lock);
|
|
||||||
op = ct->dataStreamOp.value(m_type).loadOp;
|
|
||||||
}
|
|
||||||
if (!op)
|
|
||||||
return false;
|
|
||||||
op(stream, const_cast<QMetaTypeSwitcher::NotBuiltinType *>(data));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
bool delegate(const void*) { return false; }
|
|
||||||
bool delegate(const QMetaTypeSwitcher::UnknownType*) { return false; }
|
|
||||||
};
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Writes the object pointed to by \a data with the ID \a type to
|
Writes the object pointed to by \a data with the ID \a type to
|
||||||
the given \a stream. Returns \c true if the object is saved
|
the given \a stream. Returns \c true if the object is saved
|
||||||
successfully; otherwise returns \c false.
|
successfully; otherwise returns \c false.
|
||||||
|
|
||||||
The type must have been registered with qRegisterMetaType() and
|
The type must have been registered with Q_DECLARE_METATYPE()
|
||||||
qRegisterMetaTypeStreamOperators() beforehand.
|
beforehand.
|
||||||
|
|
||||||
Normally, you should not need to call this function directly.
|
Normally, you should not need to call this function directly.
|
||||||
Instead, use QVariant's \c operator<<(), which relies on save()
|
Instead, use QVariant's \c operator<<(), which relies on save()
|
||||||
to stream custom types.
|
to stream custom types.
|
||||||
|
|
||||||
\sa load(), qRegisterMetaTypeStreamOperators()
|
\sa load()
|
||||||
*/
|
*/
|
||||||
bool QMetaType::save(QDataStream &stream, int type, const void *data)
|
bool QMetaType::save(QDataStream &stream, const void *data) const
|
||||||
{
|
{
|
||||||
if (!data)
|
if (!data || !isValid())
|
||||||
return false;
|
return false;
|
||||||
SaveOperatorSwitch saveOp{stream, type};
|
|
||||||
return QMetaTypeSwitcher::switcher<bool>(saveOp, type, data);
|
// keep compatibility for long/ulong
|
||||||
|
if (id() == QMetaType::Long) {
|
||||||
|
stream << qlonglong(*(long *)data);
|
||||||
|
return true;
|
||||||
|
} else if (id() == QMetaType::ULong) {
|
||||||
|
stream << qlonglong(*(unsigned long *)data);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!d_ptr->dataStreamOut)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
d_ptr->dataStreamOut(d_ptr, stream, data);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\fn bool QMetaType::save(QDataStream &stream, int type, const void *data)
|
||||||
|
\overload
|
||||||
|
\obsolete
|
||||||
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Reads the object of the specified \a type from the given \a
|
Reads the object of the specified \a type from the given \a
|
||||||
stream into \a data. Returns \c true if the object is loaded
|
stream into \a data. Returns \c true if the object is loaded
|
||||||
successfully; otherwise returns \c false.
|
successfully; otherwise returns \c false.
|
||||||
|
|
||||||
The type must have been registered with qRegisterMetaType() and
|
The type must have been registered with Q_DECLARE_METATYPE()
|
||||||
qRegisterMetaTypeStreamOperators() beforehand.
|
beforehand.
|
||||||
|
|
||||||
Normally, you should not need to call this function directly.
|
Normally, you should not need to call this function directly.
|
||||||
Instead, use QVariant's \c operator>>(), which relies on load()
|
Instead, use QVariant's \c operator>>(), which relies on load()
|
||||||
to stream custom types.
|
to stream custom types.
|
||||||
|
|
||||||
\sa save(), qRegisterMetaTypeStreamOperators()
|
\sa save()
|
||||||
*/
|
*/
|
||||||
bool QMetaType::load(QDataStream &stream, int type, void *data)
|
bool QMetaType::load(QDataStream &stream, void *data) const
|
||||||
{
|
{
|
||||||
if (!data)
|
if (!data || !isValid())
|
||||||
return false;
|
return false;
|
||||||
LoadOperatorSwitch loadOp{stream, type};
|
|
||||||
return QMetaTypeSwitcher::switcher<bool>(loadOp, type, data);
|
// keep compatibility for long/ulong
|
||||||
|
if (id() == QMetaType::Long) {
|
||||||
|
qlonglong ll;
|
||||||
|
stream >> ll;
|
||||||
|
*(long *)data = long(ll);
|
||||||
|
return true;
|
||||||
|
} else if (id() == QMetaType::ULong) {
|
||||||
|
qulonglong ull;
|
||||||
|
stream >> ull;
|
||||||
|
*(unsigned long *)data = (unsigned long)(ull);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!d_ptr->dataStreamIn)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
d_ptr->dataStreamIn(d_ptr, stream, data);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\fn bool QMetaType::load(QDataStream &stream, int type, void *data)
|
||||||
|
\overload
|
||||||
|
\obsolete
|
||||||
|
*/
|
||||||
#endif // QT_NO_DATASTREAM
|
#endif // QT_NO_DATASTREAM
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -1668,29 +1513,7 @@ const QMetaObject *QMetaType::metaObjectForType(int type)
|
|||||||
\warning This function is useful only for registering an alias (typedef)
|
\warning This function is useful only for registering an alias (typedef)
|
||||||
for every other use case Q_DECLARE_METATYPE and qMetaTypeId() should be used instead.
|
for every other use case Q_DECLARE_METATYPE and qMetaTypeId() should be used instead.
|
||||||
|
|
||||||
\sa {QMetaType::}{qRegisterMetaTypeStreamOperators()}, {QMetaType::}{isRegistered()},
|
\sa {QMetaType::}{isRegistered()}, Q_DECLARE_METATYPE()
|
||||||
Q_DECLARE_METATYPE()
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn void qRegisterMetaTypeStreamOperators(const char *typeName)
|
|
||||||
\relates QMetaType
|
|
||||||
\threadsafe
|
|
||||||
|
|
||||||
Registers the stream operators for the type \c{T} called \a
|
|
||||||
typeName.
|
|
||||||
|
|
||||||
Afterward, the type can be streamed using QMetaType::load() and
|
|
||||||
QMetaType::save(). These functions are used when streaming a
|
|
||||||
QVariant.
|
|
||||||
|
|
||||||
\snippet code/src_corelib_kernel_qmetatype.cpp 5
|
|
||||||
|
|
||||||
The stream operators should have the following signatures:
|
|
||||||
|
|
||||||
\snippet code/src_corelib_kernel_qmetatype.cpp 6
|
|
||||||
|
|
||||||
\sa qRegisterMetaType(), QMetaType::isRegistered(), Q_DECLARE_METATYPE()
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -249,7 +249,6 @@ inline constexpr int qMetaTypeId();
|
|||||||
F(QPointer)
|
F(QPointer)
|
||||||
|
|
||||||
class QDataStream;
|
class QDataStream;
|
||||||
class QMetaTypeInterface;
|
|
||||||
struct QMetaObject;
|
struct QMetaObject;
|
||||||
|
|
||||||
namespace QtPrivate
|
namespace QtPrivate
|
||||||
@ -267,36 +266,6 @@ To convertImplicit(const From& from)
|
|||||||
return from;
|
return from;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef QT_NO_DEBUG_STREAM
|
|
||||||
struct AbstractDebugStreamFunction
|
|
||||||
{
|
|
||||||
typedef void (*Stream)(const AbstractDebugStreamFunction *, QDebug&, const void *);
|
|
||||||
typedef void (*Destroy)(AbstractDebugStreamFunction *);
|
|
||||||
explicit AbstractDebugStreamFunction(Stream s = nullptr, Destroy d = nullptr)
|
|
||||||
: stream(s), destroy(d) {}
|
|
||||||
Q_DISABLE_COPY(AbstractDebugStreamFunction)
|
|
||||||
Stream stream;
|
|
||||||
Destroy destroy;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
struct BuiltInDebugStreamFunction : public AbstractDebugStreamFunction
|
|
||||||
{
|
|
||||||
BuiltInDebugStreamFunction()
|
|
||||||
: AbstractDebugStreamFunction(stream, destroy) {}
|
|
||||||
static void stream(const AbstractDebugStreamFunction *, QDebug& dbg, const void *r)
|
|
||||||
{
|
|
||||||
const T *rhs = static_cast<const T *>(r);
|
|
||||||
operator<<(dbg, *rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void destroy(AbstractDebugStreamFunction *_this)
|
|
||||||
{
|
|
||||||
delete static_cast<BuiltInDebugStreamFunction *>(_this);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct AbstractConverterFunction
|
struct AbstractConverterFunction
|
||||||
{
|
{
|
||||||
typedef bool (*Converter)(const AbstractConverterFunction *, const void *, void*);
|
typedef bool (*Converter)(const AbstractConverterFunction *, const void *, void*);
|
||||||
@ -461,14 +430,6 @@ public:
|
|||||||
};
|
};
|
||||||
Q_DECLARE_FLAGS(TypeFlags, TypeFlag)
|
Q_DECLARE_FLAGS(TypeFlags, TypeFlag)
|
||||||
|
|
||||||
typedef void (*SaveOperator)(QDataStream &, const void *);
|
|
||||||
typedef void (*LoadOperator)(QDataStream &, void *);
|
|
||||||
#ifndef QT_NO_DATASTREAM
|
|
||||||
static void registerStreamOperators(const char *typeName, SaveOperator saveOp,
|
|
||||||
LoadOperator loadOp);
|
|
||||||
static void registerStreamOperators(int type, SaveOperator saveOp,
|
|
||||||
LoadOperator loadOp);
|
|
||||||
#endif
|
|
||||||
static void registerNormalizedTypedef(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName, QMetaType type);
|
static void registerNormalizedTypedef(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName, QMetaType type);
|
||||||
|
|
||||||
static int type(const char *typeName);
|
static int type(const char *typeName);
|
||||||
@ -484,11 +445,6 @@ public:
|
|||||||
static void *construct(int type, void *where, const void *copy);
|
static void *construct(int type, void *where, const void *copy);
|
||||||
static void destruct(int type, void *where);
|
static void destruct(int type, void *where);
|
||||||
|
|
||||||
#ifndef QT_NO_DATASTREAM
|
|
||||||
static bool save(QDataStream &stream, int type, const void *data);
|
|
||||||
static bool load(QDataStream &stream, int type, void *data);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
explicit QMetaType(int type);
|
explicit QMetaType(int type);
|
||||||
explicit QMetaType(QtPrivate::QMetaTypeInterface *d);
|
explicit QMetaType(QtPrivate::QMetaTypeInterface *d);
|
||||||
constexpr QMetaType() : d_ptr(nullptr) {}
|
constexpr QMetaType() : d_ptr(nullptr) {}
|
||||||
@ -521,6 +477,20 @@ public:
|
|||||||
bool isEqualityComparable() const;
|
bool isEqualityComparable() const;
|
||||||
bool isOrdered() const;
|
bool isOrdered() const;
|
||||||
|
|
||||||
|
#ifndef QT_NO_DATASTREAM
|
||||||
|
bool save(QDataStream &stream, const void *data) const;
|
||||||
|
bool load(QDataStream &stream, void *data) const;
|
||||||
|
|
||||||
|
#if QT_DEPRECATED_SINCE(6, 0)
|
||||||
|
QT_DEPRECATED_VERSION_6_0
|
||||||
|
static bool save(QDataStream &stream, int type, const void *data)
|
||||||
|
{ return QMetaType(type).save(stream, data); }
|
||||||
|
QT_DEPRECATED_VERSION_6_0
|
||||||
|
static bool load(QDataStream &stream, int type, void *data)
|
||||||
|
{ return QMetaType(type).load(stream, data); }
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static QMetaType fromType();
|
static QMetaType fromType();
|
||||||
|
|
||||||
@ -530,22 +500,21 @@ public:
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
#ifndef QT_NO_DEBUG_STREAM
|
#ifndef QT_NO_DEBUG_STREAM
|
||||||
template<typename T>
|
bool debugStream(QDebug& dbg, const void *rhs);
|
||||||
static bool registerDebugStreamOperator()
|
bool hasRegisteredDebugStreamOperator() const;
|
||||||
{
|
|
||||||
static_assert((!QMetaTypeId2<T>::IsBuiltIn),
|
|
||||||
"QMetaType::registerDebugStreamOperator: The type must be a custom type.");
|
|
||||||
|
|
||||||
const int typeId = qMetaTypeId<T>();
|
#if QT_DEPRECATED_SINCE(6, 0)
|
||||||
static const QtPrivate::BuiltInDebugStreamFunction<T> f;
|
QT_DEPRECATED_VERSION_6_0
|
||||||
return registerDebugStreamOperatorFunction(&f, typeId);
|
static bool debugStream(QDebug& dbg, const void *rhs, int typeId)
|
||||||
}
|
{ return QMetaType(typeId).debugStream(dbg, rhs); }
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
QT_DEPRECATED_VERSION_6_0
|
||||||
static bool hasRegisteredDebugStreamOperator()
|
static bool hasRegisteredDebugStreamOperator()
|
||||||
{
|
{ return QMetaType::fromType<T>().hasRegisteredDebugStreamOperator(); }
|
||||||
return hasRegisteredDebugStreamOperator(qMetaTypeId<T>());
|
QT_DEPRECATED_VERSION_6_0
|
||||||
}
|
static bool hasRegisteredDebugStreamOperator(int typeId)
|
||||||
static bool hasRegisteredDebugStreamOperator(int typeId);
|
{ return QMetaType(typeId).hasRegisteredDebugStreamOperator(); }
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// implicit conversion supported like double -> float
|
// implicit conversion supported like double -> float
|
||||||
@ -628,8 +597,6 @@ public:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static bool debugStream(QDebug& dbg, const void *rhs, int typeId);
|
|
||||||
|
|
||||||
template<typename From, typename To>
|
template<typename From, typename To>
|
||||||
static bool hasRegisteredConverterFunction()
|
static bool hasRegisteredConverterFunction()
|
||||||
{
|
{
|
||||||
@ -638,10 +605,6 @@ public:
|
|||||||
|
|
||||||
static bool hasRegisteredConverterFunction(int fromTypeId, int toTypeId);
|
static bool hasRegisteredConverterFunction(int fromTypeId, int toTypeId);
|
||||||
|
|
||||||
#ifndef QT_NO_DEBUG_STREAM
|
|
||||||
static bool registerDebugStreamOperatorFunction(const QtPrivate::AbstractDebugStreamFunction *f, int type);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef Q_CLANG_QDOC
|
#ifndef Q_CLANG_QDOC
|
||||||
template<typename, bool> friend struct QtPrivate::ValueTypeIsMetaType;
|
template<typename, bool> friend struct QtPrivate::ValueTypeIsMetaType;
|
||||||
template<typename, typename> friend struct QtPrivate::ConverterMemberFunction;
|
template<typename, typename> friend struct QtPrivate::ConverterMemberFunction;
|
||||||
@ -1751,20 +1714,6 @@ int qRegisterMetaType(const char *typeName
|
|||||||
return qRegisterNormalizedMetaType<T>(normalizedTypeName, dummy, defined);
|
return qRegisterNormalizedMetaType<T>(normalizedTypeName, dummy, defined);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef QT_NO_DATASTREAM
|
|
||||||
template <typename T>
|
|
||||||
void qRegisterMetaTypeStreamOperators(const char *typeName
|
|
||||||
#ifndef Q_CLANG_QDOC
|
|
||||||
, T * /* dummy */ = nullptr
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
{
|
|
||||||
qRegisterMetaType<T>(typeName);
|
|
||||||
QMetaType::registerStreamOperators(typeName, QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Save,
|
|
||||||
QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Load);
|
|
||||||
}
|
|
||||||
#endif // QT_NO_DATASTREAM
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline constexpr int qMetaTypeId()
|
inline constexpr int qMetaTypeId()
|
||||||
{
|
{
|
||||||
@ -1889,17 +1838,6 @@ struct QMetaTypeIdQObject<T, QMetaType::IsEnumeration>
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef QT_NO_DATASTREAM
|
|
||||||
template <typename T>
|
|
||||||
inline int qRegisterMetaTypeStreamOperators()
|
|
||||||
{
|
|
||||||
int id = qMetaTypeId<T>();
|
|
||||||
QMetaType::registerStreamOperators(id, QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Save,
|
|
||||||
QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Load);
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define Q_DECLARE_OPAQUE_POINTER(POINTER) \
|
#define Q_DECLARE_OPAQUE_POINTER(POINTER) \
|
||||||
QT_BEGIN_NAMESPACE namespace QtPrivate { \
|
QT_BEGIN_NAMESPACE namespace QtPrivate { \
|
||||||
template <> \
|
template <> \
|
||||||
@ -2245,6 +2183,12 @@ public:
|
|||||||
EqualsFn equals;
|
EqualsFn equals;
|
||||||
using LessThanFn = bool (*)(const QMetaTypeInterface *, const void *, const void *);
|
using LessThanFn = bool (*)(const QMetaTypeInterface *, const void *, const void *);
|
||||||
LessThanFn lessThan;
|
LessThanFn lessThan;
|
||||||
|
using DebugStreamFn = void (*)(const QMetaTypeInterface *, QDebug &, const void *);
|
||||||
|
DebugStreamFn debugStream;
|
||||||
|
using DataStreamOutFn = void (*)(const QMetaTypeInterface *, QDataStream &, const void *);
|
||||||
|
DataStreamOutFn dataStreamOut;
|
||||||
|
using DataStreamInFn = void (*)(const QMetaTypeInterface *, QDataStream &, void *);
|
||||||
|
DataStreamInFn dataStreamIn;
|
||||||
|
|
||||||
using LegacyRegisterOp = void (*)();
|
using LegacyRegisterOp = void (*)();
|
||||||
LegacyRegisterOp legacyRegisterOp;
|
LegacyRegisterOp legacyRegisterOp;
|
||||||
@ -2692,6 +2636,35 @@ struct QLessThanOperatorForType <T, false>
|
|||||||
static constexpr QMetaTypeInterface::LessThanFn lessThan = nullptr;
|
static constexpr QMetaTypeInterface::LessThanFn lessThan = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T, bool = QTypeTraits::has_ostream_operator_v<QDebug, T>>
|
||||||
|
struct QDebugStreamOperatorForType
|
||||||
|
{
|
||||||
|
static void debugStream(const QMetaTypeInterface *, QDebug &dbg, const void *a)
|
||||||
|
{ dbg << *reinterpret_cast<const T *>(a); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct QDebugStreamOperatorForType <T, false>
|
||||||
|
{
|
||||||
|
static constexpr QMetaTypeInterface::DebugStreamFn debugStream = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, bool = QTypeTraits::has_stream_operator_v<QDataStream, T>>
|
||||||
|
struct QDataStreamOperatorForType
|
||||||
|
{
|
||||||
|
static void dataStreamOut(const QMetaTypeInterface *, QDataStream &ds, const void *a)
|
||||||
|
{ ds << *reinterpret_cast<const T *>(a); }
|
||||||
|
static void dataStreamIn(const QMetaTypeInterface *, QDataStream &ds, void *a)
|
||||||
|
{ ds >> *reinterpret_cast<T *>(a); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct QDataStreamOperatorForType <T, false>
|
||||||
|
{
|
||||||
|
static constexpr QMetaTypeInterface::DataStreamOutFn dataStreamOut = nullptr;
|
||||||
|
static constexpr QMetaTypeInterface::DataStreamInFn dataStreamIn = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
template<typename S>
|
template<typename S>
|
||||||
class QMetaTypeForType
|
class QMetaTypeForType
|
||||||
{
|
{
|
||||||
@ -2780,6 +2753,9 @@ QMetaTypeInterface QMetaTypeForType<T>::metaType = {
|
|||||||
/*.dtor=*/ getDtor<T>(),
|
/*.dtor=*/ getDtor<T>(),
|
||||||
/*.equals=*/ QEqualityOperatorForType<T>::equals,
|
/*.equals=*/ QEqualityOperatorForType<T>::equals,
|
||||||
/*.lessThan=*/ QLessThanOperatorForType<T>::lessThan,
|
/*.lessThan=*/ QLessThanOperatorForType<T>::lessThan,
|
||||||
|
/*.debugStream=*/ QDebugStreamOperatorForType<T>::debugStream,
|
||||||
|
/*.dataStreamOut=*/ QDataStreamOperatorForType<T>::dataStreamOut,
|
||||||
|
/*.dataStreamIn=*/ QDataStreamOperatorForType<T>::dataStreamIn,
|
||||||
/*.legacyRegisterOp=*/ getLegacyRegister<T>()
|
/*.legacyRegisterOp=*/ getLegacyRegister<T>()
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2809,6 +2785,9 @@ public:
|
|||||||
/*.dtor=*/ nullptr,
|
/*.dtor=*/ nullptr,
|
||||||
/*.equals=*/ nullptr,
|
/*.equals=*/ nullptr,
|
||||||
/*.lessThan=*/ nullptr,
|
/*.lessThan=*/ nullptr,
|
||||||
|
/*.debugStream=*/ nullptr,
|
||||||
|
/*.dataStreamOut=*/ nullptr,
|
||||||
|
/*.dataStreamIn=*/ nullptr,
|
||||||
/*.legacyRegisterOp=*/ nullptr
|
/*.legacyRegisterOp=*/ nullptr
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -583,11 +583,9 @@ QByteArray QMimeData::data(const QString &mimeType) const
|
|||||||
|
|
||||||
Note that if you want to use a custom data type in an item view drag and drop
|
Note that if you want to use a custom data type in an item view drag and drop
|
||||||
operation, you must register it as a Qt \l{QMetaType}{meta type}, using the
|
operation, you must register it as a Qt \l{QMetaType}{meta type}, using the
|
||||||
Q_DECLARE_METATYPE() macro, and implement stream operators for it. The stream
|
Q_DECLARE_METATYPE() macro, and implement stream operators for it.
|
||||||
operators must then be registered with the qRegisterMetaTypeStreamOperators()
|
|
||||||
function.
|
|
||||||
|
|
||||||
\sa hasFormat(), QMetaType, {QMetaType::}{qRegisterMetaTypeStreamOperators()}
|
\sa hasFormat(), QMetaType, {QMetaType::}{Q_DECLARE_METATYPE()}
|
||||||
*/
|
*/
|
||||||
void QMimeData::setData(const QString &mimeType, const QByteArray &data)
|
void QMimeData::setData(const QString &mimeType, const QByteArray &data)
|
||||||
{
|
{
|
||||||
|
@ -2437,7 +2437,8 @@ void QVariant::load(QDataStream &s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// const cast is safe since we operate on a newly constructed variant
|
// const cast is safe since we operate on a newly constructed variant
|
||||||
if (!QMetaType::load(s, d.type().id(), const_cast<void *>(constData()))) {
|
void *data = const_cast<void *>(constData());
|
||||||
|
if (!d.type().load(s, data)) {
|
||||||
s.setStatus(QDataStream::ReadCorruptData);
|
s.setStatus(QDataStream::ReadCorruptData);
|
||||||
qWarning("QVariant::load: unable to load type %d.", d.type().id());
|
qWarning("QVariant::load: unable to load type %d.", d.type().id());
|
||||||
}
|
}
|
||||||
@ -2512,7 +2513,7 @@ void QVariant::save(QDataStream &s) const
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!QMetaType::save(s, d.type().id(), constData())) {
|
if (!d.type().save(s, constData())) {
|
||||||
qWarning("QVariant::save: unable to save type '%s' (type id: %d).\n",
|
qWarning("QVariant::save: unable to save type '%s' (type id: %d).\n",
|
||||||
QMetaType::typeName(d.type().id()), d.type().id());
|
QMetaType::typeName(d.type().id()), d.type().id());
|
||||||
Q_ASSERT_X(false, "QVariant::save", "Invalid type to save");
|
Q_ASSERT_X(false, "QVariant::save", "Invalid type to save");
|
||||||
@ -3977,7 +3978,7 @@ QDebug operator<<(QDebug dbg, const QVariant &v)
|
|||||||
bool userStream = false;
|
bool userStream = false;
|
||||||
bool canConvertToString = false;
|
bool canConvertToString = false;
|
||||||
if (typeId >= QMetaType::User) {
|
if (typeId >= QMetaType::User) {
|
||||||
userStream = QMetaType::debugStream(dbg, constData(v.d), typeId);
|
userStream = v.d.type().debugStream(dbg, constData(v.d));
|
||||||
canConvertToString = v.canConvert<QString>();
|
canConvertToString = v.canConvert<QString>();
|
||||||
}
|
}
|
||||||
if (!userStream && canConvertToString)
|
if (!userStream && canConvertToString)
|
||||||
|
@ -133,7 +133,7 @@ Q_CORE_EXPORT QDebug operator<<(QDebug, QCborKnownTags tg);
|
|||||||
Q_CORE_EXPORT QDebug operator<<(QDebug, QCborTag tg);
|
Q_CORE_EXPORT QDebug operator<<(QDebug, QCborTag tg);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(QT_NO_DEBUG_STREAM)
|
#if !defined(QT_NO_DATASTREAM)
|
||||||
QDataStream &operator<<(QDataStream &ds, QCborSimpleType st);
|
QDataStream &operator<<(QDataStream &ds, QCborSimpleType st);
|
||||||
QDataStream &operator>>(QDataStream &ds, QCborSimpleType &st);
|
QDataStream &operator>>(QDataStream &ds, QCborSimpleType &st);
|
||||||
#endif
|
#endif
|
||||||
|
@ -48,8 +48,10 @@ QT_BEGIN_NAMESPACE
|
|||||||
class QBitRef;
|
class QBitRef;
|
||||||
class Q_CORE_EXPORT QBitArray
|
class Q_CORE_EXPORT QBitArray
|
||||||
{
|
{
|
||||||
|
#ifndef QT_NO_DATASTREAM
|
||||||
friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QBitArray &);
|
friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QBitArray &);
|
||||||
friend Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QBitArray &);
|
friend Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QBitArray &);
|
||||||
|
#endif
|
||||||
friend Q_CORE_EXPORT size_t qHash(const QBitArray &key, size_t seed) noexcept;
|
friend Q_CORE_EXPORT size_t qHash(const QBitArray &key, size_t seed) noexcept;
|
||||||
QByteArray d;
|
QByteArray d;
|
||||||
|
|
||||||
|
@ -139,7 +139,9 @@ static int registerComplexDBusType(const QByteArray &typeName)
|
|||||||
[](QtPrivate::QMetaTypeInterface *self) {
|
[](QtPrivate::QMetaTypeInterface *self) {
|
||||||
delete static_cast<QDBusRawTypeHandler *>(self);
|
delete static_cast<QDBusRawTypeHandler *>(self);
|
||||||
},
|
},
|
||||||
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr
|
nullptr, nullptr, nullptr, nullptr,
|
||||||
|
nullptr, nullptr, nullptr,
|
||||||
|
nullptr, nullptr, nullptr
|
||||||
},
|
},
|
||||||
name(name)
|
name(name)
|
||||||
{}
|
{}
|
||||||
|
@ -106,6 +106,8 @@ private:
|
|||||||
QItemSelectionModel *selection;
|
QItemSelectionModel *selection;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
QDataStream &operator<<(QDataStream &, const QModelIndex &);
|
QDataStream &operator<<(QDataStream &, const QModelIndex &);
|
||||||
QDataStream &operator>>(QDataStream &, QModelIndex &);
|
QDataStream &operator>>(QDataStream &, QModelIndex &);
|
||||||
QDataStream &operator<<(QDataStream &, const QModelIndexList &);
|
QDataStream &operator<<(QDataStream &, const QModelIndexList &);
|
||||||
@ -178,6 +180,8 @@ QDataStream &operator>>(QDataStream &s, QModelIndexList &output)
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
tst_QItemSelectionModel::tst_QItemSelectionModel()
|
tst_QItemSelectionModel::tst_QItemSelectionModel()
|
||||||
: model(0), selection(0)
|
: model(0), selection(0)
|
||||||
{
|
{
|
||||||
|
@ -217,7 +217,6 @@ private slots:
|
|||||||
void isRegisteredStaticLess_data();
|
void isRegisteredStaticLess_data();
|
||||||
void isRegisteredStaticLess();
|
void isRegisteredStaticLess();
|
||||||
void isEnum();
|
void isEnum();
|
||||||
void registerStreamBuiltin();
|
|
||||||
void automaticTemplateRegistration();
|
void automaticTemplateRegistration();
|
||||||
void saveAndLoadBuiltin_data();
|
void saveAndLoadBuiltin_data();
|
||||||
void saveAndLoadBuiltin();
|
void saveAndLoadBuiltin();
|
||||||
@ -351,12 +350,12 @@ static void *GadgetTypedConstructor(int type, void *where, const void *copy)
|
|||||||
return it->first->constructor(type, where, copy);
|
return it->first->constructor(type, where, copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GadgetSaveOperator(QDataStream & out, const void *data)
|
static void GadgetSaveOperator(const QtPrivate::QMetaTypeInterface *, QDataStream & out, const void *data)
|
||||||
{
|
{
|
||||||
reinterpret_cast<const BaseGenericType *>(data)->saveOperator(out);
|
reinterpret_cast<const BaseGenericType *>(data)->saveOperator(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GadgetLoadOperator(QDataStream &in, void *data)
|
static void GadgetLoadOperator(const QtPrivate::QMetaTypeInterface *, QDataStream &in, void *data)
|
||||||
{
|
{
|
||||||
reinterpret_cast<BaseGenericType *>(data)->loadOperator(in);
|
reinterpret_cast<BaseGenericType *>(data)->loadOperator(in);
|
||||||
}
|
}
|
||||||
@ -424,12 +423,15 @@ void tst_QMetaType::registerGadget(const char *name, const QList<GadgetPropertyT
|
|||||||
[](const TypeInfo *self, void *ptr) { GadgetTypedDestructor(self->typeId, ptr); },
|
[](const TypeInfo *self, void *ptr) { GadgetTypedDestructor(self->typeId, ptr); },
|
||||||
nullptr,
|
nullptr,
|
||||||
nullptr,
|
nullptr,
|
||||||
nullptr };
|
nullptr,
|
||||||
|
GadgetSaveOperator,
|
||||||
|
GadgetLoadOperator,
|
||||||
|
nullptr
|
||||||
|
};
|
||||||
QMetaType gadgetMetaType(typeInfo);
|
QMetaType gadgetMetaType(typeInfo);
|
||||||
dynamicGadgetProperties->m_metatype = gadgetMetaType;
|
dynamicGadgetProperties->m_metatype = gadgetMetaType;
|
||||||
int gadgetTypeId = QMetaType(typeInfo).id();
|
int gadgetTypeId = QMetaType(typeInfo).id();
|
||||||
QVERIFY(gadgetTypeId > 0);
|
QVERIFY(gadgetTypeId > 0);
|
||||||
QMetaType::registerStreamOperators(gadgetTypeId, &GadgetSaveOperator, &GadgetLoadOperator);
|
|
||||||
s_managedTypes[gadgetTypeId] = qMakePair(dynamicGadgetProperties, std::shared_ptr<QMetaObject>{meta, [](QMetaObject *ptr){ ::free(ptr); }});
|
s_managedTypes[gadgetTypeId] = qMakePair(dynamicGadgetProperties, std::shared_ptr<QMetaObject>{meta, [](QMetaObject *ptr){ ::free(ptr); }});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1326,12 +1328,17 @@ void tst_QMetaType::typedConstruct()
|
|||||||
[](const TypeInfo *self, void *where, const void *copy) { GadgetTypedConstructor(self->typeId, where, copy); },
|
[](const TypeInfo *self, void *where, const void *copy) { GadgetTypedConstructor(self->typeId, where, copy); },
|
||||||
[](const TypeInfo *self, void *where, void *copy) { GadgetTypedConstructor(self->typeId, where, copy); },
|
[](const TypeInfo *self, void *where, void *copy) { GadgetTypedConstructor(self->typeId, where, copy); },
|
||||||
[](const TypeInfo *self, void *ptr) { GadgetTypedDestructor(self->typeId, ptr); },
|
[](const TypeInfo *self, void *ptr) { GadgetTypedDestructor(self->typeId, ptr); },
|
||||||
nullptr, nullptr, nullptr };
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
GadgetSaveOperator,
|
||||||
|
GadgetLoadOperator,
|
||||||
|
nullptr
|
||||||
|
};
|
||||||
QMetaType metatype(typeInfo);
|
QMetaType metatype(typeInfo);
|
||||||
dynamicGadgetProperties->m_metatype = metatype;
|
dynamicGadgetProperties->m_metatype = metatype;
|
||||||
int podTypeId = metatype.id();
|
int podTypeId = metatype.id();
|
||||||
QVERIFY(podTypeId > 0);
|
QVERIFY(podTypeId > 0);
|
||||||
QMetaType::registerStreamOperators(podTypeId, &GadgetSaveOperator, &GadgetLoadOperator);
|
|
||||||
s_managedTypes[podTypeId] = qMakePair(dynamicGadgetProperties, std::shared_ptr<QMetaObject>{});
|
s_managedTypes[podTypeId] = qMakePair(dynamicGadgetProperties, std::shared_ptr<QMetaObject>{});
|
||||||
|
|
||||||
// Test POD
|
// Test POD
|
||||||
@ -1552,13 +1559,6 @@ void tst_QMetaType::isRegisteredStaticLess()
|
|||||||
QCOMPARE(QMetaType(typeId).isRegistered(), registered);
|
QCOMPARE(QMetaType(typeId).isRegistered(), registered);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QMetaType::registerStreamBuiltin()
|
|
||||||
{
|
|
||||||
//should not crash;
|
|
||||||
qRegisterMetaTypeStreamOperators<QString>("QString");
|
|
||||||
qRegisterMetaTypeStreamOperators<QVariant>("QVariant");
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef QHash<int, uint> IntUIntHash;
|
typedef QHash<int, uint> IntUIntHash;
|
||||||
Q_DECLARE_METATYPE(IntUIntHash)
|
Q_DECLARE_METATYPE(IntUIntHash)
|
||||||
typedef QMap<int, uint> IntUIntMap;
|
typedef QMap<int, uint> IntUIntMap;
|
||||||
@ -2044,7 +2044,6 @@ struct CustomStreamableType
|
|||||||
{
|
{
|
||||||
int a;
|
int a;
|
||||||
};
|
};
|
||||||
Q_DECLARE_METATYPE(CustomStreamableType)
|
|
||||||
|
|
||||||
QDataStream &operator<<(QDataStream &out, const CustomStreamableType &t)
|
QDataStream &operator<<(QDataStream &out, const CustomStreamableType &t)
|
||||||
{
|
{
|
||||||
@ -2059,6 +2058,7 @@ QDataStream &operator>>(QDataStream &in, CustomStreamableType &t)
|
|||||||
t.a = a;
|
t.a = a;
|
||||||
return in;
|
return in;
|
||||||
}
|
}
|
||||||
|
Q_DECLARE_METATYPE(CustomStreamableType)
|
||||||
|
|
||||||
void tst_QMetaType::saveAndLoadCustom()
|
void tst_QMetaType::saveAndLoadCustom()
|
||||||
{
|
{
|
||||||
@ -2068,12 +2068,7 @@ void tst_QMetaType::saveAndLoadCustom()
|
|||||||
int id = ::qMetaTypeId<CustomStreamableType>();
|
int id = ::qMetaTypeId<CustomStreamableType>();
|
||||||
QByteArray ba;
|
QByteArray ba;
|
||||||
QDataStream stream(&ba, QIODevice::ReadWrite);
|
QDataStream stream(&ba, QIODevice::ReadWrite);
|
||||||
QVERIFY(!QMetaType::save(stream, id, &t));
|
|
||||||
QCOMPARE(stream.status(), QDataStream::Ok);
|
|
||||||
QVERIFY(!QMetaType::load(stream, id, &t));
|
|
||||||
QCOMPARE(stream.status(), QDataStream::Ok);
|
|
||||||
|
|
||||||
qRegisterMetaTypeStreamOperators<CustomStreamableType>("CustomStreamableType");
|
|
||||||
QVERIFY(QMetaType::save(stream, id, &t));
|
QVERIFY(QMetaType::save(stream, id, &t));
|
||||||
QCOMPARE(stream.status(), QDataStream::Ok);
|
QCOMPARE(stream.status(), QDataStream::Ok);
|
||||||
|
|
||||||
@ -2278,6 +2273,11 @@ struct CustomDebugStreamableType
|
|||||||
QString toString() const { return "test"; }
|
QString toString() const { return "test"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CustomDebugStreamableType2
|
||||||
|
{
|
||||||
|
QString toString() const { return "test"; }
|
||||||
|
};
|
||||||
|
|
||||||
QDebug operator<<(QDebug dbg, const CustomDebugStreamableType&)
|
QDebug operator<<(QDebug dbg, const CustomDebugStreamableType&)
|
||||||
{
|
{
|
||||||
return dbg << "string-content";
|
return dbg << "string-content";
|
||||||
@ -2607,16 +2607,14 @@ void tst_QMetaType::customDebugStream()
|
|||||||
{
|
{
|
||||||
MessageHandlerCustom handler(::qMetaTypeId<CustomDebugStreamableType>());
|
MessageHandlerCustom handler(::qMetaTypeId<CustomDebugStreamableType>());
|
||||||
QVariant v1 = QVariant::fromValue(CustomDebugStreamableType());
|
QVariant v1 = QVariant::fromValue(CustomDebugStreamableType());
|
||||||
handler.expectedMessage = "QVariant(CustomDebugStreamableType, )";
|
|
||||||
qDebug() << v1;
|
|
||||||
|
|
||||||
QMetaType::registerConverter<CustomDebugStreamableType, QString>(&CustomDebugStreamableType::toString);
|
|
||||||
handler.expectedMessage = "QVariant(CustomDebugStreamableType, \"test\")";
|
|
||||||
qDebug() << v1;
|
|
||||||
|
|
||||||
QMetaType::registerDebugStreamOperator<CustomDebugStreamableType>();
|
|
||||||
handler.expectedMessage = "QVariant(CustomDebugStreamableType, string-content)";
|
handler.expectedMessage = "QVariant(CustomDebugStreamableType, string-content)";
|
||||||
qDebug() << v1;
|
qDebug() << v1;
|
||||||
|
|
||||||
|
MessageHandlerCustom handler2(::qMetaTypeId<CustomDebugStreamableType2>());
|
||||||
|
QMetaType::registerConverter<CustomDebugStreamableType2, QString>(&CustomDebugStreamableType2::toString);
|
||||||
|
handler2.expectedMessage = "QVariant(CustomDebugStreamableType2, \"test\")";
|
||||||
|
QVariant v2 = QVariant::fromValue(CustomDebugStreamableType2());
|
||||||
|
qDebug() << v2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QMetaType::unknownType()
|
void tst_QMetaType::unknownType()
|
||||||
|
@ -1405,6 +1405,20 @@ struct CustomType
|
|||||||
int value() { return i1 + i2 + i3; }
|
int value() { return i1 + i2 + i3; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
QDataStream &operator<<(QDataStream &stream, const CustomType &ct)
|
||||||
|
{
|
||||||
|
stream << ct.i1 << ct.i2 << ct.i3;
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDataStream &operator>>(QDataStream &stream, CustomType &ct)
|
||||||
|
{
|
||||||
|
stream >> ct.i1;
|
||||||
|
stream >> ct.i2;
|
||||||
|
stream >> ct.i3;
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(CustomType*)
|
Q_DECLARE_METATYPE(CustomType*)
|
||||||
Q_DECLARE_METATYPE(CustomType)
|
Q_DECLARE_METATYPE(CustomType)
|
||||||
|
|
||||||
@ -1475,26 +1489,11 @@ void tst_QObject::customTypes()
|
|||||||
QCOMPARE(instanceCount, 3);
|
QCOMPARE(instanceCount, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
QDataStream &operator<<(QDataStream &stream, const CustomType &ct)
|
|
||||||
{
|
|
||||||
stream << ct.i1 << ct.i2 << ct.i3;
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
QDataStream &operator>>(QDataStream &stream, CustomType &ct)
|
|
||||||
{
|
|
||||||
stream >> ct.i1;
|
|
||||||
stream >> ct.i2;
|
|
||||||
stream >> ct.i3;
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
void tst_QObject::streamCustomTypes()
|
void tst_QObject::streamCustomTypes()
|
||||||
{
|
{
|
||||||
QByteArray ba;
|
QByteArray ba;
|
||||||
|
|
||||||
int idx = qRegisterMetaType<CustomType>("CustomType");
|
int idx = qRegisterMetaType<CustomType>("CustomType");
|
||||||
qRegisterMetaTypeStreamOperators<CustomType>("CustomType");
|
|
||||||
|
|
||||||
{
|
{
|
||||||
CustomType t1(1, 2, 3);
|
CustomType t1(1, 2, 3);
|
||||||
|
@ -1222,7 +1222,6 @@ struct CustomStreamableClass
|
|||||||
return i == other.i;
|
return i == other.i;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Q_DECLARE_METATYPE(CustomStreamableClass);
|
|
||||||
|
|
||||||
QDataStream &operator<<(QDataStream &out, const CustomStreamableClass &myObj)
|
QDataStream &operator<<(QDataStream &out, const CustomStreamableClass &myObj)
|
||||||
{
|
{
|
||||||
@ -1233,11 +1232,10 @@ QDataStream &operator>>(QDataStream &in, CustomStreamableClass &myObj)
|
|||||||
{
|
{
|
||||||
return in >> myObj.i;
|
return in >> myObj.i;
|
||||||
}
|
}
|
||||||
|
Q_DECLARE_METATYPE(CustomStreamableClass);
|
||||||
|
|
||||||
void tst_QVariant::writeToReadFromDataStream_data()
|
void tst_QVariant::writeToReadFromDataStream_data()
|
||||||
{
|
{
|
||||||
qRegisterMetaTypeStreamOperators<CustomStreamableClass>();
|
|
||||||
|
|
||||||
QTest::addColumn<QVariant>("writeVariant");
|
QTest::addColumn<QVariant>("writeVariant");
|
||||||
QTest::addColumn<bool>("isNull");
|
QTest::addColumn<bool>("isNull");
|
||||||
{
|
{
|
||||||
@ -2184,8 +2182,6 @@ void tst_QVariant::saveLoadCustomTypes()
|
|||||||
auto tp = QMetaType::fromType<Blah>();
|
auto tp = QMetaType::fromType<Blah>();
|
||||||
QVariant v = QVariant(tp, &i);
|
QVariant v = QVariant(tp, &i);
|
||||||
|
|
||||||
qRegisterMetaTypeStreamOperators<Blah>("Blah");
|
|
||||||
|
|
||||||
QCOMPARE(v.userType(), tp.id());
|
QCOMPARE(v.userType(), tp.id());
|
||||||
QCOMPARE(v.type(), QVariant::UserType);
|
QCOMPARE(v.type(), QVariant::UserType);
|
||||||
{
|
{
|
||||||
@ -4639,8 +4635,6 @@ void tst_QVariant::fromStdVariant()
|
|||||||
|
|
||||||
void tst_QVariant::qt4UuidDataStream()
|
void tst_QVariant::qt4UuidDataStream()
|
||||||
{
|
{
|
||||||
qRegisterMetaTypeStreamOperators<QUuid>();
|
|
||||||
|
|
||||||
QByteArray data;
|
QByteArray data;
|
||||||
QDataStream stream(&data, QIODevice::WriteOnly);
|
QDataStream stream(&data, QIODevice::WriteOnly);
|
||||||
stream.setVersion(QDataStream::Qt_4_8);
|
stream.setVersion(QDataStream::Qt_4_8);
|
||||||
|
@ -741,8 +741,6 @@ void tst_QGuiVariant::guiVariantAtExit()
|
|||||||
|
|
||||||
void tst_QGuiVariant::qt4QPolygonFDataStream()
|
void tst_QGuiVariant::qt4QPolygonFDataStream()
|
||||||
{
|
{
|
||||||
qRegisterMetaTypeStreamOperators<QPolygonF>();
|
|
||||||
|
|
||||||
QByteArray data;
|
QByteArray data;
|
||||||
QDataStream stream(&data, QIODevice::WriteOnly);
|
QDataStream stream(&data, QIODevice::WriteOnly);
|
||||||
stream.setVersion(QDataStream::Qt_4_8);
|
stream.setVersion(QDataStream::Qt_4_8);
|
||||||
|
@ -297,35 +297,6 @@ namespace QtTestInternal
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
template<bool>
|
|
||||||
struct DataStreamOpHelper
|
|
||||||
{
|
|
||||||
template <typename T>
|
|
||||||
struct Getter {
|
|
||||||
static QMetaType::SaveOperator saveOp() { return 0; }
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct DataStreamOpHelper<true>
|
|
||||||
{
|
|
||||||
template <typename T>
|
|
||||||
struct Getter {
|
|
||||||
static QMetaType::SaveOperator saveOp()
|
|
||||||
{
|
|
||||||
return ::QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Save;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline QMetaType::SaveOperator getSaveOperator(T * = 0)
|
|
||||||
{
|
|
||||||
typedef typename DataStreamOpHelper<DataStreamChecker<T>::HasDataStream>::template Getter<T> GetterHelper;
|
|
||||||
return GetterHelper::saveOp();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MyString: public QString {};
|
struct MyString: public QString {};
|
||||||
@ -344,14 +315,6 @@ void tst_Compiler::detectDataStream()
|
|||||||
QVERIFY(QtTestInternal::DataStreamChecker<QString>::HasDataStream);
|
QVERIFY(QtTestInternal::DataStreamChecker<QString>::HasDataStream);
|
||||||
QVERIFY(QtTestInternal::DataStreamChecker<MyString>::HasDataStream);
|
QVERIFY(QtTestInternal::DataStreamChecker<MyString>::HasDataStream);
|
||||||
QVERIFY(!QtTestInternal::DataStreamChecker<Qxxx>::HasDataStream);
|
QVERIFY(!QtTestInternal::DataStreamChecker<Qxxx>::HasDataStream);
|
||||||
|
|
||||||
QVERIFY(QtTestInternal::getSaveOperator<int>() != 0);
|
|
||||||
QVERIFY(QtTestInternal::getSaveOperator<uint>() != 0);
|
|
||||||
QVERIFY(QtTestInternal::getSaveOperator<char *>() != 0);
|
|
||||||
QVERIFY(QtTestInternal::getSaveOperator<double>() != 0);
|
|
||||||
QVERIFY(QtTestInternal::getSaveOperator<QString>() != 0);
|
|
||||||
QVERIFY(QtTestInternal::getSaveOperator<MyString>() != 0);
|
|
||||||
QVERIFY(!QtTestInternal::getSaveOperator<Qxxx>());
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
void tst_Compiler::detectDataStream()
|
void tst_Compiler::detectDataStream()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user