/**************************************************************************** | |
** | |
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). | |
** All rights reserved. | |
** Contact: Nokia Corporation (qt-info@nokia.com) | |
** | |
** This file is part of the QtDeclarative module of the Qt Toolkit. | |
** | |
** $QT_BEGIN_LICENSE:LGPL$ | |
** GNU Lesser General Public License Usage | |
** This file may be used under the terms of the GNU Lesser General Public | |
** License version 2.1 as published by the Free Software Foundation and | |
** appearing in the file LICENSE.LGPL included in the packaging of this | |
** file. Please review the following information to ensure the GNU Lesser | |
** General Public License version 2.1 requirements will be met: | |
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. | |
** | |
** In addition, as a special exception, Nokia gives you certain additional | |
** rights. These rights are described in the Nokia Qt LGPL Exception | |
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. | |
** | |
** GNU General Public License Usage | |
** Alternatively, this file may be used under the terms of the GNU General | |
** Public License version 3.0 as published by the Free Software Foundation | |
** and appearing in the file LICENSE.GPL included in the packaging of this | |
** file. Please review the following information to ensure the GNU General | |
** Public License version 3.0 requirements will be met: | |
** http://www.gnu.org/copyleft/gpl.html. | |
** | |
** Other Usage | |
** Alternatively, this file may be used in accordance with the terms and | |
** conditions contained in a signed written agreement between you and Nokia. | |
** | |
** | |
** | |
** | |
** | |
** $QT_END_LICENSE$ | |
** | |
****************************************************************************/ | |
#include "private/qdeclarativeworkerscript_p.h" | |
#include "private/qdeclarativelistmodel_p.h" | |
#include "private/qdeclarativelistmodelworkeragent_p.h" | |
#include "private/qdeclarativeengine_p.h" | |
#include "private/qdeclarativeexpression_p.h" | |
#include <QtCore/qcoreevent.h> | |
#include <QtCore/qcoreapplication.h> | |
#include <QtCore/qdebug.h> | |
#include <QtScript/qscriptengine.h> | |
#include <QtCore/qmutex.h> | |
#include <QtCore/qwaitcondition.h> | |
#include <QtScript/qscriptvalueiterator.h> | |
#include <QtCore/qfile.h> | |
#include <QtCore/qdatetime.h> | |
#include <QtNetwork/qnetworkaccessmanager.h> | |
#include <QtDeclarative/qdeclarativeinfo.h> | |
#include "qdeclarativenetworkaccessmanagerfactory.h" | |
QT_BEGIN_NAMESPACE | |
class WorkerDataEvent : public QEvent | |
{ | |
public: | |
enum Type { WorkerData = QEvent::User }; | |
WorkerDataEvent(int workerId, const QVariant &data); | |
virtual ~WorkerDataEvent(); | |
int workerId() const; | |
QVariant data() const; | |
private: | |
int m_id; | |
QVariant m_data; | |
}; | |
class WorkerLoadEvent : public QEvent | |
{ | |
public: | |
enum Type { WorkerLoad = WorkerDataEvent::WorkerData + 1 }; | |
WorkerLoadEvent(int workerId, const QUrl &url); | |
int workerId() const; | |
QUrl url() const; | |
private: | |
int m_id; | |
QUrl m_url; | |
}; | |
class WorkerRemoveEvent : public QEvent | |
{ | |
public: | |
enum Type { WorkerRemove = WorkerLoadEvent::WorkerLoad + 1 }; | |
WorkerRemoveEvent(int workerId); | |
int workerId() const; | |
private: | |
int m_id; | |
}; | |
class WorkerErrorEvent : public QEvent | |
{ | |
public: | |
enum Type { WorkerError = WorkerRemoveEvent::WorkerRemove + 1 }; | |
WorkerErrorEvent(const QDeclarativeError &error); | |
QDeclarativeError error() const; | |
private: | |
QDeclarativeError m_error; | |
}; | |
class QDeclarativeWorkerScriptEnginePrivate : public QObject | |
{ | |
Q_OBJECT | |
public: | |
enum WorkerEventTypes { | |
WorkerDestroyEvent = QEvent::User + 100 | |
}; | |
QDeclarativeWorkerScriptEnginePrivate(QDeclarativeEngine *eng); | |
struct ScriptEngine : public QDeclarativeScriptEngine | |
{ | |
ScriptEngine(QDeclarativeWorkerScriptEnginePrivate *parent) : QDeclarativeScriptEngine(0), p(parent), accessManager(0) {} | |
~ScriptEngine() { delete accessManager; } | |
QDeclarativeWorkerScriptEnginePrivate *p; | |
QNetworkAccessManager *accessManager; | |
virtual QNetworkAccessManager *networkAccessManager() { | |
if (!accessManager) { | |
if (p->qmlengine && p->qmlengine->networkAccessManagerFactory()) { | |
accessManager = p->qmlengine->networkAccessManagerFactory()->create(this); | |
} else { | |
accessManager = new QNetworkAccessManager(this); | |
} | |
} | |
return accessManager; | |
} | |
}; | |
ScriptEngine *workerEngine; | |
static QDeclarativeWorkerScriptEnginePrivate *get(QScriptEngine *e) { | |
return static_cast<ScriptEngine *>(e)->p; | |
} | |
QDeclarativeEngine *qmlengine; | |
QMutex m_lock; | |
QWaitCondition m_wait; | |
struct WorkerScript { | |
WorkerScript(); | |
int id; | |
QUrl source; | |
bool initialized; | |
QDeclarativeWorkerScript *owner; | |
QScriptValue object; | |
QScriptValue callback; | |
}; | |
QHash<int, WorkerScript *> workers; | |
QScriptValue getWorker(int); | |
int m_nextId; | |
static QVariant scriptValueToVariant(const QScriptValue &); | |
static QScriptValue variantToScriptValue(const QVariant &, QScriptEngine *); | |
static QScriptValue onMessage(QScriptContext *ctxt, QScriptEngine *engine); | |
static QScriptValue sendMessage(QScriptContext *ctxt, QScriptEngine *engine); | |
signals: | |
void stopThread(); | |
protected: | |
virtual bool event(QEvent *); | |
private: | |
void processMessage(int, const QVariant &); | |
void processLoad(int, const QUrl &); | |
void reportScriptException(WorkerScript *); | |
}; | |
QDeclarativeWorkerScriptEnginePrivate::QDeclarativeWorkerScriptEnginePrivate(QDeclarativeEngine *engine) | |
: workerEngine(0), qmlengine(engine), m_nextId(0) | |
{ | |
} | |
QScriptValue QDeclarativeWorkerScriptEnginePrivate::onMessage(QScriptContext *ctxt, QScriptEngine *engine) | |
{ | |
QDeclarativeWorkerScriptEnginePrivate *p = QDeclarativeWorkerScriptEnginePrivate::get(engine); | |
int id = ctxt->thisObject().data().toVariant().toInt(); | |
WorkerScript *script = p->workers.value(id); | |
if (!script) | |
return engine->undefinedValue(); | |
if (ctxt->argumentCount() >= 1) | |
script->callback = ctxt->argument(0); | |
return script->callback; | |
} | |
QScriptValue QDeclarativeWorkerScriptEnginePrivate::sendMessage(QScriptContext *ctxt, QScriptEngine *engine) | |
{ | |
if (!ctxt->argumentCount()) | |
return engine->undefinedValue(); | |
QDeclarativeWorkerScriptEnginePrivate *p = QDeclarativeWorkerScriptEnginePrivate::get(engine); | |
int id = ctxt->thisObject().data().toVariant().toInt(); | |
WorkerScript *script = p->workers.value(id); | |
if (!script) | |
return engine->undefinedValue(); | |
QMutexLocker(&p->m_lock); | |
if (script->owner) | |
QCoreApplication::postEvent(script->owner, | |
new WorkerDataEvent(0, scriptValueToVariant(ctxt->argument(0)))); | |
return engine->undefinedValue(); | |
} | |
QScriptValue QDeclarativeWorkerScriptEnginePrivate::getWorker(int id) | |
{ | |
QHash<int, WorkerScript *>::ConstIterator iter = workers.find(id); | |
if (iter == workers.end()) | |
return workerEngine->nullValue(); | |
WorkerScript *script = *iter; | |
if (!script->initialized) { | |
script->initialized = true; | |
script->object = workerEngine->newObject(); | |
QScriptValue api = workerEngine->newObject(); | |
api.setData(script->id); | |
api.setProperty(QLatin1String("onMessage"), workerEngine->newFunction(onMessage), | |
QScriptValue::PropertyGetter | QScriptValue::PropertySetter); | |
api.setProperty(QLatin1String("sendMessage"), workerEngine->newFunction(sendMessage)); | |
script->object.setProperty(QLatin1String("WorkerScript"), api); | |
} | |
return script->object; | |
} | |
bool QDeclarativeWorkerScriptEnginePrivate::event(QEvent *event) | |
{ | |
if (event->type() == (QEvent::Type)WorkerDataEvent::WorkerData) { | |
WorkerDataEvent *workerEvent = static_cast<WorkerDataEvent *>(event); | |
processMessage(workerEvent->workerId(), workerEvent->data()); | |
return true; | |
} else if (event->type() == (QEvent::Type)WorkerLoadEvent::WorkerLoad) { | |
WorkerLoadEvent *workerEvent = static_cast<WorkerLoadEvent *>(event); | |
processLoad(workerEvent->workerId(), workerEvent->url()); | |
return true; | |
} else if (event->type() == (QEvent::Type)WorkerDestroyEvent) { | |
emit stopThread(); | |
return true; | |
} else { | |
return QObject::event(event); | |
} | |
} | |
void QDeclarativeWorkerScriptEnginePrivate::processMessage(int id, const QVariant &data) | |
{ | |
WorkerScript *script = workers.value(id); | |
if (!script) | |
return; | |
if (script->callback.isFunction()) { | |
QScriptValue args = workerEngine->newArray(1); | |
args.setProperty(0, variantToScriptValue(data, workerEngine)); | |
script->callback.call(script->object, args); | |
if (workerEngine->hasUncaughtException()) { | |
reportScriptException(script); | |
workerEngine->clearExceptions(); | |
} | |
} | |
} | |
void QDeclarativeWorkerScriptEnginePrivate::processLoad(int id, const QUrl &url) | |
{ | |
if (url.isRelative()) | |
return; | |
QString fileName = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url); | |
QFile f(fileName); | |
if (f.open(QIODevice::ReadOnly)) { | |
QByteArray data = f.readAll(); | |
QString sourceCode = QString::fromUtf8(data); | |
QScriptValue activation = getWorker(id); | |
QScriptContext *ctxt = QScriptDeclarativeClass::pushCleanContext(workerEngine); | |
QScriptValue urlContext = workerEngine->newObject(); | |
urlContext.setData(QScriptValue(workerEngine, url.toString())); | |
ctxt->pushScope(urlContext); | |
ctxt->pushScope(activation); | |
ctxt->setActivationObject(activation); | |
QDeclarativeScriptParser::extractPragmas(sourceCode); | |
workerEngine->baseUrl = url; | |
workerEngine->evaluate(sourceCode); | |
WorkerScript *script = workers.value(id); | |
if (script) { | |
script->source = url; | |
if (workerEngine->hasUncaughtException()) { | |
reportScriptException(script); | |
workerEngine->clearExceptions(); | |
} | |
} | |
workerEngine->popContext(); | |
} else { | |
qWarning().nospace() << "WorkerScript: Cannot find source file " << url.toString(); | |
} | |
} | |
void QDeclarativeWorkerScriptEnginePrivate::reportScriptException(WorkerScript *script) | |
{ | |
if (!script || !workerEngine->hasUncaughtException()) | |
return; | |
QDeclarativeError error; | |
QDeclarativeExpressionPrivate::exceptionToError(workerEngine, error); | |
error.setUrl(script->source); | |
QDeclarativeWorkerScriptEnginePrivate *p = QDeclarativeWorkerScriptEnginePrivate::get(workerEngine); | |
QMutexLocker(&p->m_lock); | |
if (script->owner) | |
QCoreApplication::postEvent(script->owner, new WorkerErrorEvent(error)); | |
} | |
QVariant QDeclarativeWorkerScriptEnginePrivate::scriptValueToVariant(const QScriptValue &value) | |
{ | |
if (value.isBool()) { | |
return QVariant(value.toBool()); | |
} else if (value.isString()) { | |
return QVariant(value.toString()); | |
} else if (value.isNumber()) { | |
return QVariant((qreal)value.toNumber()); | |
} else if (value.isDate()) { | |
return QVariant(value.toDateTime()); | |
#ifndef QT_NO_REGEXP | |
} else if (value.isRegExp()) { | |
return QVariant(value.toRegExp()); | |
#endif | |
} else if (value.isArray()) { | |
QVariantList list; | |
quint32 length = (quint32)value.property(QLatin1String("length")).toNumber(); | |
for (quint32 ii = 0; ii < length; ++ii) { | |
QVariant v = scriptValueToVariant(value.property(ii)); | |
list << v; | |
} | |
return QVariant(list); | |
} else if (value.isQObject()) { | |
QDeclarativeListModel *lm = qobject_cast<QDeclarativeListModel *>(value.toQObject()); | |
if (lm) { | |
QDeclarativeListModelWorkerAgent *agent = lm->agent(); | |
if (agent) { | |
QDeclarativeListModelWorkerAgent::VariantRef v(agent); | |
return qVariantFromValue(v); | |
} else { | |
return QVariant(); | |
} | |
} else { | |
// No other QObject's are allowed to be sent | |
return QVariant(); | |
} | |
} else if (value.isObject()) { | |
QVariantHash hash; | |
QScriptValueIterator iter(value); | |
while (iter.hasNext()) { | |
iter.next(); | |
hash.insert(iter.name(), scriptValueToVariant(iter.value())); | |
} | |
return QVariant(hash); | |
} | |
return QVariant(); | |
} | |
QScriptValue QDeclarativeWorkerScriptEnginePrivate::variantToScriptValue(const QVariant &value, QScriptEngine *engine) | |
{ | |
if (value.userType() == QVariant::Bool) { | |
return QScriptValue(value.toBool()); | |
} else if (value.userType() == QVariant::String) { | |
return QScriptValue(value.toString()); | |
} else if (value.userType() == QMetaType::QReal) { | |
return QScriptValue(value.toReal()); | |
} else if (value.userType() == QVariant::DateTime) { | |
return engine->newDate(value.toDateTime()); | |
#ifndef QT_NO_REGEXP | |
} else if (value.userType() == QVariant::RegExp) { | |
return engine->newRegExp(value.toRegExp()); | |
#endif | |
} else if (value.userType() == qMetaTypeId<QDeclarativeListModelWorkerAgent::VariantRef>()) { | |
QDeclarativeListModelWorkerAgent::VariantRef vr = qvariant_cast<QDeclarativeListModelWorkerAgent::VariantRef>(value); | |
if (vr.a->scriptEngine() == 0) | |
vr.a->setScriptEngine(engine); | |
else if (vr.a->scriptEngine() != engine) | |
return engine->nullValue(); | |
QScriptValue o = engine->newQObject(vr.a); | |
o.setData(engine->newVariant(value)); // Keeps the agent ref so that it is cleaned up on gc | |
return o; | |
} else if (value.userType() == QMetaType::QVariantList) { | |
QVariantList list = qvariant_cast<QVariantList>(value); | |
QScriptValue rv = engine->newArray(list.count()); | |
for (quint32 ii = 0; ii < quint32(list.count()); ++ii) | |
rv.setProperty(ii, variantToScriptValue(list.at(ii), engine)); | |
return rv; | |
} else if (value.userType() == QMetaType::QVariantHash) { | |
QVariantHash hash = qvariant_cast<QVariantHash>(value); | |
QScriptValue rv = engine->newObject(); | |
for (QVariantHash::ConstIterator iter = hash.begin(); iter != hash.end(); ++iter) | |
rv.setProperty(iter.key(), variantToScriptValue(iter.value(), engine)); | |
return rv; | |
} else { | |
return engine->nullValue(); | |
} | |
} | |
WorkerDataEvent::WorkerDataEvent(int workerId, const QVariant &data) | |
: QEvent((QEvent::Type)WorkerData), m_id(workerId), m_data(data) | |
{ | |
} | |
WorkerDataEvent::~WorkerDataEvent() | |
{ | |
} | |
int WorkerDataEvent::workerId() const | |
{ | |
return m_id; | |
} | |
QVariant WorkerDataEvent::data() const | |
{ | |
return m_data; | |
} | |
WorkerLoadEvent::WorkerLoadEvent(int workerId, const QUrl &url) | |
: QEvent((QEvent::Type)WorkerLoad), m_id(workerId), m_url(url) | |
{ | |
} | |
int WorkerLoadEvent::workerId() const | |
{ | |
return m_id; | |
} | |
QUrl WorkerLoadEvent::url() const | |
{ | |
return m_url; | |
} | |
WorkerRemoveEvent::WorkerRemoveEvent(int workerId) | |
: QEvent((QEvent::Type)WorkerRemove), m_id(workerId) | |
{ | |
} | |
int WorkerRemoveEvent::workerId() const | |
{ | |
return m_id; | |
} | |
WorkerErrorEvent::WorkerErrorEvent(const QDeclarativeError &error) | |
: QEvent((QEvent::Type)WorkerError), m_error(error) | |
{ | |
} | |
QDeclarativeError WorkerErrorEvent::error() const | |
{ | |
return m_error; | |
} | |
QDeclarativeWorkerScriptEngine::QDeclarativeWorkerScriptEngine(QDeclarativeEngine *parent) | |
: QThread(parent), d(new QDeclarativeWorkerScriptEnginePrivate(parent)) | |
{ | |
d->m_lock.lock(); | |
connect(d, SIGNAL(stopThread()), this, SLOT(quit()), Qt::DirectConnection); | |
start(QThread::IdlePriority); | |
d->m_wait.wait(&d->m_lock); | |
d->moveToThread(this); | |
d->m_lock.unlock(); | |
} | |
QDeclarativeWorkerScriptEngine::~QDeclarativeWorkerScriptEngine() | |
{ | |
d->m_lock.lock(); | |
qDeleteAll(d->workers); | |
d->workers.clear(); | |
QCoreApplication::postEvent(d, new QEvent((QEvent::Type)QDeclarativeWorkerScriptEnginePrivate::WorkerDestroyEvent)); | |
d->m_lock.unlock(); | |
wait(); | |
d->deleteLater(); | |
} | |
QDeclarativeWorkerScriptEnginePrivate::WorkerScript::WorkerScript() | |
: id(-1), initialized(false), owner(0) | |
{ | |
} | |
int QDeclarativeWorkerScriptEngine::registerWorkerScript(QDeclarativeWorkerScript *owner) | |
{ | |
QDeclarativeWorkerScriptEnginePrivate::WorkerScript *script = new QDeclarativeWorkerScriptEnginePrivate::WorkerScript; | |
script->id = d->m_nextId++; | |
script->owner = owner; | |
d->m_lock.lock(); | |
d->workers.insert(script->id, script); | |
d->m_lock.unlock(); | |
return script->id; | |
} | |
void QDeclarativeWorkerScriptEngine::removeWorkerScript(int id) | |
{ | |
QCoreApplication::postEvent(d, new WorkerRemoveEvent(id)); | |
} | |
void QDeclarativeWorkerScriptEngine::executeUrl(int id, const QUrl &url) | |
{ | |
QCoreApplication::postEvent(d, new WorkerLoadEvent(id, url)); | |
} | |
void QDeclarativeWorkerScriptEngine::sendMessage(int id, const QVariant &data) | |
{ | |
QCoreApplication::postEvent(d, new WorkerDataEvent(id, data)); | |
} | |
void QDeclarativeWorkerScriptEngine::run() | |
{ | |
d->m_lock.lock(); | |
d->workerEngine = new QDeclarativeWorkerScriptEnginePrivate::ScriptEngine(d); | |
d->m_wait.wakeAll(); | |
d->m_lock.unlock(); | |
exec(); | |
delete d->workerEngine; d->workerEngine = 0; | |
} | |
/*! | |
\qmlclass WorkerScript QDeclarativeWorkerScript | |
\ingroup qml-utility-elements | |
\brief The WorkerScript element enables the use of threads in QML. | |
Use WorkerScript to run operations in a new thread. | |
This is useful for running operations in the background so | |
that the main GUI thread is not blocked. | |
Messages can be passed between the new thread and the parent thread | |
using \l sendMessage() and the \l {WorkerScript::onMessage}{onMessage()} handler. | |
An example: | |
\snippet doc/src/snippets/declarative/workerscript.qml 0 | |
The above worker script specifies a JavaScript file, "script.js", that handles | |
the operations to be performed in the new thread. Here is \c script.js: | |
\quotefile doc/src/snippets/declarative/script.js | |
When the user clicks anywhere within the rectangle, \c sendMessage() is | |
called, triggering the \tt WorkerScript.onMessage() handler in | |
\tt script.js. This in turn sends a reply message that is then received | |
by the \tt onMessage() handler of \tt myWorker. | |
\section3 Restrictions | |
Since the \c WorkerScript.onMessage() function is run in a separate thread, the | |
JavaScript file is evaluated in a context separate from the main QML engine. This means | |
that unlike an ordinary JavaScript file that is imported into QML, the \c script.js | |
in the above example cannot access the properties, methods or other attributes | |
of the QML item, nor can it access any context properties set on the QML object | |
through QDeclarativeContext. | |
Additionally, there are restrictions on the types of values that can be passed to and | |
from the worker script. See the sendMessage() documentation for details. | |
\sa {declarative/threading/workerscript}{WorkerScript example}, | |
{declarative/threading/threadedlistmodel}{Threaded ListModel example} | |
*/ | |
QDeclarativeWorkerScript::QDeclarativeWorkerScript(QObject *parent) | |
: QObject(parent), m_engine(0), m_scriptId(-1), m_componentComplete(true) | |
{ | |
} | |
QDeclarativeWorkerScript::~QDeclarativeWorkerScript() | |
{ | |
if (m_scriptId != -1) m_engine->removeWorkerScript(m_scriptId); | |
} | |
/*! | |
\qmlproperty url WorkerScript::source | |
This holds the url of the JavaScript file that implements the | |
\tt WorkerScript.onMessage() handler for threaded operations. | |
*/ | |
QUrl QDeclarativeWorkerScript::source() const | |
{ | |
return m_source; | |
} | |
void QDeclarativeWorkerScript::setSource(const QUrl &source) | |
{ | |
if (m_source == source) | |
return; | |
m_source = source; | |
if (engine()) | |
m_engine->executeUrl(m_scriptId, m_source); | |
emit sourceChanged(); | |
} | |
/*! | |
\qmlmethod WorkerScript::sendMessage(jsobject message) | |
Sends the given \a message to a worker script handler in another | |
thread. The other worker script handler can receive this message | |
through the onMessage() handler. | |
The \c message object may only contain values of the following | |
types: | |
\list | |
\o boolean, number, string | |
\o JavaScript objects and arrays | |
\o ListModel objects (any other type of QObject* is not allowed) | |
\endlist | |
All objects and arrays are copied to the \c message. With the exception | |
of ListModel objects, any modifications by the other thread to an object | |
passed in \c message will not be reflected in the original object. | |
*/ | |
void QDeclarativeWorkerScript::sendMessage(const QScriptValue &message) | |
{ | |
if (!engine()) { | |
qWarning("QDeclarativeWorkerScript: Attempt to send message before WorkerScript establishment"); | |
return; | |
} | |
m_engine->sendMessage(m_scriptId, QDeclarativeWorkerScriptEnginePrivate::scriptValueToVariant(message)); | |
} | |
void QDeclarativeWorkerScript::classBegin() | |
{ | |
m_componentComplete = false; | |
} | |
QDeclarativeWorkerScriptEngine *QDeclarativeWorkerScript::engine() | |
{ | |
if (m_engine) return m_engine; | |
if (m_componentComplete) { | |
QDeclarativeEngine *engine = qmlEngine(this); | |
if (!engine) { | |
qWarning("QDeclarativeWorkerScript: engine() called without qmlEngine() set"); | |
return 0; | |
} | |
m_engine = QDeclarativeEnginePrivate::get(engine)->getWorkerScriptEngine(); | |
m_scriptId = m_engine->registerWorkerScript(this); | |
if (m_source.isValid()) | |
m_engine->executeUrl(m_scriptId, m_source); | |
return m_engine; | |
} | |
return 0; | |
} | |
void QDeclarativeWorkerScript::componentComplete() | |
{ | |
m_componentComplete = true; | |
engine(); // Get it started now. | |
} | |
/*! | |
\qmlsignal WorkerScript::onMessage(jsobject msg) | |
This handler is called when a message \a msg is received from a worker | |
script in another thread through a call to sendMessage(). | |
*/ | |
bool QDeclarativeWorkerScript::event(QEvent *event) | |
{ | |
if (event->type() == (QEvent::Type)WorkerDataEvent::WorkerData) { | |
QDeclarativeEngine *engine = qmlEngine(this); | |
if (engine) { | |
QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine); | |
WorkerDataEvent *workerEvent = static_cast<WorkerDataEvent *>(event); | |
QScriptValue value = | |
QDeclarativeWorkerScriptEnginePrivate::variantToScriptValue(workerEvent->data(), scriptEngine); | |
emit message(value); | |
} | |
return true; | |
} else if (event->type() == (QEvent::Type)WorkerErrorEvent::WorkerError) { | |
WorkerErrorEvent *workerEvent = static_cast<WorkerErrorEvent *>(event); | |
QDeclarativeEnginePrivate::warning(qmlEngine(this), workerEvent->error()); | |
return true; | |
} else { | |
return QObject::event(event); | |
} | |
} | |
QT_END_NAMESPACE | |
#include <qdeclarativeworkerscript.moc> | |