2
* Copyright (C) 2006 Justin Karneges <justin@affinix.com>
4
* This library is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU Lesser General Public
6
* License as published by the Free Software Foundation; either
7
* version 2.1 of the License, or (at your option) any later version.
9
* This library is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
* Lesser General Public License for more details.
14
* You should have received a copy of the GNU Lesser General Public
15
* License along with this library; if not, write to the Free Software
16
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
20
#include "qca_support.h"
23
#include <QMetaMethod>
24
#include <QMutexLocker>
25
#include <QWaitCondition>
29
QByteArray methodReturnType(const QMetaObject *obj, const QByteArray &method, const QList<QByteArray> argTypes)
31
for(int n = 0; n < obj->methodCount(); ++n)
33
QMetaMethod m = obj->method(n);
34
QByteArray sig = m.signature();
35
int offset = sig.indexOf('(');
38
QByteArray name = sig.mid(0, offset);
41
if(m.parameterTypes() != argTypes)
49
bool invokeMethodWithVariants(QObject *obj, const QByteArray &method, const QVariantList &args, QVariant *ret, Qt::ConnectionType type)
51
// QMetaObject::invokeMethod() has a 10 argument maximum
55
QList<QByteArray> argTypes;
56
for(int n = 0; n < args.count(); ++n)
57
argTypes += args[n].typeName();
61
QByteArray retTypeName = methodReturnType(obj->metaObject(), method, argTypes);
62
if(!retTypeName.isEmpty())
64
metatype = QMetaType::type(retTypeName.data());
65
if(metatype == 0) // lookup failed
69
QGenericArgument arg[10];
70
for(int n = 0; n < args.count(); ++n)
71
arg[n] = QGenericArgument(args[n].typeName(), args[n].constData());
73
QGenericReturnArgument retarg;
77
retval = QVariant(metatype, (const void *)0);
78
retarg = QGenericReturnArgument(retval.typeName(), retval.data());
81
if(!QMetaObject::invokeMethod(obj, method.data(), type, retarg, arg[0], arg[1], arg[2], arg[3], arg[4], arg[5], arg[6], arg[7], arg[8], arg[9]))
84
if(retval.isValid() && ret)
89
//----------------------------------------------------------------------------
91
//----------------------------------------------------------------------------
92
class SyncThreadAgent;
94
class SyncThread::Private : public QObject
102
SyncThreadAgent *agent;
106
Private(SyncThread *_q) : QObject(_q), q(_q)
113
void agent_started();
114
void agent_call_ret(bool success, const QVariant &ret);
117
class SyncThreadAgent : public QObject
121
SyncThreadAgent(QObject *parent = 0) : QObject(parent)
123
QMetaObject::invokeMethod(this, "started", Qt::QueuedConnection);
128
void call_ret(bool success, const QVariant &ret);
131
void call_do(QObject *obj, const QByteArray &method, const QVariantList &args)
134
bool ok = invokeMethodWithVariants(obj, method, args, &ret, Qt::DirectConnection);
135
emit call_ret(ok, ret);
139
SyncThread::SyncThread(QObject *parent)
142
d = new Private(this);
143
qRegisterMetaType<QVariant>("QVariant");
144
qRegisterMetaType<QVariantList>("QVariantList");
147
SyncThread::~SyncThread()
153
void SyncThread::start()
155
QMutexLocker locker(&d->m);
161
void SyncThread::stop()
163
QMutexLocker locker(&d->m);
166
QMetaObject::invokeMethod(d->loop, "quit");
171
QVariant SyncThread::call(QObject *obj, const QByteArray &method, const QVariantList &args, bool *ok)
173
QMutexLocker locker(&d->m);
175
ret = QMetaObject::invokeMethod(d->agent, "call_do",
176
Qt::QueuedConnection, Q_ARG(QObject*, obj),
177
Q_ARG(QByteArray, method), Q_ARG(QVariantList, args));
181
*ok = d->last_success;
182
QVariant v = d->last_ret;
183
d->last_ret = QVariant();
187
void SyncThread::run()
190
d->loop = new QEventLoop;
191
d->agent = new SyncThreadAgent;
192
connect(d->agent, SIGNAL(started()), d, SLOT(agent_started()), Qt::DirectConnection);
193
connect(d->agent, SIGNAL(call_ret(bool, const QVariant &)), d, SLOT(agent_call_ret(bool, const QVariant &)), Qt::DirectConnection);
205
void SyncThread::Private::agent_started()
212
void SyncThread::Private::agent_call_ret(bool success, const QVariant &ret)
214
QMutexLocker locker(&m);
215
last_success = success;
222
#include "syncthread.moc"