QMetaObject: add a new, variadic invoke/invokeMethod/newInstance
[ChangeLog][QtCore][Meta Objects] The QMetaObject::invokeMethod() taking a method name by string, QMetaObject::newInstance(), and QMetaMethod::invoke() now support more than 10 arguments. [ChangeLog][QtCore][Meta Objects] The use of the Q_ARG and Q_RETURN_ARG macros is now optional with QMetaObject::invokeMethod(), QMetaObject::newInstance(), and QMetaMethod::invoke(): the type name will be obtained from the C++ type (the same as QMetaType). The function qReturnArg() can be used in place of the Q_RETURN_ARG macro. The macros are still useful in rare conditions where the type was typedef'ed from its original name. Change-Id: I36b24183fbd041179f2ffffd17022a2b48c7639b Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
This commit is contained in:
parent
191419e980
commit
fe92b08065
@ -223,22 +223,13 @@ QObject *QMetaObject::newInstance(QGenericArgument val0,
|
|||||||
QGenericArgument val8,
|
QGenericArgument val8,
|
||||||
QGenericArgument val9) const
|
QGenericArgument val9) const
|
||||||
{
|
{
|
||||||
if (!inherits(&QObject::staticMetaObject))
|
|
||||||
{
|
|
||||||
qWarning("QMetaObject::newInstance: type %s does not inherit QObject", className());
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
QObject *returnValue = nullptr;
|
|
||||||
QMetaType returnValueMetaType = QMetaType::fromType<decltype(returnValue)>();
|
|
||||||
|
|
||||||
const char *typeNames[] = {
|
const char *typeNames[] = {
|
||||||
returnValueMetaType.name(),
|
nullptr,
|
||||||
val0.name(), val1.name(), val2.name(), val3.name(), val4.name(),
|
val0.name(), val1.name(), val2.name(), val3.name(), val4.name(),
|
||||||
val5.name(), val6.name(), val7.name(), val8.name(), val9.name()
|
val5.name(), val6.name(), val7.name(), val8.name(), val9.name()
|
||||||
};
|
};
|
||||||
const void *parameters[] = {
|
const void *parameters[] = {
|
||||||
&returnValue,
|
nullptr,
|
||||||
val0.data(), val1.data(), val2.data(), val3.data(), val4.data(),
|
val0.data(), val1.data(), val2.data(), val3.data(), val4.data(),
|
||||||
val5.data(), val6.data(), val7.data(), val8.data(), val9.data()
|
val5.data(), val6.data(), val7.data(), val8.data(), val9.data()
|
||||||
};
|
};
|
||||||
@ -250,10 +241,34 @@ QObject *QMetaObject::newInstance(QGenericArgument val0,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return newInstanceImpl(this, paramCount, parameters, typeNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
QObject *QMetaObject::newInstanceImpl(const QMetaObject *mobj, qsizetype paramCount,
|
||||||
|
const void **parameters, const char **typeNames)
|
||||||
|
{
|
||||||
|
if (!mobj->inherits(&QObject::staticMetaObject)) {
|
||||||
|
qWarning("QMetaObject::newInstance: type %s does not inherit QObject", mobj->className());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
QT_WARNING_PUSH
|
||||||
|
#if Q_CC_GNU >= 1200
|
||||||
|
QT_WARNING_DISABLE_GCC("-Wdangling-pointer")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// set the return type
|
||||||
|
QObject *returnValue = nullptr;
|
||||||
|
QMetaType returnValueMetaType = QMetaType::fromType<decltype(returnValue)>();
|
||||||
|
parameters[0] = &returnValue;
|
||||||
|
typeNames[0] = returnValueMetaType.name();
|
||||||
|
|
||||||
|
QT_WARNING_POP
|
||||||
|
|
||||||
// find the constructor
|
// find the constructor
|
||||||
auto priv = QMetaObjectPrivate::get(this);
|
auto priv = QMetaObjectPrivate::get(mobj);
|
||||||
for (int i = 0; i < priv->constructorCount; ++i) {
|
for (int i = 0; i < priv->constructorCount; ++i) {
|
||||||
QMetaMethod m = QMetaMethod::fromRelativeConstructorIndex(this, i);
|
QMetaMethod m = QMetaMethod::fromRelativeConstructorIndex(mobj, i);
|
||||||
if (m.parameterCount() != (paramCount - 1))
|
if (m.parameterCount() != (paramCount - 1))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -1457,6 +1472,19 @@ bool QMetaObject::invokeMethod(QObject *obj,
|
|||||||
if (qstrlen(typeNames[paramCount]) <= 0)
|
if (qstrlen(typeNames[paramCount]) <= 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
return invokeMethodImpl(obj, member, type, paramCount, parameters, typeNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QMetaObject::invokeMethodImpl(QObject *obj, const char *member, Qt::ConnectionType type,
|
||||||
|
qsizetype paramCount, const void * const *parameters,
|
||||||
|
const char * const *typeNames)
|
||||||
|
{
|
||||||
|
if (!obj)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Q_ASSERT(paramCount >= 1); // includes the return type
|
||||||
|
Q_ASSERT(parameters);
|
||||||
|
Q_ASSERT(typeNames);
|
||||||
|
|
||||||
// find the method
|
// find the method
|
||||||
QLatin1StringView name(member);
|
QLatin1StringView name(member);
|
||||||
@ -2382,9 +2410,17 @@ bool QMetaMethod::invoke(QObject *object,
|
|||||||
if (qstrlen(typeNames[paramCount]) <= 0)
|
if (qstrlen(typeNames[paramCount]) <= 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
return invokeImpl(*this, object, connectionType, paramCount, param, typeNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QMetaMethod::invokeImpl(QMetaMethod self, void *target, Qt::ConnectionType connectionType,
|
||||||
|
qsizetype paramCount, const void *const *parameters,
|
||||||
|
const char *const *typeNames)
|
||||||
|
{
|
||||||
|
if (!target || !self.mobj)
|
||||||
|
return false;
|
||||||
QMetaMethodPrivate::InvokeFailReason r =
|
QMetaMethodPrivate::InvokeFailReason r =
|
||||||
QMetaMethodPrivate::invokeImpl(*this, object, connectionType, paramCount, param, typeNames);
|
QMetaMethodPrivate::invokeImpl(self, target, connectionType, paramCount, parameters, typeNames);
|
||||||
|
|
||||||
if (Q_LIKELY(r == QMetaMethodPrivate::InvokeFailReason::None))
|
if (Q_LIKELY(r == QMetaMethodPrivate::InvokeFailReason::None))
|
||||||
return true;
|
return true;
|
||||||
@ -2392,11 +2428,11 @@ bool QMetaMethod::invoke(QObject *object,
|
|||||||
if (int(r) >= int(QMetaMethodPrivate::InvokeFailReason::FormalParameterMismatch)) {
|
if (int(r) >= int(QMetaMethodPrivate::InvokeFailReason::FormalParameterMismatch)) {
|
||||||
int n = int(r) - int(QMetaMethodPrivate::InvokeFailReason::FormalParameterMismatch);
|
int n = int(r) - int(QMetaMethodPrivate::InvokeFailReason::FormalParameterMismatch);
|
||||||
qWarning("QMetaMethod::invoke: cannot convert formal parameter %d from %s in call to %s::%s",
|
qWarning("QMetaMethod::invoke: cannot convert formal parameter %d from %s in call to %s::%s",
|
||||||
n, typeNames[n + 1], mobj->className(), methodSignature().constData());
|
n, typeNames[n + 1], self.mobj->className(), self.methodSignature().constData());
|
||||||
}
|
}
|
||||||
if (r == QMetaMethodPrivate::InvokeFailReason::TooFewArguments) {
|
if (r == QMetaMethodPrivate::InvokeFailReason::TooFewArguments) {
|
||||||
qWarning("QMetaMethod::invoke: too few arguments (%d) in call to %s::%s",
|
qWarning("QMetaMethod::invoke: too few arguments (%d) in call to %s::%s",
|
||||||
int(paramCount), mobj->className(), methodSignature().constData());
|
int(paramCount), self.mobj->className(), self.methodSignature().constData());
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -2412,7 +2448,8 @@ auto QMetaMethodInvoker::invokeImpl(QMetaMethod self, void *target,
|
|||||||
|
|
||||||
Q_ASSERT(priv->mobj);
|
Q_ASSERT(priv->mobj);
|
||||||
Q_ASSERT(self.methodType() == Constructor || object);
|
Q_ASSERT(self.methodType() == Constructor || object);
|
||||||
Q_ASSERT(self.methodType() == Constructor || priv->mobj->cast(object));
|
Q_ASSERT(self.methodType() == Constructor || connectionType == Qt::ConnectionType(-1) ||
|
||||||
|
priv->mobj->cast(object));
|
||||||
Q_ASSERT(paramCount >= 1); // includes the return type
|
Q_ASSERT(paramCount >= 1); // includes the return type
|
||||||
Q_ASSERT(parameters);
|
Q_ASSERT(parameters);
|
||||||
Q_ASSERT(typeNames);
|
Q_ASSERT(typeNames);
|
||||||
@ -2477,18 +2514,23 @@ auto QMetaMethodInvoker::invokeImpl(QMetaMethod self, void *target,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Qt::HANDLE currentThreadId = QThread::currentThreadId();
|
Qt::HANDLE currentThreadId = nullptr;
|
||||||
QThread *objectThread = object->thread();
|
QThread *objectThread = nullptr;
|
||||||
bool receiverInSameThread = false;
|
auto receiverInSameThread = [&]() {
|
||||||
if (objectThread)
|
if (!currentThreadId) {
|
||||||
receiverInSameThread = currentThreadId == QThreadData::get2(objectThread)->threadId.loadRelaxed();
|
currentThreadId = QThread::currentThreadId();
|
||||||
|
objectThread = object->thread();
|
||||||
|
}
|
||||||
|
if (objectThread)
|
||||||
|
return currentThreadId == QThreadData::get2(objectThread)->threadId.loadRelaxed();
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
// check connection type
|
// check connection type
|
||||||
if (connectionType == Qt::AutoConnection) {
|
if (connectionType == Qt::AutoConnection)
|
||||||
connectionType = receiverInSameThread
|
connectionType = receiverInSameThread() ? Qt::DirectConnection : Qt::QueuedConnection;
|
||||||
? Qt::DirectConnection
|
else if (connectionType == Qt::ConnectionType(-1))
|
||||||
: Qt::QueuedConnection;
|
connectionType = Qt::DirectConnection;
|
||||||
}
|
|
||||||
|
|
||||||
#if !QT_CONFIG(thread)
|
#if !QT_CONFIG(thread)
|
||||||
if (connectionType == Qt::BlockingQueuedConnection) {
|
if (connectionType == Qt::BlockingQueuedConnection) {
|
||||||
@ -2536,7 +2578,7 @@ auto QMetaMethodInvoker::invokeImpl(QMetaMethod self, void *target,
|
|||||||
QCoreApplication::postEvent(object, event.release());
|
QCoreApplication::postEvent(object, event.release());
|
||||||
} else { // blocking queued connection
|
} else { // blocking queued connection
|
||||||
#if QT_CONFIG(thread)
|
#if QT_CONFIG(thread)
|
||||||
if (receiverInSameThread) {
|
if (receiverInSameThread()) {
|
||||||
qWarning("QMetaMethod::invoke: Dead lock detected in BlockingQueuedConnection: "
|
qWarning("QMetaMethod::invoke: Dead lock detected in BlockingQueuedConnection: "
|
||||||
"Receiver is %s(%p)", priv->mobj->className(), object);
|
"Receiver is %s(%p)", priv->mobj->className(), object);
|
||||||
return InvokeFailReason::DeadLockDetected;
|
return InvokeFailReason::DeadLockDetected;
|
||||||
|
@ -45,6 +45,7 @@ public:
|
|||||||
|
|
||||||
inline const QMetaObject *enclosingMetaObject() const { return mobj; }
|
inline const QMetaObject *enclosingMetaObject() const { return mobj; }
|
||||||
|
|
||||||
|
#if QT_VERSION <= QT_VERSION_CHECK(7, 0, 0)
|
||||||
bool invoke(QObject *object,
|
bool invoke(QObject *object,
|
||||||
Qt::ConnectionType connectionType,
|
Qt::ConnectionType connectionType,
|
||||||
QGenericReturnArgument returnValue,
|
QGenericReturnArgument returnValue,
|
||||||
@ -76,7 +77,7 @@ public:
|
|||||||
}
|
}
|
||||||
inline bool invoke(QObject *object,
|
inline bool invoke(QObject *object,
|
||||||
Qt::ConnectionType connectionType,
|
Qt::ConnectionType connectionType,
|
||||||
QGenericArgument val0 = QGenericArgument(nullptr),
|
QGenericArgument val0,
|
||||||
QGenericArgument val1 = QGenericArgument(),
|
QGenericArgument val1 = QGenericArgument(),
|
||||||
QGenericArgument val2 = QGenericArgument(),
|
QGenericArgument val2 = QGenericArgument(),
|
||||||
QGenericArgument val3 = QGenericArgument(),
|
QGenericArgument val3 = QGenericArgument(),
|
||||||
@ -91,7 +92,7 @@ public:
|
|||||||
val0, val1, val2, val3, val4, val5, val6, val7, val8, val9);
|
val0, val1, val2, val3, val4, val5, val6, val7, val8, val9);
|
||||||
}
|
}
|
||||||
inline bool invoke(QObject *object,
|
inline bool invoke(QObject *object,
|
||||||
QGenericArgument val0 = QGenericArgument(nullptr),
|
QGenericArgument val0,
|
||||||
QGenericArgument val1 = QGenericArgument(),
|
QGenericArgument val1 = QGenericArgument(),
|
||||||
QGenericArgument val2 = QGenericArgument(),
|
QGenericArgument val2 = QGenericArgument(),
|
||||||
QGenericArgument val3 = QGenericArgument(),
|
QGenericArgument val3 = QGenericArgument(),
|
||||||
@ -118,7 +119,7 @@ public:
|
|||||||
QGenericArgument val8 = QGenericArgument(),
|
QGenericArgument val8 = QGenericArgument(),
|
||||||
QGenericArgument val9 = QGenericArgument()) const;
|
QGenericArgument val9 = QGenericArgument()) const;
|
||||||
inline bool invokeOnGadget(void *gadget,
|
inline bool invokeOnGadget(void *gadget,
|
||||||
QGenericArgument val0 = QGenericArgument(nullptr),
|
QGenericArgument val0,
|
||||||
QGenericArgument val1 = QGenericArgument(),
|
QGenericArgument val1 = QGenericArgument(),
|
||||||
QGenericArgument val2 = QGenericArgument(),
|
QGenericArgument val2 = QGenericArgument(),
|
||||||
QGenericArgument val3 = QGenericArgument(),
|
QGenericArgument val3 = QGenericArgument(),
|
||||||
@ -132,6 +133,48 @@ public:
|
|||||||
return invokeOnGadget(gadget, QGenericReturnArgument(),
|
return invokeOnGadget(gadget, QGenericReturnArgument(),
|
||||||
val0, val1, val2, val3, val4, val5, val6, val7, val8, val9);
|
val0, val1, val2, val3, val4, val5, val6, val7, val8, val9);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <typename... Args> QtPrivate::Invoke::IfNotOldStyleArgs<bool, Args...>
|
||||||
|
invoke(QObject *obj, Qt::ConnectionType c, QMetaMethodReturnArgument r,
|
||||||
|
Args &&... arguments) const
|
||||||
|
{
|
||||||
|
auto h = QtPrivate::invokeMethodHelper(r, std::forward<Args>(arguments)...);
|
||||||
|
return invokeImpl(*this, obj, c, h.parameterCount(), h.parameters.data(),
|
||||||
|
h.typeNames.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Args> QtPrivate::Invoke::IfNotOldStyleArgs<bool, Args...>
|
||||||
|
invoke(QObject *obj, Qt::ConnectionType c, Args &&... arguments) const
|
||||||
|
{
|
||||||
|
return invoke(obj, c, QMetaMethodReturnArgument{}, std::forward<Args>(arguments)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Args> QtPrivate::Invoke::IfNotOldStyleArgs<bool, Args...>
|
||||||
|
invoke(QObject *obj, QMetaMethodReturnArgument r, Args &&... arguments) const
|
||||||
|
{
|
||||||
|
return invoke(obj, Qt::AutoConnection, r, std::forward<Args>(arguments)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Args> QtPrivate::Invoke::IfNotOldStyleArgs<bool, Args...>
|
||||||
|
invoke(QObject *obj, Args &&... arguments) const
|
||||||
|
{
|
||||||
|
return invoke(obj, Qt::AutoConnection, std::forward<Args>(arguments)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Args> QtPrivate::Invoke::IfNotOldStyleArgs<bool, Args...>
|
||||||
|
invokeOnGadget(void *gadget, QMetaMethodReturnArgument r, Args &&... arguments) const
|
||||||
|
{
|
||||||
|
auto h = QtPrivate::invokeMethodHelper(r, std::forward<Args>(arguments)...);
|
||||||
|
return invokeImpl(*this, gadget, Qt::ConnectionType(-1), h.parameterCount(),
|
||||||
|
h.parameters.data(), h.typeNames.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Args> QtPrivate::Invoke::IfNotOldStyleArgs<bool, Args...>
|
||||||
|
invokeOnGadget(void *gadget, Args &&... arguments) const
|
||||||
|
{
|
||||||
|
return invokeOnGadget(gadget, QMetaMethodReturnArgument{}, std::forward<Args>(arguments)...);
|
||||||
|
}
|
||||||
|
|
||||||
inline bool isValid() const { return mobj != nullptr; }
|
inline bool isValid() const { return mobj != nullptr; }
|
||||||
|
|
||||||
@ -146,6 +189,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static bool invokeImpl(QMetaMethod self, void *target, Qt::ConnectionType, qsizetype paramCount,
|
||||||
|
const void *const *parameters, const char *const *typeNames);
|
||||||
static QMetaMethod fromSignalImpl(const QMetaObject *, void **);
|
static QMetaMethod fromSignalImpl(const QMetaObject *, void **);
|
||||||
static QMetaMethod fromRelativeMethodIndex(const QMetaObject *mobj, int index);
|
static QMetaMethod fromRelativeMethodIndex(const QMetaObject *mobj, int index);
|
||||||
static QMetaMethod fromRelativeConstructorIndex(const QMetaObject *mobj, int index);
|
static QMetaMethod fromRelativeConstructorIndex(const QMetaObject *mobj, int index);
|
||||||
|
@ -59,8 +59,8 @@ Q_CORE_EXPORT const char *qFlagLocation(const char *method);
|
|||||||
# endif
|
# endif
|
||||||
#endif // QT_NO_META_MACROS
|
#endif // QT_NO_META_MACROS
|
||||||
|
|
||||||
#define Q_ARG(type, data) QArgument<type >(#type, data)
|
#define Q_ARG(Type, data) QtPrivate::Invoke::argument<Type>(QT_STRINGIFY(Type), data)
|
||||||
#define Q_RETURN_ARG(type, data) QReturnArgument<type >(#type, data)
|
#define Q_RETURN_ARG(Type, data) QtPrivate::Invoke::returnArgument<Type>(QT_STRINGIFY(Type), data)
|
||||||
|
|
||||||
class QObject;
|
class QObject;
|
||||||
class QMetaMethod;
|
class QMetaMethod;
|
||||||
@ -70,6 +70,7 @@ class QMetaClassInfo;
|
|||||||
|
|
||||||
namespace QtPrivate {
|
namespace QtPrivate {
|
||||||
class QMetaTypeInterface;
|
class QMetaTypeInterface;
|
||||||
|
template<typename T> constexpr auto typenameHelper();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct QMethodRawArguments
|
struct QMethodRawArguments
|
||||||
@ -77,6 +78,7 @@ struct QMethodRawArguments
|
|||||||
void **arguments;
|
void **arguments;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if QT_VERSION <= QT_VERSION_CHECK(7, 0, 0)
|
||||||
class Q_CORE_EXPORT QGenericArgument
|
class Q_CORE_EXPORT QGenericArgument
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -124,6 +126,91 @@ public:
|
|||||||
: QGenericReturnArgument(aName, static_cast<void *>(&aData))
|
: QGenericReturnArgument(aName, static_cast<void *>(&aData))
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct QMetaMethodArgument
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
const void *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QMetaMethodReturnArgument
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
void *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace QtPrivate {
|
||||||
|
namespace Invoke {
|
||||||
|
#if QT_VERSION <= QT_VERSION_CHECK(7, 0, 0)
|
||||||
|
template <typename... Args> struct AreOldStyleArgs :
|
||||||
|
std::disjunction<std::is_base_of<QGenericArgument, Args>...>
|
||||||
|
{};
|
||||||
|
template <typename T, typename... Args> using IfNotOldStyleArgs =
|
||||||
|
std::enable_if_t<!AreOldStyleArgs<Args...>::value, T>;
|
||||||
|
#else
|
||||||
|
template <typename T, typename... Args> using IfNotOldStyleArgs = T;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <typename T> inline QMetaMethodArgument argument(const char *name, const T &t)
|
||||||
|
{
|
||||||
|
return { name, std::addressof(t) };
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> inline QMetaMethodReturnArgument returnArgument(const char *name, T &t)
|
||||||
|
{
|
||||||
|
return { name, std::addressof(t) };
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> inline const char *typenameHelper(const T &)
|
||||||
|
{
|
||||||
|
// duplicated from the QMetaTypeInterface, FIXME
|
||||||
|
static constexpr auto name = QtPrivate::typenameHelper<T>();
|
||||||
|
return name.data();
|
||||||
|
}
|
||||||
|
template <typename T> inline const void *dataHelper(const T &t)
|
||||||
|
{
|
||||||
|
return std::addressof(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const char *typenameHelper(QMetaMethodArgument a)
|
||||||
|
{ return a.name; }
|
||||||
|
inline const void *dataHelper(QMetaMethodArgument a)
|
||||||
|
{ return a.data; }
|
||||||
|
|
||||||
|
inline const char *typenameHelper(const char *) = delete;
|
||||||
|
template <typename T> inline const void *dataHelper(const char *) = delete;
|
||||||
|
inline const char *typenameHelper(const char16_t *) = delete;
|
||||||
|
template <typename T> inline const void *dataHelper(const char16_t *) = delete;
|
||||||
|
|
||||||
|
} // namespace QtPrivate::Invoke
|
||||||
|
|
||||||
|
template <typename... Args> inline auto invokeMethodHelper(QMetaMethodReturnArgument r, Args &&... arguments)
|
||||||
|
{
|
||||||
|
std::array params = { const_cast<const void *>(r.data), Invoke::dataHelper(arguments)... };
|
||||||
|
std::array names = { r.name, Invoke::typenameHelper(arguments)... };
|
||||||
|
static_assert(params.size() == names.size());
|
||||||
|
|
||||||
|
struct R {
|
||||||
|
decltype(params) parameters;
|
||||||
|
decltype(names) typeNames;
|
||||||
|
constexpr qsizetype parameterCount() const { return qsizetype(parameters.size()); }
|
||||||
|
};
|
||||||
|
return R { params, names };
|
||||||
|
}
|
||||||
|
} // namespace QtPrivate
|
||||||
|
|
||||||
|
template <typename T> inline QMetaMethodReturnArgument qReturnArg(T &&) = delete;
|
||||||
|
template <typename T> inline QMetaMethodReturnArgument qReturnArg(T &data)
|
||||||
|
{
|
||||||
|
if constexpr (std::is_same_v<T, const char *>) {
|
||||||
|
// need to go around the = delete above
|
||||||
|
return QtPrivate::Invoke::returnArgument("const char *", data);
|
||||||
|
} else {
|
||||||
|
const char *name = QtPrivate::Invoke::typenameHelper(data);
|
||||||
|
return QtPrivate::Invoke::returnArgument(name, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct Q_CORE_EXPORT QMetaObject
|
struct Q_CORE_EXPORT QMetaObject
|
||||||
{
|
{
|
||||||
@ -191,6 +278,7 @@ struct Q_CORE_EXPORT QMetaObject
|
|||||||
static void activate(QObject *sender, const QMetaObject *, int local_signal_index, void **argv);
|
static void activate(QObject *sender, const QMetaObject *, int local_signal_index, void **argv);
|
||||||
static void activate(QObject *sender, int signal_offset, int local_signal_index, void **argv);
|
static void activate(QObject *sender, int signal_offset, int local_signal_index, void **argv);
|
||||||
|
|
||||||
|
#if QT_VERSION <= QT_VERSION_CHECK(7, 0, 0)
|
||||||
static bool invokeMethod(QObject *obj, const char *member,
|
static bool invokeMethod(QObject *obj, const char *member,
|
||||||
Qt::ConnectionType,
|
Qt::ConnectionType,
|
||||||
QGenericReturnArgument ret,
|
QGenericReturnArgument ret,
|
||||||
@ -224,7 +312,7 @@ struct Q_CORE_EXPORT QMetaObject
|
|||||||
|
|
||||||
static inline bool invokeMethod(QObject *obj, const char *member,
|
static inline bool invokeMethod(QObject *obj, const char *member,
|
||||||
Qt::ConnectionType type,
|
Qt::ConnectionType type,
|
||||||
QGenericArgument val0 = QGenericArgument(nullptr),
|
QGenericArgument val0,
|
||||||
QGenericArgument val1 = QGenericArgument(),
|
QGenericArgument val1 = QGenericArgument(),
|
||||||
QGenericArgument val2 = QGenericArgument(),
|
QGenericArgument val2 = QGenericArgument(),
|
||||||
QGenericArgument val3 = QGenericArgument(),
|
QGenericArgument val3 = QGenericArgument(),
|
||||||
@ -240,7 +328,7 @@ struct Q_CORE_EXPORT QMetaObject
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline bool invokeMethod(QObject *obj, const char *member,
|
static inline bool invokeMethod(QObject *obj, const char *member,
|
||||||
QGenericArgument val0 = QGenericArgument(nullptr),
|
QGenericArgument val0,
|
||||||
QGenericArgument val1 = QGenericArgument(),
|
QGenericArgument val1 = QGenericArgument(),
|
||||||
QGenericArgument val2 = QGenericArgument(),
|
QGenericArgument val2 = QGenericArgument(),
|
||||||
QGenericArgument val3 = QGenericArgument(),
|
QGenericArgument val3 = QGenericArgument(),
|
||||||
@ -254,6 +342,41 @@ struct Q_CORE_EXPORT QMetaObject
|
|||||||
return invokeMethod(obj, member, Qt::AutoConnection, QGenericReturnArgument(), val0,
|
return invokeMethod(obj, member, Qt::AutoConnection, QGenericReturnArgument(), val0,
|
||||||
val1, val2, val3, val4, val5, val6, val7, val8, val9);
|
val1, val2, val3, val4, val5, val6, val7, val8, val9);
|
||||||
}
|
}
|
||||||
|
#endif // Qt < 7.0
|
||||||
|
|
||||||
|
template <typename... Args> static
|
||||||
|
QtPrivate::Invoke::IfNotOldStyleArgs<bool, Args...>
|
||||||
|
invokeMethod(QObject *obj, const char *member, Qt::ConnectionType c,
|
||||||
|
QMetaMethodReturnArgument r, Args &&... arguments)
|
||||||
|
{
|
||||||
|
auto h = QtPrivate::invokeMethodHelper(r, std::forward<Args>(arguments)...);
|
||||||
|
return invokeMethodImpl(obj, member, c, h.parameterCount(), h.parameters.data(),
|
||||||
|
h.typeNames.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Args> static
|
||||||
|
QtPrivate::Invoke::IfNotOldStyleArgs<bool, Args...>
|
||||||
|
invokeMethod(QObject *obj, const char *member, Qt::ConnectionType c, Args &&... arguments)
|
||||||
|
{
|
||||||
|
QMetaMethodReturnArgument r = {};
|
||||||
|
return invokeMethod(obj, member, c, r, std::forward<Args>(arguments)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Args> static
|
||||||
|
QtPrivate::Invoke::IfNotOldStyleArgs<bool, Args...>
|
||||||
|
invokeMethod(QObject *obj, const char *member, QMetaMethodReturnArgument r,
|
||||||
|
Args &&... arguments)
|
||||||
|
{
|
||||||
|
return invokeMethod(obj, member, Qt::AutoConnection, r, std::forward<Args>(arguments)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Args> static
|
||||||
|
QtPrivate::Invoke::IfNotOldStyleArgs<bool, Args...>
|
||||||
|
invokeMethod(QObject *obj, const char *member, Args &&... arguments)
|
||||||
|
{
|
||||||
|
QMetaMethodReturnArgument r = {};
|
||||||
|
return invokeMethod(obj, member, Qt::AutoConnection, r, std::forward<Args>(arguments)...);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef Q_CLANG_QDOC
|
#ifdef Q_CLANG_QDOC
|
||||||
template<typename Functor, typename FunctorReturnType>
|
template<typename Functor, typename FunctorReturnType>
|
||||||
@ -336,7 +459,8 @@ struct Q_CORE_EXPORT QMetaObject
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QObject *newInstance(QGenericArgument val0 = QGenericArgument(nullptr),
|
#if QT_VERSION <= QT_VERSION_CHECK(7, 0, 0)
|
||||||
|
QObject *newInstance(QGenericArgument val0,
|
||||||
QGenericArgument val1 = QGenericArgument(),
|
QGenericArgument val1 = QGenericArgument(),
|
||||||
QGenericArgument val2 = QGenericArgument(),
|
QGenericArgument val2 = QGenericArgument(),
|
||||||
QGenericArgument val3 = QGenericArgument(),
|
QGenericArgument val3 = QGenericArgument(),
|
||||||
@ -346,6 +470,14 @@ struct Q_CORE_EXPORT QMetaObject
|
|||||||
QGenericArgument val7 = QGenericArgument(),
|
QGenericArgument val7 = QGenericArgument(),
|
||||||
QGenericArgument val8 = QGenericArgument(),
|
QGenericArgument val8 = QGenericArgument(),
|
||||||
QGenericArgument val9 = QGenericArgument()) const;
|
QGenericArgument val9 = QGenericArgument()) const;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <typename... Args> QtPrivate::Invoke::IfNotOldStyleArgs<QObject *, Args...>
|
||||||
|
newInstance(Args &&... arguments) const
|
||||||
|
{
|
||||||
|
auto h = QtPrivate::invokeMethodHelper(QMetaMethodReturnArgument{}, std::forward<Args>(arguments)...);
|
||||||
|
return newInstanceImpl(this, h.parameterCount(), h.parameters.data(), h.typeNames.data());
|
||||||
|
}
|
||||||
|
|
||||||
enum Call {
|
enum Call {
|
||||||
InvokeMetaMethod,
|
InvokeMetaMethod,
|
||||||
@ -405,7 +537,11 @@ struct Q_CORE_EXPORT QMetaObject
|
|||||||
} d;
|
} d;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static bool invokeMethodImpl(QObject *object, const char *member, Qt::ConnectionType type,
|
||||||
|
qsizetype parameterCount, const void *const *parameters, const char *const *names);
|
||||||
static bool invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *slot, Qt::ConnectionType type, void *ret);
|
static bool invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *slot, Qt::ConnectionType type, void *ret);
|
||||||
|
static QObject *newInstanceImpl(const QMetaObject *mobj, qsizetype parameterCount,
|
||||||
|
const void **parameters, const char **typeNames);
|
||||||
friend class QTimer;
|
friend class QTimer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -732,12 +732,12 @@ void tst_qmessagehandler::qMessagePattern_data()
|
|||||||
// Q_OBJECT macro hence the ?helper? frame
|
// Q_OBJECT macro hence the ?helper? frame
|
||||||
"[MyClass::myFunction|MyClass::mySlot1|?" BACKTRACE_HELPER_NAME "?|",
|
"[MyClass::myFunction|MyClass::mySlot1|?" BACKTRACE_HELPER_NAME "?|",
|
||||||
|
|
||||||
// QMetaObject::invokeMethod calls internal function
|
// QMetaObject::invokeMethodImpl calls internal function
|
||||||
// (QMetaMethodPrivate::invokeImpl, at the tims of this writing), which
|
// (QMetaMethodPrivate::invokeImpl, at the tims of this writing), which
|
||||||
// will usually show only as ?libQt6Core.so? or equivalent, so we skip
|
// will usually show only as ?libQt6Core.so? or equivalent, so we skip
|
||||||
|
|
||||||
// end of backtrace, actual message
|
// end of backtrace, actual message
|
||||||
"|" QT_NAMESPACE_STR "QMetaObject::invokeMethod] from_a_function 34"
|
"|" QT_NAMESPACE_STR "QMetaObject::invokeMethodImpl] from_a_function 34"
|
||||||
};
|
};
|
||||||
QTest::newRow("backtrace") << "[%{backtrace}] %{message}" << true << expectedBacktrace;
|
QTest::newRow("backtrace") << "[%{backtrace}] %{message}" << true << expectedBacktrace;
|
||||||
#endif
|
#endif
|
||||||
|
@ -20,3 +20,11 @@ qt_internal_add_test(tst_qmetaobject
|
|||||||
Qt::CorePrivate
|
Qt::CorePrivate
|
||||||
)
|
)
|
||||||
|
|
||||||
|
qt_internal_add_test(tst_qmetaobject_compat
|
||||||
|
SOURCES
|
||||||
|
${tst_qmetaobject_SOURCES}
|
||||||
|
DEFINES
|
||||||
|
USE_COMPAT_Q_ARG=1
|
||||||
|
PUBLIC_LIBRARIES
|
||||||
|
Qt::CorePrivate
|
||||||
|
)
|
||||||
|
@ -14,6 +14,23 @@ Q_DECLARE_METATYPE(const QMetaObject *)
|
|||||||
|
|
||||||
#include "forwarddeclared.h"
|
#include "forwarddeclared.h"
|
||||||
|
|
||||||
|
#ifdef USE_COMPAT_Q_ARG
|
||||||
|
# define tst_QMetaObject tst_QMetaObject_CompatQArg
|
||||||
|
# if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0)
|
||||||
|
# error "This is a Qt 6 compatibility check test"
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# undef Q_ARG
|
||||||
|
# undef Q_RETURN_ARG
|
||||||
|
# define Q_ARG(type, data) QArgument<type >(#type, data)
|
||||||
|
# define Q_RETURN_ARG(type, data) QReturnArgument<type >(#type, data)
|
||||||
|
# define Q_NO_ARG , QGenericArgument()
|
||||||
|
#else
|
||||||
|
// This macro is used to force the overload selection to the compat
|
||||||
|
// (non-variadic) code above
|
||||||
|
# define Q_NO_ARG
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef QEASINGCURVE_H
|
#ifdef QEASINGCURVE_H
|
||||||
# error "Please make sure qeasingcurve.h is not #include'd here! " \
|
# error "Please make sure qeasingcurve.h is not #include'd here! " \
|
||||||
"We need QEasingCurve to be only forward-declared."
|
"We need QEasingCurve to be only forward-declared."
|
||||||
@ -279,13 +296,17 @@ public:
|
|||||||
private slots:
|
private slots:
|
||||||
void connectSlotsByName();
|
void connectSlotsByName();
|
||||||
void invokeMetaMember();
|
void invokeMetaMember();
|
||||||
|
void invokeMetaMemberNoMacros();
|
||||||
void invokePointer();
|
void invokePointer();
|
||||||
void invokeQueuedMetaMember();
|
void invokeQueuedMetaMember();
|
||||||
|
void invokeQueuedMetaMemberNoMacro();
|
||||||
void invokeQueuedPointer();
|
void invokeQueuedPointer();
|
||||||
void invokeBlockingQueuedMetaMember();
|
void invokeBlockingQueuedMetaMember();
|
||||||
|
void invokeBlockingQueuedMetaMemberNoMacros();
|
||||||
void invokeBlockingQueuedPointer();
|
void invokeBlockingQueuedPointer();
|
||||||
void invokeCustomTypes();
|
void invokeCustomTypes();
|
||||||
void invokeMetaConstructor();
|
void invokeMetaConstructor();
|
||||||
|
void invokeMetaConstructorNoMacro();
|
||||||
void invokeTypedefTypes();
|
void invokeTypedefTypes();
|
||||||
void invokeException();
|
void invokeException();
|
||||||
void invokeQueuedAutoRegister();
|
void invokeQueuedAutoRegister();
|
||||||
@ -307,6 +328,7 @@ private slots:
|
|||||||
void classInfo();
|
void classInfo();
|
||||||
|
|
||||||
void metaMethod();
|
void metaMethod();
|
||||||
|
void metaMethodNoMacro();
|
||||||
|
|
||||||
void indexOfMethod_data();
|
void indexOfMethod_data();
|
||||||
void indexOfMethod();
|
void indexOfMethod();
|
||||||
@ -651,6 +673,7 @@ void QtTestObject::staticFunction0()
|
|||||||
qint64 QtTestObject::staticFunction1()
|
qint64 QtTestObject::staticFunction1()
|
||||||
{ staticResult = "staticFunction1"; return Q_INT64_C(123456789)*123456789; }
|
{ staticResult = "staticFunction1"; return Q_INT64_C(123456789)*123456789; }
|
||||||
|
|
||||||
|
// this test is duplicated below
|
||||||
void tst_QMetaObject::invokeMetaMember()
|
void tst_QMetaObject::invokeMetaMember()
|
||||||
{
|
{
|
||||||
QtTestObject obj;
|
QtTestObject obj;
|
||||||
@ -661,17 +684,17 @@ void tst_QMetaObject::invokeMetaMember()
|
|||||||
// Test nullptr
|
// Test nullptr
|
||||||
char *nullCharArray = nullptr;
|
char *nullCharArray = nullptr;
|
||||||
const char *nullConstCharArray = nullptr;
|
const char *nullConstCharArray = nullptr;
|
||||||
QVERIFY(!QMetaObject::invokeMethod(nullptr, nullCharArray));
|
QVERIFY(!QMetaObject::invokeMethod(nullptr, nullCharArray Q_NO_ARG));
|
||||||
QVERIFY(!QMetaObject::invokeMethod(nullptr, nullConstCharArray));
|
QVERIFY(!QMetaObject::invokeMethod(nullptr, nullConstCharArray Q_NO_ARG));
|
||||||
QVERIFY(!QMetaObject::invokeMethod(nullptr, "sl0"));
|
QVERIFY(!QMetaObject::invokeMethod(nullptr, "sl0" Q_NO_ARG));
|
||||||
QVERIFY(!QMetaObject::invokeMethod(&obj, nullCharArray));
|
QVERIFY(!QMetaObject::invokeMethod(&obj, nullCharArray Q_NO_ARG));
|
||||||
QVERIFY(!QMetaObject::invokeMethod(&obj, nullConstCharArray));
|
QVERIFY(!QMetaObject::invokeMethod(&obj, nullConstCharArray Q_NO_ARG));
|
||||||
QVERIFY(!QMetaObject::invokeMethod(&obj, nullCharArray, Qt::AutoConnection));
|
QVERIFY(!QMetaObject::invokeMethod(&obj, nullCharArray, Qt::AutoConnection Q_NO_ARG));
|
||||||
QVERIFY(!QMetaObject::invokeMethod(&obj, nullConstCharArray, Qt::AutoConnection));
|
QVERIFY(!QMetaObject::invokeMethod(&obj, nullConstCharArray, Qt::AutoConnection Q_NO_ARG));
|
||||||
QVERIFY(!QMetaObject::invokeMethod(&obj, nullCharArray, Qt::AutoConnection, QGenericReturnArgument()));
|
QVERIFY(!QMetaObject::invokeMethod(&obj, nullCharArray, Qt::AutoConnection, QGenericReturnArgument()));
|
||||||
QVERIFY(!QMetaObject::invokeMethod(&obj, nullConstCharArray, Qt::AutoConnection, QGenericReturnArgument()));
|
QVERIFY(!QMetaObject::invokeMethod(&obj, nullConstCharArray, Qt::AutoConnection, QGenericReturnArgument()));
|
||||||
|
|
||||||
QVERIFY(QMetaObject::invokeMethod(&obj, "sl0"));
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl0" Q_NO_ARG));
|
||||||
QCOMPARE(obj.slotResult, QString("sl0"));
|
QCOMPARE(obj.slotResult, QString("sl0"));
|
||||||
|
|
||||||
QVERIFY(QMetaObject::invokeMethod(&obj, "sl1", Q_ARG(QString, t1)));
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl1", Q_ARG(QString, t1)));
|
||||||
@ -710,17 +733,19 @@ void tst_QMetaObject::invokeMetaMember()
|
|||||||
Q_ARG(QString, t7), Q_ARG(QString, t8), Q_ARG(QString, t9)));
|
Q_ARG(QString, t7), Q_ARG(QString, t8), Q_ARG(QString, t9)));
|
||||||
QCOMPARE(obj.slotResult, QString("sl9:123456789"));
|
QCOMPARE(obj.slotResult, QString("sl9:123456789"));
|
||||||
|
|
||||||
QVERIFY(QMetaObject::invokeMethod(&obj, "sl11"));
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl11" Q_NO_ARG));
|
||||||
QCOMPARE(obj.slotResult, QString("sl11"));
|
QCOMPARE(obj.slotResult, QString("sl11"));
|
||||||
|
|
||||||
QVERIFY(QMetaObject::invokeMethod(&obj, "testSender"));
|
QVERIFY(QMetaObject::invokeMethod(&obj, "testSender" Q_NO_ARG));
|
||||||
QCOMPARE(obj.slotResult, QString("0x0"));
|
QCOMPARE(obj.slotResult, QString("0x0"));
|
||||||
|
|
||||||
QString refStr("whatever");
|
QString refStr("whatever");
|
||||||
|
#ifdef USE_COMPAT_Q_ARG
|
||||||
QVERIFY(QMetaObject::invokeMethod(&obj, "testReference", QGenericArgument("QString&", &refStr)));
|
QVERIFY(QMetaObject::invokeMethod(&obj, "testReference", QGenericArgument("QString&", &refStr)));
|
||||||
QCOMPARE(obj.slotResult, QString("testReference:whatever"));
|
QCOMPARE(obj.slotResult, QString("testReference:whatever"));
|
||||||
QCOMPARE(refStr, QString("gotcha"));
|
QCOMPARE(refStr, QString("gotcha"));
|
||||||
obj.slotResult.clear();
|
obj.slotResult.clear();
|
||||||
|
#endif
|
||||||
refStr = "whatever";
|
refStr = "whatever";
|
||||||
QVERIFY(QMetaObject::invokeMethod(&obj, "testReference", Q_ARG(QString&, refStr)));
|
QVERIFY(QMetaObject::invokeMethod(&obj, "testReference", Q_ARG(QString&, refStr)));
|
||||||
QCOMPARE(obj.slotResult, QString("testReference:whatever"));
|
QCOMPARE(obj.slotResult, QString("testReference:whatever"));
|
||||||
@ -800,7 +825,7 @@ void tst_QMetaObject::invokeMetaMember()
|
|||||||
QCOMPARE(obj.slotResult, "sl17");
|
QCOMPARE(obj.slotResult, "sl17");
|
||||||
|
|
||||||
// test overloads
|
// test overloads
|
||||||
QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot"));
|
QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot" Q_NO_ARG));
|
||||||
QCOMPARE(obj.slotResult, QString("overloadedSlot"));
|
QCOMPARE(obj.slotResult, QString("overloadedSlot"));
|
||||||
QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot", Q_ARG(int, 1)));
|
QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot", Q_ARG(int, 1)));
|
||||||
QCOMPARE(obj.slotResult, QString("overloadedSlot:1"));
|
QCOMPARE(obj.slotResult, QString("overloadedSlot:1"));
|
||||||
@ -808,7 +833,7 @@ void tst_QMetaObject::invokeMetaMember()
|
|||||||
QCOMPARE(obj.slotResult, QString("overloadedSlot:1,42"));
|
QCOMPARE(obj.slotResult, QString("overloadedSlot:1,42"));
|
||||||
|
|
||||||
//test signals
|
//test signals
|
||||||
QVERIFY(QMetaObject::invokeMethod(&obj, "sig0"));
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sig0" Q_NO_ARG));
|
||||||
QCOMPARE(obj.slotResult, QString("sl0"));
|
QCOMPARE(obj.slotResult, QString("sl0"));
|
||||||
|
|
||||||
QVERIFY(QMetaObject::invokeMethod(&obj, "sig1", Q_ARG(QString, "baba")));
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sig1", Q_ARG(QString, "baba")));
|
||||||
@ -838,6 +863,177 @@ void tst_QMetaObject::invokeMetaMember()
|
|||||||
QCOMPARE(obj.slotResult, QString("sl1:hehe"));
|
QCOMPARE(obj.slotResult, QString("sl1:hehe"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this is a copy-paste-adapt of the above
|
||||||
|
void tst_QMetaObject::invokeMetaMemberNoMacros()
|
||||||
|
{
|
||||||
|
QtTestObject obj;
|
||||||
|
|
||||||
|
QString t1("1"); QString t2("2"); QString t3("3"); QString t4("4"); QString t5("5");
|
||||||
|
QString t6("6"); QString t7("7"); QString t8("8"); QString t9("9"); QString t10("X");
|
||||||
|
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl0"));
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl0"));
|
||||||
|
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl1", t1));
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl1:1"));
|
||||||
|
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl2", qAsConst(t1), t2));
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl2:12"));
|
||||||
|
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl3", t1, t2, t3));
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl3:123"));
|
||||||
|
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl4", t1, t2, t3,
|
||||||
|
t4));
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl4:1234"));
|
||||||
|
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl5", t1, t2, t3,
|
||||||
|
t4, QStringLiteral("5")));
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl5:12345"));
|
||||||
|
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl6", t1, t2, t3,
|
||||||
|
t4, t5, t6));
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl6:123456"));
|
||||||
|
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl7", t1, t2, t3,
|
||||||
|
t4, t5, t6,
|
||||||
|
t7));
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl7:1234567"));
|
||||||
|
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl8", t1, t2, t3,
|
||||||
|
t4, t5, t6,
|
||||||
|
t7, t8));
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl8:12345678"));
|
||||||
|
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl9", t1, t2, t3,
|
||||||
|
t4, t5, t6,
|
||||||
|
t7, t8, t9));
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl9:123456789"));
|
||||||
|
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl11"));
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl11"));
|
||||||
|
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "testSender"));
|
||||||
|
QCOMPARE(obj.slotResult, QString("0x0"));
|
||||||
|
|
||||||
|
// this is not working for now
|
||||||
|
// QString refStr("whatever");
|
||||||
|
// QVERIFY(QMetaObject::invokeMethod(&obj, "testReference", refStr));
|
||||||
|
// QCOMPARE(obj.slotResult, QString("testReference:whatever"));
|
||||||
|
// QCOMPARE(refStr, QString("gotcha"));
|
||||||
|
|
||||||
|
qint64 ll1 = -1;
|
||||||
|
quint64 ll2 = 0;
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj,
|
||||||
|
"testLongLong",
|
||||||
|
ll1,
|
||||||
|
ll2));
|
||||||
|
QCOMPARE(obj.slotResult, QString("testLongLong:-1,0"));
|
||||||
|
|
||||||
|
QString exp;
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl1", qReturnArg(exp), QStringLiteral("bubu")));
|
||||||
|
QCOMPARE(exp, QString("yessir"));
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl1:bubu"));
|
||||||
|
|
||||||
|
QObject *ptr = nullptr;
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl11", qReturnArg(ptr)));
|
||||||
|
QCOMPARE(ptr, (QObject *)&obj);
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl11"));
|
||||||
|
// try again with a space:
|
||||||
|
ptr = nullptr;
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl11", qReturnArg(ptr)));
|
||||||
|
QCOMPARE(ptr, (QObject *)&obj);
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl11"));
|
||||||
|
|
||||||
|
const char *ptr2 = nullptr;
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl12", qReturnArg(ptr2)));
|
||||||
|
QVERIFY(ptr2 != nullptr);
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl12"));
|
||||||
|
// try again with a space:
|
||||||
|
ptr2 = nullptr;
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl12", qReturnArg(ptr2)));
|
||||||
|
QVERIFY(ptr2 != nullptr);
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl12"));
|
||||||
|
|
||||||
|
// test w/ template args
|
||||||
|
QList<QString> returnValue, argument;
|
||||||
|
argument << QString("one") << QString("two") << QString("three");
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl13",
|
||||||
|
qReturnArg(returnValue),
|
||||||
|
argument));
|
||||||
|
QCOMPARE(returnValue, argument);
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl13"));
|
||||||
|
|
||||||
|
// return qint64
|
||||||
|
qint64 return64;
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl14",
|
||||||
|
qReturnArg(return64)));
|
||||||
|
QCOMPARE(return64, Q_INT64_C(123456789)*123456789);
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl14"));
|
||||||
|
|
||||||
|
// pointers
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl15", &return64));
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl15"));
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl16", getForwardDeclaredPointer()));
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl16:notnull"));
|
||||||
|
|
||||||
|
obj.slotResult.clear();
|
||||||
|
qint64 *return64Ptr;
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl15", qReturnArg(return64Ptr), &return64));
|
||||||
|
QCOMPARE(return64Ptr, &return64);
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl15"));
|
||||||
|
|
||||||
|
obj.slotResult.clear();
|
||||||
|
MyForwardDeclaredType *forwardPtr = nullptr;
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl16", qReturnArg(forwardPtr),
|
||||||
|
forwardPtr));
|
||||||
|
QCOMPARE(forwardPtr, getForwardDeclaredPointer());
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl16:null"));
|
||||||
|
|
||||||
|
// forward-declared builtin
|
||||||
|
obj.slotResult.clear();
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl17", getEasingCurve()));
|
||||||
|
QCOMPARE(obj.slotResult, "sl17");
|
||||||
|
|
||||||
|
// test overloads
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot"));
|
||||||
|
QCOMPARE(obj.slotResult, QString("overloadedSlot"));
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot", 1));
|
||||||
|
QCOMPARE(obj.slotResult, QString("overloadedSlot:1"));
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot", 1, 42));
|
||||||
|
QCOMPARE(obj.slotResult, QString("overloadedSlot:1,42"));
|
||||||
|
|
||||||
|
//test signals
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sig0"));
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl0"));
|
||||||
|
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sig1", QStringLiteral("baba")));
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl1:baba"));
|
||||||
|
|
||||||
|
exp.clear();
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sig1", qReturnArg(exp), QStringLiteral("hehe")));
|
||||||
|
QCOMPARE(exp, QString("yessir"));
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl1:hehe"));
|
||||||
|
|
||||||
|
QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::doesNotExist()");
|
||||||
|
QVERIFY(!QMetaObject::invokeMethod(&obj, "doesNotExist"));
|
||||||
|
QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl1(QString)(QString)");
|
||||||
|
QVERIFY(!QMetaObject::invokeMethod(&obj, "sl1(QString)", QStringLiteral("arg")));
|
||||||
|
QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl3(QString)\n"
|
||||||
|
"Candidates are:\n sl3(QString,QString,QString)");
|
||||||
|
QVERIFY(!QMetaObject::invokeMethod(&obj, "sl3", QStringLiteral("arg")));
|
||||||
|
QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl1(QString,QString,QString)\n"
|
||||||
|
"Candidates are:\n sl1(QString)");
|
||||||
|
QVERIFY(!QMetaObject::invokeMethod(&obj, "sl1", QStringLiteral("arg"), QStringLiteral("arg"), QStringLiteral("arg")));
|
||||||
|
QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::testReference(QString)\n"
|
||||||
|
"Candidates are:\n testReference(QString&)");
|
||||||
|
QVERIFY(!QMetaObject::invokeMethod(&obj, "testReference", exp));
|
||||||
|
|
||||||
|
//should not have changed since last test.
|
||||||
|
QCOMPARE(exp, QString("yessir"));
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl1:hehe"));
|
||||||
|
}
|
||||||
|
|
||||||
void testFunction(){}
|
void testFunction(){}
|
||||||
|
|
||||||
|
|
||||||
@ -908,7 +1104,7 @@ void tst_QMetaObject::invokeQueuedMetaMember()
|
|||||||
{
|
{
|
||||||
QtTestObject obj;
|
QtTestObject obj;
|
||||||
|
|
||||||
QVERIFY(QMetaObject::invokeMethod(&obj, "sl0", Qt::QueuedConnection));
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl0", Qt::QueuedConnection Q_NO_ARG));
|
||||||
QVERIFY(obj.slotResult.isEmpty());
|
QVERIFY(obj.slotResult.isEmpty());
|
||||||
qApp->processEvents(QEventLoop::AllEvents);
|
qApp->processEvents(QEventLoop::AllEvents);
|
||||||
QCOMPARE(obj.slotResult, QString("sl0"));
|
QCOMPARE(obj.slotResult, QString("sl0"));
|
||||||
@ -942,7 +1138,7 @@ void tst_QMetaObject::invokeQueuedMetaMember()
|
|||||||
QCOMPARE(obj.slotResult, "sl17");
|
QCOMPARE(obj.slotResult, "sl17");
|
||||||
|
|
||||||
// test overloads
|
// test overloads
|
||||||
QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot", Qt::QueuedConnection));
|
QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot", Qt::QueuedConnection Q_NO_ARG));
|
||||||
qApp->processEvents(QEventLoop::AllEvents);
|
qApp->processEvents(QEventLoop::AllEvents);
|
||||||
QCOMPARE(obj.slotResult, QString("overloadedSlot"));
|
QCOMPARE(obj.slotResult, QString("overloadedSlot"));
|
||||||
QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot", Qt::QueuedConnection, Q_ARG(int, 1)));
|
QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot", Qt::QueuedConnection, Q_ARG(int, 1)));
|
||||||
@ -955,7 +1151,7 @@ void tst_QMetaObject::invokeQueuedMetaMember()
|
|||||||
// signals
|
// signals
|
||||||
|
|
||||||
obj.slotResult.clear();
|
obj.slotResult.clear();
|
||||||
QVERIFY(QMetaObject::invokeMethod(&obj, "sig0", Qt::QueuedConnection));
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sig0", Qt::QueuedConnection Q_NO_ARG));
|
||||||
QVERIFY(obj.slotResult.isEmpty());
|
QVERIFY(obj.slotResult.isEmpty());
|
||||||
qApp->processEvents(QEventLoop::AllEvents);
|
qApp->processEvents(QEventLoop::AllEvents);
|
||||||
QCOMPARE(obj.slotResult, QString("sl0"));
|
QCOMPARE(obj.slotResult, QString("sl0"));
|
||||||
@ -1013,6 +1209,119 @@ void tst_QMetaObject::invokeQueuedMetaMember()
|
|||||||
QVERIFY(obj.slotResult.isEmpty());
|
QVERIFY(obj.slotResult.isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this is a copy-paste-adapt of the above
|
||||||
|
void tst_QMetaObject::invokeQueuedMetaMemberNoMacro()
|
||||||
|
{
|
||||||
|
QtTestObject obj;
|
||||||
|
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl0", Qt::QueuedConnection));
|
||||||
|
QVERIFY(obj.slotResult.isEmpty());
|
||||||
|
qApp->processEvents(QEventLoop::AllEvents);
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl0"));
|
||||||
|
obj.slotResult = QString();
|
||||||
|
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl1", Qt::QueuedConnection, QString("hallo")));
|
||||||
|
QVERIFY(obj.slotResult.isEmpty());
|
||||||
|
qApp->processEvents(QEventLoop::AllEvents);
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl1:hallo"));
|
||||||
|
obj.slotResult = QString();
|
||||||
|
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl9", Qt::QueuedConnection, QStringLiteral("1"), QStringLiteral("2"),
|
||||||
|
QStringLiteral("3"), QStringLiteral("4"), QStringLiteral("5"),
|
||||||
|
QStringLiteral("6"), QStringLiteral("7"), QStringLiteral("8"),
|
||||||
|
QStringLiteral("9")));
|
||||||
|
QVERIFY(obj.slotResult.isEmpty());
|
||||||
|
qApp->processEvents(QEventLoop::AllEvents);
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl9:123456789"));
|
||||||
|
|
||||||
|
// pointers
|
||||||
|
qint64 return64;
|
||||||
|
obj.slotResult.clear();
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl15", Qt::QueuedConnection, &return64));
|
||||||
|
qApp->processEvents(QEventLoop::AllEvents);
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl15"));
|
||||||
|
|
||||||
|
// forward-declared builtin
|
||||||
|
obj.slotResult.clear();
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl17", Qt::QueuedConnection, getEasingCurve()));
|
||||||
|
qApp->processEvents(QEventLoop::AllEvents);
|
||||||
|
QCOMPARE(obj.slotResult, "sl17");
|
||||||
|
|
||||||
|
// test overloads
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot", Qt::QueuedConnection));
|
||||||
|
qApp->processEvents(QEventLoop::AllEvents);
|
||||||
|
QCOMPARE(obj.slotResult, QString("overloadedSlot"));
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot", Qt::QueuedConnection, 1));
|
||||||
|
qApp->processEvents(QEventLoop::AllEvents);
|
||||||
|
QCOMPARE(obj.slotResult, QString("overloadedSlot:1"));
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot", Qt::QueuedConnection, 1, 42));
|
||||||
|
qApp->processEvents(QEventLoop::AllEvents);
|
||||||
|
QCOMPARE(obj.slotResult, QString("overloadedSlot:1,42"));
|
||||||
|
|
||||||
|
// signals
|
||||||
|
|
||||||
|
obj.slotResult.clear();
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sig0", Qt::QueuedConnection));
|
||||||
|
QVERIFY(obj.slotResult.isEmpty());
|
||||||
|
qApp->processEvents(QEventLoop::AllEvents);
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl0"));
|
||||||
|
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sig1", Qt::QueuedConnection, QStringLiteral("gogo")));
|
||||||
|
qApp->processEvents(QEventLoop::AllEvents);
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl1:gogo"));
|
||||||
|
|
||||||
|
QString exp;
|
||||||
|
QTest::ignoreMessage(QtWarningMsg, "QMetaMethod::invoke: Unable to invoke methods with return values in queued connections");
|
||||||
|
QVERIFY(!QMetaObject::invokeMethod(&obj, "sig1", Qt::QueuedConnection, qReturnArg(exp),
|
||||||
|
QStringLiteral("nono")));
|
||||||
|
|
||||||
|
qint64 ll1 = -1;
|
||||||
|
quint64 ll2 = 0;
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj,
|
||||||
|
"testLongLong",
|
||||||
|
Qt::QueuedConnection,
|
||||||
|
ll1,
|
||||||
|
ll2));
|
||||||
|
qApp->processEvents(QEventLoop::AllEvents);
|
||||||
|
QCOMPARE(obj.slotResult, QString("testLongLong:-1,0"));
|
||||||
|
|
||||||
|
QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::testReference(QString)\n"
|
||||||
|
"Candidates are:\n testReference(QString&)");
|
||||||
|
QVERIFY(!QMetaObject::invokeMethod(&obj, "testReference", exp));
|
||||||
|
QCOMPARE(obj.slotResult, QString("testLongLong:-1,0"));
|
||||||
|
QVERIFY(exp.isEmpty());
|
||||||
|
|
||||||
|
// this doesn't work yet
|
||||||
|
// QString refStr = "whatever";
|
||||||
|
// QTest::ignoreMessage(QtWarningMsg, "QMetaMethod::invoke: Unable to handle unregistered datatype 'QString&'");
|
||||||
|
// QVERIFY(!QMetaObject::invokeMethod(&obj, "testReference", Qt::QueuedConnection, Q_ARG(QString&, refStr)));
|
||||||
|
// QCOMPARE(refStr, "whatever");
|
||||||
|
|
||||||
|
obj.slotResult.clear();
|
||||||
|
{
|
||||||
|
const MyForwardDeclaredType &t = getForwardDeclaredType();
|
||||||
|
QTest::ignoreMessage(QtWarningMsg, "QMetaMethod::invoke: Unable to handle unregistered datatype 'MyForwardDeclaredType'");
|
||||||
|
QVERIFY(!QMetaObject::invokeMethod(&obj, "slotWithUnregisteredParameterType", Qt::QueuedConnection, t));
|
||||||
|
QVERIFY(obj.slotResult.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
obj.slotResult.clear();
|
||||||
|
{
|
||||||
|
QString a1("Cannot happen");
|
||||||
|
const MyForwardDeclaredType &t = getForwardDeclaredType();
|
||||||
|
QTest::ignoreMessage(QtWarningMsg, "QMetaMethod::invoke: Unable to handle unregistered datatype 'MyForwardDeclaredType'");
|
||||||
|
QVERIFY(!QMetaObject::invokeMethod(&obj, "slotWithOneUnregisteredParameterType", Qt::QueuedConnection,
|
||||||
|
a1, t));
|
||||||
|
QVERIFY(obj.slotResult.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
obj.slotResult.clear();
|
||||||
|
QTest::ignoreMessage(QtWarningMsg, "QMetaMethod::invoke: Unable to handle unregistered datatype 'MyForwardDeclaredType*'");
|
||||||
|
QVERIFY(!QMetaObject::invokeMethod(&obj, "sl16", Qt::QueuedConnection, getForwardDeclaredPointer()));
|
||||||
|
qApp->processEvents(QEventLoop::AllEvents);
|
||||||
|
QVERIFY(obj.slotResult.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
void tst_QMetaObject::invokeQueuedPointer()
|
void tst_QMetaObject::invokeQueuedPointer()
|
||||||
{
|
{
|
||||||
QtTestObject obj;
|
QtTestObject obj;
|
||||||
@ -1062,7 +1371,7 @@ void tst_QMetaObject::invokeQueuedPointer()
|
|||||||
QCOMPARE(countedStructObjectsCount, 0);
|
QCOMPARE(countedStructObjectsCount, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this test is duplicated below
|
||||||
void tst_QMetaObject::invokeBlockingQueuedMetaMember()
|
void tst_QMetaObject::invokeBlockingQueuedMetaMember()
|
||||||
{
|
{
|
||||||
QThread t;
|
QThread t;
|
||||||
@ -1109,17 +1418,19 @@ void tst_QMetaObject::invokeBlockingQueuedMetaMember()
|
|||||||
Q_ARG(QString, t7), Q_ARG(QString, t8), Q_ARG(QString, t9)));
|
Q_ARG(QString, t7), Q_ARG(QString, t8), Q_ARG(QString, t9)));
|
||||||
QCOMPARE(obj.slotResult, QString("sl9:123456789"));
|
QCOMPARE(obj.slotResult, QString("sl9:123456789"));
|
||||||
|
|
||||||
QVERIFY(QMetaObject::invokeMethod(&obj, "sl11", Qt::BlockingQueuedConnection));
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl11", Qt::BlockingQueuedConnection Q_NO_ARG));
|
||||||
QCOMPARE(obj.slotResult, QString("sl11"));
|
QCOMPARE(obj.slotResult, QString("sl11"));
|
||||||
|
|
||||||
QVERIFY(QMetaObject::invokeMethod(&obj, "testSender", Qt::BlockingQueuedConnection));
|
QVERIFY(QMetaObject::invokeMethod(&obj, "testSender", Qt::BlockingQueuedConnection Q_NO_ARG));
|
||||||
QCOMPARE(obj.slotResult, QString("0x0"));
|
QCOMPARE(obj.slotResult, QString("0x0"));
|
||||||
|
|
||||||
QString refStr("whatever");
|
QString refStr("whatever");
|
||||||
|
#ifdef USE_COMPAT_Q_ARG
|
||||||
QVERIFY(QMetaObject::invokeMethod(&obj, "testReference", Qt::BlockingQueuedConnection, QGenericArgument("QString&", &refStr)));
|
QVERIFY(QMetaObject::invokeMethod(&obj, "testReference", Qt::BlockingQueuedConnection, QGenericArgument("QString&", &refStr)));
|
||||||
QCOMPARE(obj.slotResult, QString("testReference:whatever"));
|
QCOMPARE(obj.slotResult, QString("testReference:whatever"));
|
||||||
QCOMPARE(refStr, QString("gotcha"));
|
QCOMPARE(refStr, QString("gotcha"));
|
||||||
obj.slotResult.clear();
|
obj.slotResult.clear();
|
||||||
|
#endif
|
||||||
refStr = "whatever";
|
refStr = "whatever";
|
||||||
QVERIFY(QMetaObject::invokeMethod(&obj, "testReference", Qt::BlockingQueuedConnection, Q_ARG(QString&, refStr)));
|
QVERIFY(QMetaObject::invokeMethod(&obj, "testReference", Qt::BlockingQueuedConnection, Q_ARG(QString&, refStr)));
|
||||||
QCOMPARE(obj.slotResult, QString("testReference:whatever"));
|
QCOMPARE(obj.slotResult, QString("testReference:whatever"));
|
||||||
@ -1200,7 +1511,7 @@ void tst_QMetaObject::invokeBlockingQueuedMetaMember()
|
|||||||
QCOMPARE(obj.slotResult, "sl17");
|
QCOMPARE(obj.slotResult, "sl17");
|
||||||
|
|
||||||
// test overloads
|
// test overloads
|
||||||
QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot", Qt::BlockingQueuedConnection));
|
QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot", Qt::BlockingQueuedConnection Q_NO_ARG));
|
||||||
QCOMPARE(obj.slotResult, QString("overloadedSlot"));
|
QCOMPARE(obj.slotResult, QString("overloadedSlot"));
|
||||||
QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot", Qt::BlockingQueuedConnection, Q_ARG(int, 1)));
|
QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot", Qt::BlockingQueuedConnection, Q_ARG(int, 1)));
|
||||||
QCOMPARE(obj.slotResult, QString("overloadedSlot:1"));
|
QCOMPARE(obj.slotResult, QString("overloadedSlot:1"));
|
||||||
@ -1208,7 +1519,7 @@ void tst_QMetaObject::invokeBlockingQueuedMetaMember()
|
|||||||
QCOMPARE(obj.slotResult, QString("overloadedSlot:1,42"));
|
QCOMPARE(obj.slotResult, QString("overloadedSlot:1,42"));
|
||||||
|
|
||||||
//test signals
|
//test signals
|
||||||
QVERIFY(QMetaObject::invokeMethod(&obj, "sig0", Qt::BlockingQueuedConnection));
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sig0", Qt::BlockingQueuedConnection Q_NO_ARG));
|
||||||
QCOMPARE(obj.slotResult, QString("sl0"));
|
QCOMPARE(obj.slotResult, QString("sl0"));
|
||||||
|
|
||||||
QVERIFY(QMetaObject::invokeMethod(&obj, "sig1", Qt::BlockingQueuedConnection, Q_ARG(QString, "baba")));
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sig1", Qt::BlockingQueuedConnection, Q_ARG(QString, "baba")));
|
||||||
@ -1220,7 +1531,7 @@ void tst_QMetaObject::invokeBlockingQueuedMetaMember()
|
|||||||
QCOMPARE(obj.slotResult, QString("sl1:hehe"));
|
QCOMPARE(obj.slotResult, QString("sl1:hehe"));
|
||||||
|
|
||||||
QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::doesNotExist()");
|
QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::doesNotExist()");
|
||||||
QVERIFY(!QMetaObject::invokeMethod(&obj, "doesNotExist", Qt::BlockingQueuedConnection));
|
QVERIFY(!QMetaObject::invokeMethod(&obj, "doesNotExist", Qt::BlockingQueuedConnection Q_NO_ARG));
|
||||||
QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl1(QString)(QString)");
|
QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl1(QString)(QString)");
|
||||||
QVERIFY(!QMetaObject::invokeMethod(&obj, "sl1(QString)", Qt::BlockingQueuedConnection, Q_ARG(QString, "arg")));
|
QVERIFY(!QMetaObject::invokeMethod(&obj, "sl1(QString)", Qt::BlockingQueuedConnection, Q_ARG(QString, "arg")));
|
||||||
QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl3(QString)\n"
|
QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl3(QString)\n"
|
||||||
@ -1240,7 +1551,182 @@ void tst_QMetaObject::invokeBlockingQueuedMetaMember()
|
|||||||
QVERIFY(QMetaObject::invokeMethod(&obj, "moveToThread", Qt::BlockingQueuedConnection, Q_ARG(QThread*, QThread::currentThread())));
|
QVERIFY(QMetaObject::invokeMethod(&obj, "moveToThread", Qt::BlockingQueuedConnection, Q_ARG(QThread*, QThread::currentThread())));
|
||||||
t.quit();
|
t.quit();
|
||||||
QVERIFY(t.wait());
|
QVERIFY(t.wait());
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is a copy-paste-adapt of the above
|
||||||
|
void tst_QMetaObject::invokeBlockingQueuedMetaMemberNoMacros()
|
||||||
|
{
|
||||||
|
QThread t;
|
||||||
|
t.start();
|
||||||
|
QtTestObject obj;
|
||||||
|
obj.moveToThread(&t);
|
||||||
|
|
||||||
|
QString t1("1"); QString t2("2"); QString t3("3"); QString t4("4"); QString t5("5");
|
||||||
|
QString t6("6"); QString t7("7"); QString t8("8"); QString t9("9"); QString t10("X");
|
||||||
|
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl1", Qt::BlockingQueuedConnection, t1));
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl1:1"));
|
||||||
|
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl2", Qt::BlockingQueuedConnection, t1, t2));
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl2:12"));
|
||||||
|
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl3", Qt::BlockingQueuedConnection, t1, t2, t3));
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl3:123"));
|
||||||
|
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl4", Qt::BlockingQueuedConnection, t1, t2,
|
||||||
|
t3, t4));
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl4:1234"));
|
||||||
|
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl5", Qt::BlockingQueuedConnection, t1, t2,
|
||||||
|
t3, t4, QStringLiteral("5")));
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl5:12345"));
|
||||||
|
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl6", Qt::BlockingQueuedConnection, t1, t2,
|
||||||
|
t3, t4, t5, t6));
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl6:123456"));
|
||||||
|
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl7", Qt::BlockingQueuedConnection, t1, t2,
|
||||||
|
t3, t4, t5, t6,
|
||||||
|
t7));
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl7:1234567"));
|
||||||
|
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl8", Qt::BlockingQueuedConnection, t1, t2,
|
||||||
|
t3, t4, t5, t6,
|
||||||
|
t7, t8));
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl8:12345678"));
|
||||||
|
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl9", Qt::BlockingQueuedConnection, t1, t2,
|
||||||
|
t3, t4, t5, t6,
|
||||||
|
t7, t8, t9));
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl9:123456789"));
|
||||||
|
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl11", Qt::BlockingQueuedConnection));
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl11"));
|
||||||
|
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "testSender", Qt::BlockingQueuedConnection));
|
||||||
|
QCOMPARE(obj.slotResult, QString("0x0"));
|
||||||
|
|
||||||
|
// this is not working
|
||||||
|
// QString refStr("whatever");
|
||||||
|
// QVERIFY(QMetaObject::invokeMethod(&obj, "testReference", Qt::BlockingQueuedConnection, refStr));
|
||||||
|
// QCOMPARE(obj.slotResult, QString("testReference:whatever"));
|
||||||
|
// QCOMPARE(refStr, QString("gotcha"));
|
||||||
|
|
||||||
|
qint64 ll1 = -1;
|
||||||
|
quint64 ll2 = 0;
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj,
|
||||||
|
"testLongLong",
|
||||||
|
Qt::BlockingQueuedConnection,
|
||||||
|
ll1,
|
||||||
|
ll2));
|
||||||
|
QCOMPARE(obj.slotResult, QString("testLongLong:-1,0"));
|
||||||
|
|
||||||
|
QString exp;
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl1", Qt::BlockingQueuedConnection, qReturnArg(exp), QStringLiteral("bubu")));
|
||||||
|
QCOMPARE(exp, QString("yessir"));
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl1:bubu"));
|
||||||
|
|
||||||
|
QObject *ptr = nullptr;
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl11", Qt::BlockingQueuedConnection, qReturnArg(ptr)));
|
||||||
|
QCOMPARE(ptr, (QObject *)&obj);
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl11"));
|
||||||
|
// try again with a space:
|
||||||
|
ptr = nullptr;
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl11", Qt::BlockingQueuedConnection, qReturnArg(ptr)));
|
||||||
|
QCOMPARE(ptr, (QObject *)&obj);
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl11"));
|
||||||
|
|
||||||
|
const char *ptr2 = 0;
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl12", Qt::BlockingQueuedConnection, qReturnArg(ptr2)));
|
||||||
|
QVERIFY(ptr2 != 0);
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl12"));
|
||||||
|
// try again with a space:
|
||||||
|
ptr2 = 0;
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl12", Qt::BlockingQueuedConnection, qReturnArg(ptr2)));
|
||||||
|
QVERIFY(ptr2 != 0);
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl12"));
|
||||||
|
|
||||||
|
// test w/ template args
|
||||||
|
QList<QString> returnValue, argument;
|
||||||
|
argument << QString("one") << QString("two") << QString("three");
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl13", Qt::BlockingQueuedConnection,
|
||||||
|
qReturnArg(returnValue),
|
||||||
|
argument));
|
||||||
|
QCOMPARE(returnValue, argument);
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl13"));
|
||||||
|
|
||||||
|
// return qint64
|
||||||
|
qint64 return64;
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl14", Qt::BlockingQueuedConnection,
|
||||||
|
qReturnArg(return64)));
|
||||||
|
QCOMPARE(return64, Q_INT64_C(123456789)*123456789);
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl14"));
|
||||||
|
|
||||||
|
// pointers
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl15", Qt::BlockingQueuedConnection, &return64));
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl15"));
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl16", Qt::BlockingQueuedConnection, getForwardDeclaredPointer()));
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl16:notnull"));
|
||||||
|
|
||||||
|
obj.slotResult.clear();
|
||||||
|
qint64 *return64Ptr;
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl15", Qt::BlockingQueuedConnection, qReturnArg(return64Ptr), &return64));
|
||||||
|
QCOMPARE(return64Ptr, &return64);
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl15"));
|
||||||
|
|
||||||
|
obj.slotResult.clear();
|
||||||
|
MyForwardDeclaredType *forwardPtr = nullptr;
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl16", Qt::BlockingQueuedConnection, qReturnArg(forwardPtr),
|
||||||
|
forwardPtr));
|
||||||
|
QCOMPARE(forwardPtr, getForwardDeclaredPointer());
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl16:null"));
|
||||||
|
|
||||||
|
// forward-declared builtin
|
||||||
|
obj.slotResult.clear();
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl17", Qt::BlockingQueuedConnection, getEasingCurve()));
|
||||||
|
QCOMPARE(obj.slotResult, "sl17");
|
||||||
|
|
||||||
|
// test overloads
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot", Qt::BlockingQueuedConnection));
|
||||||
|
QCOMPARE(obj.slotResult, QString("overloadedSlot"));
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot", Qt::BlockingQueuedConnection, 1));
|
||||||
|
QCOMPARE(obj.slotResult, QString("overloadedSlot:1"));
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot", Qt::BlockingQueuedConnection, 1, 42));
|
||||||
|
QCOMPARE(obj.slotResult, QString("overloadedSlot:1,42"));
|
||||||
|
|
||||||
|
//test signals
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sig0", Qt::BlockingQueuedConnection));
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl0"));
|
||||||
|
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sig1", Qt::BlockingQueuedConnection, QStringLiteral("baba")));
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl1:baba"));
|
||||||
|
|
||||||
|
exp.clear();
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sig1", Qt::BlockingQueuedConnection, qReturnArg(exp), QStringLiteral("hehe")));
|
||||||
|
QCOMPARE(exp, QString("yessir"));
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl1:hehe"));
|
||||||
|
|
||||||
|
QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::doesNotExist()");
|
||||||
|
QVERIFY(!QMetaObject::invokeMethod(&obj, "doesNotExist", Qt::BlockingQueuedConnection));
|
||||||
|
QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl1(QString)(QString)");
|
||||||
|
QVERIFY(!QMetaObject::invokeMethod(&obj, "sl1(QString)", Qt::BlockingQueuedConnection, QStringLiteral("arg")));
|
||||||
|
QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl3(QString)\n"
|
||||||
|
"Candidates are:\n sl3(QString,QString,QString)");
|
||||||
|
QVERIFY(!QMetaObject::invokeMethod(&obj, "sl3", Qt::BlockingQueuedConnection, QStringLiteral("arg")));
|
||||||
|
QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl1(QString,QString,QString)\n"
|
||||||
|
"Candidates are:\n sl1(QString)");
|
||||||
|
QVERIFY(!QMetaObject::invokeMethod(&obj, "sl1", Qt::BlockingQueuedConnection, QStringLiteral("arg"), QStringLiteral("arg"), QStringLiteral("arg")));
|
||||||
|
QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::testReference(QString)\n"
|
||||||
|
"Candidates are:\n testReference(QString&)");
|
||||||
|
QVERIFY(!QMetaObject::invokeMethod(&obj, "testReference", Qt::BlockingQueuedConnection, exp));
|
||||||
|
|
||||||
|
//should not have changed since last test.
|
||||||
|
QCOMPARE(exp, QString("yessir"));
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl1:hehe"));
|
||||||
|
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "moveToThread", Qt::BlockingQueuedConnection, QThread::currentThread()));
|
||||||
|
t.quit();
|
||||||
|
QVERIFY(t.wait());
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QMetaObject::invokeBlockingQueuedPointer()
|
void tst_QMetaObject::invokeBlockingQueuedPointer()
|
||||||
@ -1366,6 +1852,10 @@ void tst_QMetaObject::invokeCustomTypes()
|
|||||||
QCOMPARE(obj.sum, 0);
|
QCOMPARE(obj.sum, 0);
|
||||||
QVERIFY(QMetaObject::invokeMethod(&obj, "sl1", Q_ARG(MyType, tp)));
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl1", Q_ARG(MyType, tp)));
|
||||||
QCOMPARE(obj.sum, 3);
|
QCOMPARE(obj.sum, 3);
|
||||||
|
|
||||||
|
obj.sum = 0;
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "sl1", tp));
|
||||||
|
QCOMPARE(obj.sum, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace NamespaceWithConstructibleClass
|
namespace NamespaceWithConstructibleClass
|
||||||
@ -1381,13 +1871,16 @@ public:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this test is duplicated below
|
||||||
void tst_QMetaObject::invokeMetaConstructor()
|
void tst_QMetaObject::invokeMetaConstructor()
|
||||||
{
|
{
|
||||||
const QMetaObject *mo = &QtTestObject::staticMetaObject;
|
const QMetaObject *mo = &QtTestObject::staticMetaObject;
|
||||||
|
#ifdef USE_COMPAT_Q_ARG
|
||||||
{
|
{
|
||||||
QObject *obj = mo->newInstance();
|
QObject *obj = mo->newInstance(QGenericArgument());
|
||||||
QVERIFY(!obj);
|
QVERIFY(!obj);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
QtTestObject obj;
|
QtTestObject obj;
|
||||||
QObject *obj2 = mo->newInstance(Q_ARG(QObject*, &obj));
|
QObject *obj2 = mo->newInstance(Q_ARG(QObject*, &obj));
|
||||||
@ -1430,6 +1923,38 @@ void tst_QMetaObject::invokeMetaConstructor()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this is a copy-paste-adapt of the above
|
||||||
|
void tst_QMetaObject::invokeMetaConstructorNoMacro()
|
||||||
|
{
|
||||||
|
const QMetaObject *mo = &QtTestObject::staticMetaObject;
|
||||||
|
{
|
||||||
|
QObject *obj = mo->newInstance();
|
||||||
|
QVERIFY(!obj);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
QtTestObject obj;
|
||||||
|
QObject *obj2 = mo->newInstance(static_cast<QObject *>(&obj));
|
||||||
|
QVERIFY(obj2 != 0);
|
||||||
|
QCOMPARE(obj2->parent(), (QObject*)&obj);
|
||||||
|
QVERIFY(qobject_cast<QtTestObject*>(obj2) != 0);
|
||||||
|
}
|
||||||
|
// class in namespace
|
||||||
|
const QMetaObject *nsmo = &NamespaceWithConstructibleClass::ConstructibleClass::staticMetaObject;
|
||||||
|
{
|
||||||
|
QtTestObject obj;
|
||||||
|
QObject *obj2 = nsmo->newInstance(static_cast<QObject *>(&obj));
|
||||||
|
QVERIFY(obj2 != 0);
|
||||||
|
QCOMPARE(obj2->parent(), (QObject*)&obj);
|
||||||
|
QVERIFY(qobject_cast<NamespaceWithConstructibleClass::ConstructibleClass*>(obj2) != 0);
|
||||||
|
}
|
||||||
|
// gadget shouldn't return a valid pointer
|
||||||
|
{
|
||||||
|
QCOMPARE(MyGadget::staticMetaObject.constructorCount(), 1);
|
||||||
|
QTest::ignoreMessage(QtWarningMsg, "QMetaObject::newInstance: type MyGadget does not inherit QObject");
|
||||||
|
QVERIFY(!MyGadget::staticMetaObject.newInstance());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void tst_QMetaObject::invokeTypedefTypes()
|
void tst_QMetaObject::invokeTypedefTypes()
|
||||||
{
|
{
|
||||||
qRegisterMetaType<CustomString>("CustomString");
|
qRegisterMetaType<CustomString>("CustomString");
|
||||||
@ -1457,6 +1982,14 @@ void tst_QMetaObject::invokeException()
|
|||||||
QFAIL("Did not throw");
|
QFAIL("Did not throw");
|
||||||
} catch(ObjectException &) {}
|
} catch(ObjectException &) {}
|
||||||
QCOMPARE(countedStructObjectsCount, 0);
|
QCOMPARE(countedStructObjectsCount, 0);
|
||||||
|
|
||||||
|
try {
|
||||||
|
CountedStruct s;
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(&obj, "throwingSlot", qReturnArg(s),
|
||||||
|
s, s));
|
||||||
|
QFAIL("Did not throw");
|
||||||
|
} catch(ObjectException &) {}
|
||||||
|
QCOMPARE(countedStructObjectsCount, 0);
|
||||||
#else
|
#else
|
||||||
QSKIP("Needs exceptions");
|
QSKIP("Needs exceptions");
|
||||||
#endif
|
#endif
|
||||||
@ -1478,6 +2011,18 @@ void tst_QMetaObject::invokeQueuedAutoRegister()
|
|||||||
qApp->processEvents(QEventLoop::AllEvents);
|
qApp->processEvents(QEventLoop::AllEvents);
|
||||||
QCOMPARE(obj.slotResult,
|
QCOMPARE(obj.slotResult,
|
||||||
QString("slotWithRegistrableArgument:myShared-myShared-myShared-myShared-00"));
|
QString("slotWithRegistrableArgument:myShared-myShared-myShared-myShared-00"));
|
||||||
|
|
||||||
|
obj.slotResult.clear();
|
||||||
|
QVERIFY(QMetaObject::invokeMethod(
|
||||||
|
&obj, "slotWithRegistrableArgument", Qt::QueuedConnection,
|
||||||
|
shared.data(), QPointer<QtTestObject>(shared.data()),
|
||||||
|
QSharedPointer<QtTestObject>(shared), QWeakPointer<QtTestObject>(shared),
|
||||||
|
QList<QtTestObject *>(),
|
||||||
|
QList<QtTestObject *>()));
|
||||||
|
QVERIFY(obj.slotResult.isEmpty());
|
||||||
|
qApp->processEvents(QEventLoop::AllEvents);
|
||||||
|
QCOMPARE(obj.slotResult,
|
||||||
|
QString("slotWithRegistrableArgument:myShared-myShared-myShared-myShared-00"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QMetaObject::normalizedSignature_data()
|
void tst_QMetaObject::normalizedSignature_data()
|
||||||
@ -1811,6 +2356,7 @@ void tst_QMetaObject::classInfo()
|
|||||||
QCOMPARE(QLatin1String(b.metaObject()->classInfo(index).value()), QLatin1String("Christopher Pike"));
|
QCOMPARE(QLatin1String(b.metaObject()->classInfo(index).value()), QLatin1String("Christopher Pike"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this test is duplicated below
|
||||||
void tst_QMetaObject::metaMethod()
|
void tst_QMetaObject::metaMethod()
|
||||||
{
|
{
|
||||||
QString str("foo");
|
QString str("foo");
|
||||||
@ -1863,6 +2409,59 @@ void tst_QMetaObject::metaMethod()
|
|||||||
QCOMPARE(obj.slotResult, QString("sl13"));
|
QCOMPARE(obj.slotResult, QString("sl13"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this is a copy-paste-adapt of the above
|
||||||
|
void tst_QMetaObject::metaMethodNoMacro()
|
||||||
|
{
|
||||||
|
QString str("foo");
|
||||||
|
QString ret("bar");
|
||||||
|
QMetaMethod method;
|
||||||
|
QVERIFY(!method.invoke(this));
|
||||||
|
QVERIFY(!method.invoke(this, str));
|
||||||
|
QVERIFY(!method.invoke(this, qReturnArg(ret), str));
|
||||||
|
QCOMPARE(str, QString("foo"));
|
||||||
|
QCOMPARE(ret, QString("bar"));
|
||||||
|
|
||||||
|
QtTestObject obj;
|
||||||
|
QString t1("1"); QString t2("2"); QString t3("3"); QString t4("4"); QString t5("5");
|
||||||
|
QString t6("6"); QString t7("7"); QString t8("8"); QString t9("9"); QString t10("X");
|
||||||
|
|
||||||
|
int index = QtTestObject::staticMetaObject.indexOfMethod("sl5(QString,QString,QString,QString,QString)");
|
||||||
|
QVERIFY(index > 0);
|
||||||
|
method = QtTestObject::staticMetaObject.method(index);
|
||||||
|
//wrong args
|
||||||
|
QTest::ignoreMessage(QtWarningMsg, "QMetaMethod::invoke: too few arguments (5) in call to QtTestObject::sl5(QString,QString,QString,QString,QString)");
|
||||||
|
QVERIFY(!method.invoke(&obj, QStringLiteral("1"), QStringLiteral("2"), QStringLiteral("3"), QStringLiteral("4")));
|
||||||
|
//QVERIFY(!method.invoke(&obj, "1", "2", "3", "4", "5", "6"));
|
||||||
|
//QVERIFY(!method.invoke(&obj, "1", "2", "3", "4", 5));
|
||||||
|
QTest::ignoreMessage(QtWarningMsg, "QMetaMethod::invokeMethod: return type mismatch for method "
|
||||||
|
"QtTestObject::sl5(QString,QString,QString,QString,QString): "
|
||||||
|
"cannot convert from void to QString during invocation");
|
||||||
|
QVERIFY(!method.invoke(&obj, qReturnArg(ret), QStringLiteral("1"), QStringLiteral("2"), QStringLiteral("3"), QStringLiteral("4"), QStringLiteral("5")));
|
||||||
|
|
||||||
|
//wrong object
|
||||||
|
//QVERIFY(!method.invoke(this, "1", "2", "3", "4", "5"));
|
||||||
|
QVERIFY(!method.invoke(0, QStringLiteral("1"), QStringLiteral("2"), QStringLiteral("3"), QStringLiteral("4"), QStringLiteral("5")));
|
||||||
|
QCOMPARE(ret, QString("bar"));
|
||||||
|
QCOMPARE(obj.slotResult, QString());
|
||||||
|
|
||||||
|
QVERIFY(method.invoke(&obj, QStringLiteral("1"), QStringLiteral("2"), QStringLiteral("3"), QStringLiteral("4"), QStringLiteral("5")));
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl5:12345"));
|
||||||
|
|
||||||
|
index = QtTestObject::staticMetaObject.indexOfMethod("sl13(QList<QString>)");
|
||||||
|
QVERIFY(index > 0);
|
||||||
|
QMetaMethod sl13 = QtTestObject::staticMetaObject.method(index);
|
||||||
|
QList<QString> returnValue, argument;
|
||||||
|
argument << QString("one") << QString("two") << QString("three");
|
||||||
|
//wrong object
|
||||||
|
//QVERIFY(!sl13.invoke(this, qReturnArg(returnValue), argument));
|
||||||
|
QVERIFY(!sl13.invoke(0, qReturnArg(returnValue), argument));
|
||||||
|
QVERIFY(returnValue.isEmpty());
|
||||||
|
|
||||||
|
QVERIFY(sl13.invoke(&obj, qReturnArg(returnValue), argument));
|
||||||
|
QCOMPARE(returnValue, argument);
|
||||||
|
QCOMPARE(obj.slotResult, QString("sl13"));
|
||||||
|
}
|
||||||
|
|
||||||
void tst_QMetaObject::indexOfMethod_data()
|
void tst_QMetaObject::indexOfMethod_data()
|
||||||
{
|
{
|
||||||
QTest::addColumn<QObject *>("object");
|
QTest::addColumn<QObject *>("object");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user