diff options
-rw-r--r-- | src/declarative/util/qdeclarativexmllistmodel.cpp | 296 |
1 files changed, 91 insertions, 205 deletions
diff --git a/src/declarative/util/qdeclarativexmllistmodel.cpp b/src/declarative/util/qdeclarativexmllistmodel.cpp index 9a74c04..983a25e 100644 --- a/src/declarative/util/qdeclarativexmllistmodel.cpp +++ b/src/declarative/util/qdeclarativexmllistmodel.cpp @@ -147,226 +147,114 @@ struct XmlQueryJob QString prefix; }; - -class QDeclarativeXmlQueryEngine; -class QDeclarativeXmlQueryThreadObject : public QObject +class QDeclarativeXmlQuery : public QObject { Q_OBJECT public: - QDeclarativeXmlQueryThreadObject(QDeclarativeXmlQueryEngine *); - - void processJobs(); - virtual bool event(QEvent *e); - -private: - QDeclarativeXmlQueryEngine *m_queryEngine; -}; - - -class QDeclarativeXmlQueryEngine : public QThread -{ - Q_OBJECT -public: - QDeclarativeXmlQueryEngine(QDeclarativeEngine *eng); - ~QDeclarativeXmlQueryEngine(); - - int doQuery(QString query, QString namespaces, QByteArray data, QList<QDeclarativeXmlListModelRole *>* roleObjects, QStringList keyRoleResultsCache); - void abort(int id); - - void processJobs(); - - static QDeclarativeXmlQueryEngine *instance(QDeclarativeEngine *engine); - -signals: - void queryCompleted(const QDeclarativeXmlQueryResult &); - void error(void*, const QString&); - -protected: - void run(); - -private: - void processQuery(XmlQueryJob *job); - void doQueryJob(XmlQueryJob *job, QDeclarativeXmlQueryResult *currentResult); - void doSubQueryJob(XmlQueryJob *job, QDeclarativeXmlQueryResult *currentResult); - void getValuesOfKeyRoles(const XmlQueryJob& currentJob, QStringList *values, QXmlQuery *query) const; - void addIndexToRangeList(QList<QDeclarativeXmlListRange> *ranges, int index) const; - - QMutex m_mutex; - QDeclarativeXmlQueryThreadObject *m_threadObject; - QList<XmlQueryJob> m_jobs; - QSet<int> m_cancelledJobs; - QAtomicInt m_queryIds; - - QDeclarativeEngine *m_engine; - QObject *m_eventLoopQuitHack; - - static QHash<QDeclarativeEngine *,QDeclarativeXmlQueryEngine*> queryEngines; - static QMutex queryEnginesMutex; -}; -QHash<QDeclarativeEngine *,QDeclarativeXmlQueryEngine*> QDeclarativeXmlQueryEngine::queryEngines; -QMutex QDeclarativeXmlQueryEngine::queryEnginesMutex; - - -QDeclarativeXmlQueryThreadObject::QDeclarativeXmlQueryThreadObject(QDeclarativeXmlQueryEngine *e) - : m_queryEngine(e) -{ -} - -void QDeclarativeXmlQueryThreadObject::processJobs() -{ - QCoreApplication::postEvent(this, new QEvent(QEvent::User)); -} - -bool QDeclarativeXmlQueryThreadObject::event(QEvent *e) -{ - if (e->type() == QEvent::User) { - m_queryEngine->processJobs(); - return true; - } else { - return QObject::event(e); + QDeclarativeXmlQuery(QObject *parent=0) + : QObject(parent), m_queryIds(XMLLISTMODEL_CLEAR_ID + 1) { + qRegisterMetaType<QDeclarativeXmlQueryResult>("QDeclarativeXmlQueryResult"); + moveToThread(&m_thread); + m_thread.start(QThread::IdlePriority); } -} - - - -QDeclarativeXmlQueryEngine::QDeclarativeXmlQueryEngine(QDeclarativeEngine *eng) -: QThread(eng), m_threadObject(0), m_queryIds(XMLLISTMODEL_CLEAR_ID + 1), m_engine(eng), m_eventLoopQuitHack(0) -{ - qRegisterMetaType<QDeclarativeXmlQueryResult>("QDeclarativeXmlQueryResult"); - - m_eventLoopQuitHack = new QObject; - m_eventLoopQuitHack->moveToThread(this); - connect(m_eventLoopQuitHack, SIGNAL(destroyed(QObject*)), SLOT(quit()), Qt::DirectConnection); - start(QThread::IdlePriority); -} - -QDeclarativeXmlQueryEngine::~QDeclarativeXmlQueryEngine() -{ - queryEnginesMutex.lock(); - queryEngines.remove(m_engine); - queryEnginesMutex.unlock(); - m_eventLoopQuitHack->deleteLater(); - wait(); -} - -int QDeclarativeXmlQueryEngine::doQuery(QString query, QString namespaces, QByteArray data, QList<QDeclarativeXmlListModelRole *>* roleObjects, QStringList keyRoleResultsCache) { - { - QMutexLocker m1(&m_mutex); - m_queryIds.ref(); - if (m_queryIds <= 0) - m_queryIds = 1; - } - - XmlQueryJob job; - job.queryId = m_queryIds; - job.data = data; - job.query = QLatin1String("doc($src)") + query; - job.namespaces = namespaces; - job.keyRoleResultsCache = keyRoleResultsCache; - - for (int i=0; i<roleObjects->count(); i++) { - if (!roleObjects->at(i)->isValid()) { - job.roleQueries << QString(); - continue; + ~QDeclarativeXmlQuery() { + if(m_thread.isRunning()) { + m_thread.quit(); + m_thread.wait(); } - job.roleQueries << roleObjects->at(i)->query(); - job.roleQueryErrorId << static_cast<void*>(roleObjects->at(i)); - if (roleObjects->at(i)->isKey()) - job.keyRoleQueries << job.roleQueries.last(); } - { + void abort(int id) { QMutexLocker ml(&m_mutex); - m_jobs.append(job); - if (m_threadObject) - m_threadObject->processJobs(); + if (id != -1) { + m_jobs.remove(id); + } } - return job.queryId; -} + int doQuery(QString query, QString namespaces, QByteArray data, QList<QDeclarativeXmlListModelRole *>* roleObjects, QStringList keyRoleResultsCache) { + { + QMutexLocker m1(&m_mutex); + m_queryIds.ref(); + if (m_queryIds <= 0) + m_queryIds = 1; + } -void QDeclarativeXmlQueryEngine::abort(int id) -{ - QMutexLocker ml(&m_mutex); - if (id != -1) { - m_cancelledJobs.insert(id); - if (m_threadObject) - m_threadObject->processJobs(); - } -} + XmlQueryJob job; + job.queryId = m_queryIds; + job.data = data; + job.query = QLatin1String("doc($src)") + query; + job.namespaces = namespaces; + job.keyRoleResultsCache = keyRoleResultsCache; + + for (int i=0; i<roleObjects->count(); i++) { + if (!roleObjects->at(i)->isValid()) { + job.roleQueries << QString(); + continue; + } + job.roleQueries << roleObjects->at(i)->query(); + job.roleQueryErrorId << static_cast<void*>(roleObjects->at(i)); + if (roleObjects->at(i)->isKey()) + job.keyRoleQueries << job.roleQueries.last(); + } -void QDeclarativeXmlQueryEngine::run() -{ - m_mutex.lock(); - m_threadObject = new QDeclarativeXmlQueryThreadObject(this); - m_mutex.unlock(); + { + QMutexLocker ml(&m_mutex); + m_jobs.insert(m_queryIds, job); + } - processJobs(); - exec(); + QMetaObject::invokeMethod(this, "processQuery", Qt::QueuedConnection, Q_ARG(int, job.queryId)); + return job.queryId; + } - delete m_threadObject; - m_threadObject = 0; -} +private slots: + void processQuery(int queryId) { + XmlQueryJob job; -void QDeclarativeXmlQueryEngine::processJobs() -{ - QMutexLocker locker(&m_mutex); + { + QMutexLocker ml(&m_mutex); + if (!m_jobs.contains(queryId)) + return; + job = m_jobs.value(queryId); + } - while (true) { - if (m_cancelledJobs.isEmpty() && m_jobs.isEmpty()) - return; + QDeclarativeXmlQueryResult result; + result.queryId = job.queryId; + doQueryJob(&job, &result); + doSubQueryJob(&job, &result); - if (!m_cancelledJobs.isEmpty()) { - for (QList<XmlQueryJob>::Iterator it = m_jobs.begin(); it != m_jobs.end(); ++it) { - int queryId = (*it).queryId; - if (m_cancelledJobs.remove(queryId)) - it = m_jobs.erase(it); + { + QMutexLocker ml(&m_mutex); + if (m_jobs.contains(queryId)) { + emit queryCompleted(result); + m_jobs.remove(queryId); } - m_cancelledJobs.clear(); } + } - if (!m_jobs.isEmpty()) { - XmlQueryJob currentJob = m_jobs.takeLast(); +Q_SIGNALS: + void queryCompleted(const QDeclarativeXmlQueryResult &); + void error(void*, const QString&); - locker.unlock(); - processQuery(¤tJob); - locker.relock(); - } - } -} +protected: -QDeclarativeXmlQueryEngine *QDeclarativeXmlQueryEngine::instance(QDeclarativeEngine *engine) -{ - queryEnginesMutex.lock(); - QDeclarativeXmlQueryEngine *queryEng = queryEngines.value(engine); - if (!queryEng) { - queryEng = new QDeclarativeXmlQueryEngine(engine); - queryEngines.insert(engine, queryEng); - } - queryEnginesMutex.unlock(); - return queryEng; -} +private: + void doQueryJob(XmlQueryJob *job, QDeclarativeXmlQueryResult *currentResult); + void doSubQueryJob(XmlQueryJob *job, QDeclarativeXmlQueryResult *currentResult); + void getValuesOfKeyRoles(const XmlQueryJob& currentJob, QStringList *values, QXmlQuery *query) const; + void addIndexToRangeList(QList<QDeclarativeXmlListRange> *ranges, int index) const; -void QDeclarativeXmlQueryEngine::processQuery(XmlQueryJob *job) -{ - QDeclarativeXmlQueryResult result; - result.queryId = job->queryId; - doQueryJob(job, &result); - doSubQueryJob(job, &result); +private: + QMutex m_mutex; + QThread m_thread; + QMap<int, XmlQueryJob> m_jobs; + QAtomicInt m_queryIds; +}; - { - QMutexLocker ml(&m_mutex); - if (m_cancelledJobs.contains(job->queryId)) { - m_cancelledJobs.remove(job->queryId); - } else { - emit queryCompleted(result); - } - } -} +Q_GLOBAL_STATIC(QDeclarativeXmlQuery, globalXmlQuery) -void QDeclarativeXmlQueryEngine::doQueryJob(XmlQueryJob *currentJob, QDeclarativeXmlQueryResult *currentResult) +void QDeclarativeXmlQuery::doQueryJob(XmlQueryJob *currentJob, QDeclarativeXmlQueryResult *currentResult) { Q_ASSERT(currentJob->queryId != -1); @@ -405,7 +293,7 @@ void QDeclarativeXmlQueryEngine::doQueryJob(XmlQueryJob *currentJob, QDeclarativ currentResult->size = (count > 0 ? count : 0); } -void QDeclarativeXmlQueryEngine::getValuesOfKeyRoles(const XmlQueryJob& currentJob, QStringList *values, QXmlQuery *query) const +void QDeclarativeXmlQuery::getValuesOfKeyRoles(const XmlQueryJob& currentJob, QStringList *values, QXmlQuery *query) const { const QStringList &keysQueries = currentJob.keyRoleQueries; QString keysQuery; @@ -426,7 +314,7 @@ void QDeclarativeXmlQueryEngine::getValuesOfKeyRoles(const XmlQueryJob& currentJ } } -void QDeclarativeXmlQueryEngine::addIndexToRangeList(QList<QDeclarativeXmlListRange> *ranges, int index) const { +void QDeclarativeXmlQuery::addIndexToRangeList(QList<QDeclarativeXmlListRange> *ranges, int index) const { if (ranges->isEmpty()) ranges->append(qMakePair(index, 1)); else if (ranges->last().first + ranges->last().second == index) @@ -435,7 +323,7 @@ void QDeclarativeXmlQueryEngine::addIndexToRangeList(QList<QDeclarativeXmlListRa ranges->append(qMakePair(index, 1)); } -void QDeclarativeXmlQueryEngine::doSubQueryJob(XmlQueryJob *currentJob, QDeclarativeXmlQueryResult *currentResult) +void QDeclarativeXmlQuery::doSubQueryJob(XmlQueryJob *currentJob, QDeclarativeXmlQueryResult *currentResult) { Q_ASSERT(currentJob->queryId != -1); @@ -695,6 +583,10 @@ void QDeclarativeXmlListModelPrivate::clear_role(QDeclarativeListProperty<QDecla QDeclarativeXmlListModel::QDeclarativeXmlListModel(QObject *parent) : QListModelInterface(*(new QDeclarativeXmlListModelPrivate), parent) { + connect(globalXmlQuery(), SIGNAL(queryCompleted(QDeclarativeXmlQueryResult)), + this, SLOT(queryCompleted(QDeclarativeXmlQueryResult))); + connect(globalXmlQuery(), SIGNAL(error(void*,QString)), + this, SLOT(queryError(void*,QString))); } QDeclarativeXmlListModel::~QDeclarativeXmlListModel() @@ -960,12 +852,6 @@ void QDeclarativeXmlListModel::classBegin() { Q_D(QDeclarativeXmlListModel); d->isComponentComplete = false; - - QDeclarativeXmlQueryEngine *queryEngine = QDeclarativeXmlQueryEngine::instance(qmlEngine(this)); - connect(queryEngine, SIGNAL(queryCompleted(QDeclarativeXmlQueryResult)), - SLOT(queryCompleted(QDeclarativeXmlQueryResult))); - connect(queryEngine, SIGNAL(error(void*,QString)), - SLOT(queryError(void*,QString))); } void QDeclarativeXmlListModel::componentComplete() @@ -995,7 +881,7 @@ void QDeclarativeXmlListModel::reload() if (!d->isComponentComplete) return; - QDeclarativeXmlQueryEngine::instance(qmlEngine(this))->abort(d->queryId); + globalXmlQuery()->abort(d->queryId); d->queryId = -1; if (d->size < 0) @@ -1011,7 +897,7 @@ void QDeclarativeXmlListModel::reload() } if (!d->xml.isEmpty()) { - d->queryId = QDeclarativeXmlQueryEngine::instance(qmlEngine(this))->doQuery(d->query, d->namespaces, d->xml.toUtf8(), &d->roleObjects, d->keyRoleResultsCache); + d->queryId = globalXmlQuery()->doQuery(d->query, d->namespaces, d->xml.toUtf8(), &d->roleObjects, d->keyRoleResultsCache); d->notifyQueryStarted(false); } else if (d->src.isEmpty()) { @@ -1072,7 +958,7 @@ void QDeclarativeXmlListModel::requestFinished() d->queryId = XMLLISTMODEL_CLEAR_ID; QTimer::singleShot(0, this, SLOT(dataCleared())); } else { - d->queryId = QDeclarativeXmlQueryEngine::instance(qmlEngine(this))->doQuery(d->query, d->namespaces, data, &d->roleObjects, d->keyRoleResultsCache); + d->queryId = globalXmlQuery()->doQuery(d->query, d->namespaces, data, &d->roleObjects, d->keyRoleResultsCache); } disconnect(d->reply, 0, this, 0); d->reply->deleteLater(); |