diff options
Diffstat (limited to 'src/imports')
31 files changed, 1376 insertions, 1440 deletions
diff --git a/src/imports/jsondb-listmodel/jsondb-listmodel.pro b/src/imports/jsondb-listmodel/jsondb-listmodel.pro index 9e86677..cfa60ad 100644 --- a/src/imports/jsondb-listmodel/jsondb-listmodel.pro +++ b/src/imports/jsondb-listmodel/jsondb-listmodel.pro @@ -18,6 +18,7 @@ INSTALLS += target qmldir qtPrepareTool(QMLPLUGINDUMP, qmlplugindump) QMLTYPESFILE = $$QT.jsondb.imports/$$TARGETPATH/plugin.qmltypes mac: !exists($$QMLPLUGINDUMP): QMLPLUGINDUMP = "$${QMLPLUGINDUMP}.app/Contents/MacOS/qmlplugindump" + unix:!mac: QMLPLUGINDUMP = "$${QMLPLUGINDUMP} -platform minimal" QMAKE_POST_LINK += LD_LIBRARY_PATH=$$QT.jsondb.libs $$QMLPLUGINDUMP QtAddOn.JsonDb 1.0 $$QT.jsondb.imports > $$QMLTYPESFILE qmltypes.files = $$QMLTYPESFILE @@ -27,19 +28,15 @@ INSTALLS += target qmldir VERSION = 1.0 -include(../../common/common.pri) - HEADERS += \ jsondb-listmodel.h \ jsondb-listmodel_p.h \ jsondb-component.h \ plugin.h -HEADERS += $$QSONCONVERSION_HEADERS - SOURCES += \ jsondb-listmodel.cpp \ jsondb-component.cpp \ plugin.cpp -SOURCES += $$QSONCONVERSION_SOURCES +OTHER_FILES += jsondb.json diff --git a/src/imports/jsondb-listmodel/jsondb.json b/src/imports/jsondb-listmodel/jsondb.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/src/imports/jsondb-listmodel/jsondb.json @@ -0,0 +1 @@ +{} diff --git a/src/imports/jsondb-listmodel/plugin.cpp b/src/imports/jsondb-listmodel/plugin.cpp index 3bd5763..28554c0 100644 --- a/src/imports/jsondb-listmodel/plugin.cpp +++ b/src/imports/jsondb-listmodel/plugin.cpp @@ -45,9 +45,6 @@ #include "jsondb-component.h" #include "jsondb-listmodel.h" -Q_EXPORT_STATIC_PLUGIN(JsonDbListModelPlugin) -Q_EXPORT_PLUGIN2(jsondblistmodelplugin, JsonDbListModelPlugin) - void JsonDbListModelPlugin::initializeEngine(QQmlEngine *engine, const char *uri) { Q_UNUSED(engine); diff --git a/src/imports/jsondb-listmodel/plugin.h b/src/imports/jsondb-listmodel/plugin.h index 68b28ab..e6e88b3 100644 --- a/src/imports/jsondb-listmodel/plugin.h +++ b/src/imports/jsondb-listmodel/plugin.h @@ -47,12 +47,12 @@ class JsonDbListModelPlugin : public QQmlExtensionPlugin { - Q_OBJECT + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface" FILE "jsondb.json") - public: - - void initializeEngine(QQmlEngine *engine, const char *uri); - void registerTypes(const char *uri); +public: + void initializeEngine(QQmlEngine *engine, const char *uri); + void registerTypes(const char *uri); }; #endif diff --git a/src/imports/jsondb/jsondatabase.cpp b/src/imports/jsondb/jsondatabase.cpp index 491fe85..3d78428 100644 --- a/src/imports/jsondb/jsondatabase.cpp +++ b/src/imports/jsondb/jsondatabase.cpp @@ -41,22 +41,15 @@ #include "jsondatabase.h" #include "jsondbpartition.h" -#include "jsondb-object.h" #include <QJSEngine> #include <QQmlEngine> +#include <qjsondbobject.h> +#include <qjsondbconnection.h> #include <qdebug.h> QT_BEGIN_NAMESPACE_JSONDB -struct Uuid -{ - uint data1; - ushort data2; - ushort data3; - uchar data4[8]; -}; - -static const Uuid JsonDbNamespace = {0x6ba7b810, 0x9dad, 0x11d1, { 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} }; +QPointer<QJsonDbConnection> JsonDatabase::connection(0); /*! \qmlclass JsonDatabase @@ -70,13 +63,6 @@ static const Uuid JsonDbNamespace = {0x6ba7b810, 0x9dad, 0x11d1, { 0x80, 0xb4, 0 JsonDatabase::JsonDatabase(QObject *parent) :QObject(parent) { - connect(&jsonDb, SIGNAL(response(int,const QVariant&)), - this, SLOT(dbResponse(int,const QVariant&)), - Qt::QueuedConnection); - connect(&jsonDb, SIGNAL(error(int,int,QString)), - this, SLOT(dbErrorResponse(int,int,QString)), - Qt::QueuedConnection); - } JsonDatabase::~JsonDatabase() @@ -133,9 +119,18 @@ void JsonDatabase::listPartitions(const QJSValue &listCallback) qWarning() << "Invalid callback specified."; return; } - QString query(QLatin1String("[?_type=\"Partition\"]")); - int id = jsonDb.query(query, 0, -1); - listCallbacks.insert(id, listCallback); + + QJsonDbReadRequest *request = new QJsonDbReadRequest; + request->setQuery(QLatin1String("[?_type=\"Partition\"]")); + request->setPartition(QLatin1String("Ephemeral")); + connect(request, SIGNAL(finished()), this, SLOT(onQueryFinished())); + connect(request, SIGNAL(finished()), request, SLOT(deleteLater())); + connect(request, SIGNAL(error(QtJsonDb::QJsonDbRequest::ErrorCode,QString)), + this, SLOT(onQueryError(QtJsonDb::QJsonDbRequest::ErrorCode,QString))); + connect(request, SIGNAL(error(QtJsonDb::QJsonDbRequest::ErrorCode,QString)), + request, SLOT(deleteLater())); + sharedConnection().send(request); + listCallbacks.insert(request, listCallback); } /*! @@ -156,29 +151,23 @@ void JsonDatabase::listPartitions(const QJSValue &listCallback) QString JsonDatabase::uuidFromString(const QString &identifier) { - const QUuid ns(JsonDbNamespace.data1, JsonDbNamespace.data2, JsonDbNamespace.data3, - JsonDbNamespace.data4[0], JsonDbNamespace.data4[1], JsonDbNamespace.data4[2], - JsonDbNamespace.data4[3], JsonDbNamespace.data4[4], JsonDbNamespace.data4[5], - JsonDbNamespace.data4[6], JsonDbNamespace.data4[7]); - return QUuid::createUuidV3(ns, identifier).toString(); + return QJsonDbObject::createUuidFromString(identifier).toString(); } -void JsonDatabase::dbResponse(int id, const QVariant &result) +void JsonDatabase::onQueryFinished() { - if (listCallbacks.contains(id)) { - // Make sure that id exists in the map. - QJSValue callback = listCallbacks[id]; + QJsonDbReadRequest *request = qobject_cast<QJsonDbReadRequest *>(sender()); + if (listCallbacks.contains(request)) { + QJSValue callback = listCallbacks[request]; QJSEngine *engine = callback.engine(); QJSValueList args; args << QJSValue(QJSValue::UndefinedValue); - QVariantMap objectMap = result.toMap(); - if (objectMap.contains(QLatin1String("data"))) { - QVariantList items = objectMap.value(QLatin1String("data")).toList(); - int count = items.count(); + QList<QJsonObject> objects = request->takeResults(); + int count = objects.count(); + if (count) { QJSValue response = engine->newArray(count); for (int i = 0; i < count; ++i) { - QVariantMap object = items.at(i).toMap(); - QString partitionName = object.value(QLatin1String("name")).toString(); + QString partitionName = objects[i].value(QLatin1String("name")).toString(); response.setProperty(i, engine->newQObject(partition(partitionName))); } args << response; @@ -186,14 +175,15 @@ void JsonDatabase::dbResponse(int id, const QVariant &result) args << engine->newArray(); } callback.call(args); - listCallbacks.remove(id); + listCallbacks.remove(request); } } -void JsonDatabase::dbErrorResponse(int id, int code, const QString &message) +void JsonDatabase::onQueryError(QtJsonDb::QJsonDbRequest::ErrorCode code, const QString &message) { - if (listCallbacks.contains(id)) { - QJSValue callback = listCallbacks[id]; + QJsonDbReadRequest *request = qobject_cast<QJsonDbReadRequest *>(sender()); + if (listCallbacks.contains(request)) { + QJSValue callback = listCallbacks[request]; QJSEngine *engine = callback.engine(); QJSValueList args; @@ -204,9 +194,19 @@ void JsonDatabase::dbErrorResponse(int id, int code, const QString &message) args << engine->toScriptValue(QVariant(error))<< engine->newArray(); callback.call(args); - listCallbacks.remove(id); + listCallbacks.remove(request); } } +QJsonDbConnection& JsonDatabase::sharedConnection() +{ + if (!connection) { + connection = QJsonDbConnection::defaultConnection(); + connection->connectToServer(); + } + return *connection; +} + + #include "moc_jsondatabase.cpp" QT_END_NAMESPACE_JSONDB diff --git a/src/imports/jsondb/jsondatabase.h b/src/imports/jsondb/jsondatabase.h index a1803a8..19ae5a4 100644 --- a/src/imports/jsondb/jsondatabase.h +++ b/src/imports/jsondb/jsondatabase.h @@ -45,7 +45,9 @@ #include <QObject> #include <QJSValue> #include <QPointer> -#include "jsondb-client.h" +#include <QMap> +#include <QJsonDbConnection> +#include <QJsonDbReadRequest> QT_BEGIN_NAMESPACE_JSONDB @@ -61,14 +63,15 @@ public: Q_INVOKABLE JsonDbPartition* partition(const QString &partitionName); Q_INVOKABLE void listPartitions(const QJSValue &callback); Q_INVOKABLE QString uuidFromString(const QString &identifier); + static QJsonDbConnection& sharedConnection(); private Q_SLOTS: - void dbResponse(int id, const QVariant &result); - void dbErrorResponse(int id, int code, const QString &message); + void onQueryFinished(); + void onQueryError(QtJsonDb::QJsonDbRequest::ErrorCode code, const QString &message); private: - QMap<int, QJSValue> listCallbacks; - JsonDbClient jsonDb; + QMap<QJsonDbReadRequest*, QJSValue> listCallbacks; + static QPointer<QJsonDbConnection> connection; }; QT_END_NAMESPACE_JSONDB diff --git a/src/imports/jsondb/jsondb.json b/src/imports/jsondb/jsondb.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/src/imports/jsondb/jsondb.json @@ -0,0 +1 @@ +{} diff --git a/src/imports/jsondb/jsondb.pro b/src/imports/jsondb/jsondb.pro index 781e3d1..1f6e7f4 100644 --- a/src/imports/jsondb/jsondb.pro +++ b/src/imports/jsondb/jsondb.pro @@ -3,9 +3,9 @@ TARGETPATH = QtJsonDb include(../qimportbase.pri) -QT += network qml jsondbcompat-private +QT += network qml jsondb jsondb-private -DESTDIR = $$QT.jsondbcompat.imports/$$TARGETPATH +DESTDIR = $$QT.jsondb.imports/$$TARGETPATH target.path = $$[QT_INSTALL_IMPORTS]/$$TARGETPATH qmldir.files += $$PWD/qmldir @@ -17,8 +17,9 @@ INSTALLS += target qmldir !cross_compile { qtPrepareTool(QMLPLUGINDUMP, qmlplugindump) mac: !exists($$QMLPLUGINDUMP): QMLPLUGINDUMP = "$${QMLPLUGINDUMP}.app/Contents/MacOS/qmlplugindump" - QMLTYPESFILE = $$QT.jsondbcompat.imports/$$TARGETPATH/plugin.qmltypes - QMAKE_POST_LINK += LD_LIBRARY_PATH=$$QT.jsondbcompat.libs $$QMLPLUGINDUMP QtJsonDb 1.0 $$QT.jsondbcompat.imports > $$QMLTYPESFILE + unix:!mac: QMLPLUGINDUMP = "$${QMLPLUGINDUMP} -platform minimal" + QMLTYPESFILE = $$QT.jsondb.imports/$$TARGETPATH/plugin.qmltypes + QMAKE_POST_LINK += LD_LIBRARY_PATH=$$QT.jsondb.libs $$QMLPLUGINDUMP QtJsonDb 1.0 $$QT.jsondb.imports > $$QMLTYPESFILE qmltypes.files = $$QMLTYPESFILE qmltypes.path = $$[QT_INSTALL_IMPORTS]/$$TARGETPATH @@ -27,37 +28,31 @@ INSTALLS += target qmldir VERSION = 1.0 -include(../../common/common.pri) - HEADERS += \ jsondbpartition.h \ jsondbnotification.h \ - jsondbsortinglistmodel.h \ - jsondbsortinglistmodel_p.h \ - jsondblistmodel.h \ - jsondblistmodel_p.h \ plugin.h \ jsondatabase.h \ jsondbqueryobject.h \ - jsondbchangessinceobject.h \ + jsondbmodelutils.h \ jsondbmodelcache.h \ + jsondblistmodel.h \ + jsondblistmodel_p.h \ + jsondbsortinglistmodel_p.h \ + jsondbsortinglistmodel.h \ jsondbcachinglistmodel_p.h \ - jsondbcachinglistmodel.h \ - jsondbmodelutils.h - -HEADERS += $$QSONCONVERSION_HEADERS + jsondbcachinglistmodel.h SOURCES += \ jsondbpartition.cpp \ jsondbnotification.cpp \ - jsondbsortinglistmodel.cpp \ - jsondblistmodel.cpp \ plugin.cpp \ jsondatabase.cpp \ jsondbqueryobject.cpp \ - jsondbchangessinceobject.cpp \ - jsondbcachinglistmodel.cpp \ + jsondbmodelutils.cpp \ jsondbmodelcache.cpp \ - jsondbmodelutils.cpp + jsondblistmodel.cpp \ + jsondbsortinglistmodel.cpp \ + jsondbcachinglistmodel.cpp -SOURCES += $$QSONCONVERSION_SOURCES +OTHER_FILES += jsondb.json diff --git a/src/imports/jsondb/jsondbcachinglistmodel.cpp b/src/imports/jsondb/jsondbcachinglistmodel.cpp index c34617c..afcec55 100644 --- a/src/imports/jsondb/jsondbcachinglistmodel.cpp +++ b/src/imports/jsondb/jsondbcachinglistmodel.cpp @@ -40,15 +40,18 @@ ****************************************************************************/ //#define JSONDB_LISTMODEL_DEBUG +//#define JSONDB_LISTMODEL_BENCHMARK #include "jsondbcachinglistmodel.h" #include "jsondbcachinglistmodel_p.h" -#include "private/jsondb-strings_p.h" #include "plugin.h" #include <QJSEngine> #include <QJSValueIterator> #include <QDebug> +#ifdef JSONDB_LISTMODEL_BENCHMARK +#include <QElapsedTimer> +#endif /*! \internal @@ -70,13 +73,6 @@ JsonDbCachingListModelPrivate::JsonDbCachingListModelPrivate(JsonDbCachingListMo void JsonDbCachingListModelPrivate::init() { - Q_Q(JsonDbCachingListModel); - q->connect(&dbClient, SIGNAL(response(int,const QVariant&)), - q, SLOT(_q_jsonDbResponse(int,const QVariant&)), - Qt::QueuedConnection); - q->connect(&dbClient, SIGNAL(error(int,int,const QString&)), - q, SLOT(_q_jsonDbErrorResponse(int,int,const QString&)), - Qt::QueuedConnection); } void JsonDbCachingListModelPrivate::setCacheParams(int maxItems) @@ -84,18 +80,29 @@ void JsonDbCachingListModelPrivate::setCacheParams(int maxItems) objectCache.setPageSize(maxItems); chunkSize = objectCache.chunkSize(); lowWaterMark = objectCache.chunkSize()/4; - //lowWaterMark = objectCache.pageSize/4; } JsonDbCachingListModelPrivate::~JsonDbCachingListModelPrivate() { - // Why do we need to do this while destroying the object clearNotifications(); + while (!keyRequests.isEmpty()) { + delete keyRequests[0]; + keyRequests.removeFirst(); + } + while (!indexRequests.isEmpty()) { + delete indexRequests[0]; + indexRequests.removeFirst(); + } + while (!valueRequests.isEmpty()) { + delete valueRequests[0]; + valueRequests.removeFirst(); + } + } // insert item notification handler // + add items, for chunked read -void JsonDbCachingListModelPrivate::addItem(const QVariantMap &item, int partitionIndex) +void JsonDbCachingListModelPrivate::addItem(const QJsonObject &item, int partitionIndex) { Q_Q(JsonDbCachingListModel); const QString &uuid = item.value(QLatin1String("_uuid")).toString(); @@ -103,7 +110,10 @@ void JsonDbCachingListModelPrivate::addItem(const QVariantMap &item, int partiti if (objectSortValues.contains(uuid)) return; - SortingKey key(partitionIndex, item, ascendingOrders, orderPaths, partitionIndexDetails[0].spec); + QVariantList vl; + vl.append(uuid); + vl.append(item.value(QLatin1String("_indexValue")).toVariant()); + SortingKey key(partitionIndex, vl, QList<bool>() << ascendingOrder, partitionIndexDetails[partitionIndex].spec); QMap<SortingKey, QString>::const_iterator begin = objectUuids.constBegin(); QMap<SortingKey, QString>::const_iterator end = objectUuids.constEnd(); QMap<SortingKey, QString>::const_iterator i = objectUuids.upperBound(key); @@ -120,7 +130,7 @@ void JsonDbCachingListModelPrivate::addItem(const QVariantMap &item, int partiti // deleteitem notification handler -void JsonDbCachingListModelPrivate::deleteItem(const QVariantMap &item, int partitionIndex) +void JsonDbCachingListModelPrivate::deleteItem(const QJsonObject &item, int partitionIndex) { Q_Q(JsonDbCachingListModel); QString uuid = item.value(QLatin1String("_uuid")).toString(); @@ -144,14 +154,17 @@ void JsonDbCachingListModelPrivate::deleteItem(const QVariantMap &item, int part } // updateitem notification handler -void JsonDbCachingListModelPrivate::updateItem(const QVariantMap &item, int partitionIndex) +void JsonDbCachingListModelPrivate::updateItem(const QJsonObject &item, int partitionIndex) { Q_Q(JsonDbCachingListModel); QString uuid = item.value(QLatin1String("_uuid")).toString(); QMap<QString, SortingKey>::const_iterator keyIndex = objectSortValues.constFind(uuid); if (keyIndex != objectSortValues.constEnd()) { SortingKey key = keyIndex.value(); - SortingKey newKey(partitionIndex, item, ascendingOrders, orderPaths, partitionIndexDetails[0].spec); + QVariantList vl; + vl.append(uuid); + vl.append(item.value(QLatin1String("_indexValue")).toVariant()); + SortingKey newKey(partitionIndex, vl, QList<bool>() << ascendingOrder, partitionIndexDetails[partitionIndex].spec); QMap<SortingKey, QString>::const_iterator begin = objectUuids.constBegin(); QMap<SortingKey, QString>::const_iterator end = objectUuids.constEnd(); QMap<SortingKey, QString>::const_iterator oldPos = objectUuids.constFind(key); @@ -276,55 +289,50 @@ void JsonDbCachingListModelPrivate::createObjectRequests(int startIndex, int max r.lastOffset = indexNSizes[i].index; r.lastSize = -1; r.requestCount = indexNSizes[i].count; - r.requestId = dbClient.query(query+sortOrder, indexNSizes[i].index, - qMin(r.requestCount, chunkSize), - partitionObjects[i]->name()); + QJsonDbReadRequest *request = valueRequests[i]->newRequest(i); + request->setQuery(query+sortOrder); + request->setProperty("queryOffset", indexNSizes[i].index); + request->setQueryLimit(qMin(r.requestCount, chunkSize)); + request->setPartition(partitionObjects[i]->name()); + JsonDatabase::sharedConnection().send(request); #ifdef JSONDB_LISTMODEL_DEBUG qDebug()<<"Query"<<query+sortOrder<<partitionObjects[i]->name(); - qDebug()<<"Request "<<r.requestId << + qDebug()<<"Request "<<request->property("requestId") << "Total Count "<<r.requestCount << "Offset"<<r.lastOffset<< "Count "<<qMin(r.requestCount,chunkSize); #endif } else { - r.requestId = -1; r.lastSize = 0; r.requestCount = 0; } } - delete indexNSizes; + delete [] indexNSizes; } -void JsonDbCachingListModelPrivate::verifyIndexSpec(const QVariant &v, int partitionIndex) +void JsonDbCachingListModelPrivate::verifyIndexSpec(const QList<QJsonObject> &items, int partitionIndex) { Q_Q(JsonDbCachingListModel); - QVariantMap m = v.toMap(); - QVariantList items; - if (m.contains(QLatin1String("data"))) - items = m.value(QLatin1String("data")).toList(); SortIndexSpec &indexSpec = partitionIndexDetails[partitionIndex].spec; - QString propertyFunction; - QString indexName; bool validIndex = false; - if (orderProperties.count()) - indexName = orderProperties[0]; if (items.count()) { - QVariantMap spec = items[0].toMap(); - indexSpec.propertyName = spec.value(QLatin1String("propertyName")).toString(); - indexSpec.propertyType = spec.value(QLatin1String("propertyType")).toString(); + QJsonObject spec = items[0]; + indexSpec.propertyName = QLatin1String("_indexValue"); + QString propertyType = spec.value(QLatin1String("propertyType")).toString(); indexSpec.name = spec.value(QLatin1String("name")).toString(); - propertyFunction = spec.value(QLatin1String("propertyFunction")).toString(); + indexSpec.caseSensitive = true; if (!indexName.isEmpty()) { if (indexSpec.name == indexName) { - validIndex = true; - if (!indexSpec.propertyType.compare(QLatin1String("string"), Qt::CaseInsensitive)) { + if (!propertyType.compare(QLatin1String("string"), Qt::CaseInsensitive)) { indexSpec.type = SortIndexSpec::String; - indexSpec.caseSensitive = true; + validIndex = true; + } else if (!propertyType.compare(QLatin1String("number"), Qt::CaseInsensitive)) { + indexSpec.type = SortIndexSpec::Number; + validIndex = true; + } else if (!propertyType.compare(QLatin1String("UUID"), Qt::CaseInsensitive)) { + indexSpec.type = SortIndexSpec::UUID; + validIndex = true; } - if (indexSpec.propertyName.isEmpty()) - validIndex = false; - if (!propertyFunction.isEmpty()) - validIndex = false; // Cannot support property functions } } } @@ -345,7 +353,6 @@ void JsonDbCachingListModelPrivate::verifyIndexSpec(const QVariant &v, int parti } if (checkedAll) { //Start fetching the keys. - orderProperties[0] = indexSpec.propertyName; setQueryForSortKeys(); for (int i = 0; i < partitionKeyRequestDetails.count(); i++) { fetchPartitionKeys(i); @@ -354,32 +361,17 @@ void JsonDbCachingListModelPrivate::verifyIndexSpec(const QVariant &v, int parti } } -void JsonDbCachingListModelPrivate::fillKeys(const QVariant &v, int partitionIndex) +void JsonDbCachingListModelPrivate::fillKeys(const QList<QJsonObject> &items, int partitionIndex) { - Q_Q(JsonDbCachingListModel); - QVariantMap m = v.toMap(); - QVariantList items; - if (m.contains(QLatin1String("data"))) - items = m.value(QLatin1String("data")).toList(); - // Check if the sort key is same as requested. - // We can only support this model if an index is present - if (m.contains(QLatin1String("sortKeys"))) { - const QVariantList &sortKeys = m.value(QLatin1String("sortKeys")).toList(); - if (!(sortKeys.count() && sortKeys[0].toString() == orderProperties[0])) { - qWarning() << "Error JsonDbCachingListModel requires Index for "<<orderProperties[0]<<" Sort Keys"<<sortKeys; - reset(); - state = JsonDbCachingListModel::Error; - emit q->stateChanged(state); - return; - } - } RequestInfo &r = partitionKeyRequestDetails[partitionIndex]; r.lastSize = items.size(); for (int i = 0; i < r.lastSize; i++) { - const QVariantList &item = items.at(i).toList(); - const QString &uuid = item.at(0).toString(); - - SortingKey key(partitionIndex, item, ascendingOrders, partitionIndexDetails[0].spec); + const QJsonObject &item = items.at(i); + const QString &uuid = item.value(QLatin1String("_uuid")).toString(); + QVariantList vl; + vl.append(uuid); + vl.append(item.value(QLatin1String("_indexValue")).toVariant()); + SortingKey key(partitionIndex, vl, QList<bool>() << ascendingOrder, partitionIndexDetails[partitionIndex].spec); objectUuids.insert(key, uuid); partitionObjectUuids[partitionIndex].insert(key, uuid); objectSortValues.insert(uuid, key); @@ -389,7 +381,7 @@ void JsonDbCachingListModelPrivate::fillKeys(const QVariant &v, int partitionInd // all the results bool allRequestsFinished = true; for (int i = 0; i < partitionKeyRequestDetails.count(); i++) { - if (partitionKeyRequestDetails[i].lastSize >= chunkSize*2 || partitionKeyRequestDetails[i].lastSize == -1) { + if (partitionKeyRequestDetails[i].lastSize >= chunkSize || partitionKeyRequestDetails[i].lastSize == -1) { allRequestsFinished = false; break; } @@ -401,12 +393,12 @@ void JsonDbCachingListModelPrivate::fillKeys(const QVariant &v, int partitionInd #endif if (!objectUuids.count()) { for (int i = 0; i<partitionObjectDetails.count(); i++) { - fillData(QVariant(), i); + fillData(QList<QJsonObject>(), i); } return; } createObjectRequests(0, qMin(objectCache.maxItems(), objectUuids.count())); - } else if (r.lastSize >= chunkSize*2){ + } else if (r.lastSize >= chunkSize){ // more items, fetch next chunk of keys fetchNextKeyChunk(partitionIndex); } @@ -420,20 +412,16 @@ void JsonDbCachingListModelPrivate::emitDataChanged(int from, int to) emit q->dataChanged(modelIndexFrom, modelIndexTo); } -void JsonDbCachingListModelPrivate::fillData(const QVariant &v, int partitionIndex) +void JsonDbCachingListModelPrivate::fillData(const QList<QJsonObject> &items, int partitionIndex) { Q_Q(JsonDbCachingListModel); - QVariantMap m = v.toMap(); - QVariantList items; - if (m.contains(QLatin1String("data"))) - items = m.value(QLatin1String("data")).toList(); RequestInfo &r = partitionObjectDetails[partitionIndex]; r.lastSize = items.size(); r.requestCount -= r.lastSize; r.lastOffset += r.lastSize; for (int i = 0; i < r.lastSize; i++) { - const QVariantMap &item = items.at(i).toMap(); + const QJsonObject &item = items.at(i); const QString &uuid = item.value(QLatin1String("_uuid")).toString(); tmpObjects.insert(uuid, item); } @@ -499,11 +487,11 @@ void JsonDbCachingListModelPrivate::fillData(const QVariant &v, int partitionInd // retrieved all elements state = JsonDbCachingListModel::Ready; emit q->stateChanged(state); - for (int i = 0; i < pendingNotifications.size(); i++) { - const NotifyItem &pending = pendingNotifications[i]; - sendNotifications(pending.notifyUuid, pendingNotifications[i].item, pendingNotifications[i].action); + if (!pendingNotifications.isEmpty()) { + foreach (NotificationItem pending, pendingNotifications) + sendNotification(pending.partitionIndex, pending.item, pending.action); + pendingNotifications.clear(); } - pendingNotifications.clear(); if (requestQueue.count()) { QPair<int, int> req = requestQueue.takeFirst(); createObjectRequests(req.first, req.second); @@ -550,10 +538,7 @@ void JsonDbCachingListModelPrivate::reset() bool JsonDbCachingListModelPrivate::checkForDefaultIndexTypes(int index) { Q_Q(JsonDbCachingListModel); - if (!orderProperties.count()) - return false; bool defaultType = false; - QString indexName = orderProperties[0]; if (!indexName.compare(QLatin1String("_uuid")) || !indexName.compare(QLatin1String("_type"))) { defaultType = true; QMetaObject::invokeMethod(q, "_q_verifyDefaultIndexType", Qt::QueuedConnection, @@ -574,10 +559,12 @@ void JsonDbCachingListModelPrivate::fetchIndexSpec(int index) state = JsonDbCachingListModel::Querying; emit q->stateChanged(state); } - IndexInfo &r = partitionIndexDetails[index]; QPointer<JsonDbPartition> p = partitionObjects[index]; if (p) { - r.requestId = dbClient.query(queryForIndexSpec, 0, -1, p->name()); + QJsonDbReadRequest *request = indexRequests[index]->newRequest(index); + request->setQuery(queryForIndexSpec); + request->setPartition(p->name()); + JsonDatabase::sharedConnection().send(request); } } @@ -596,7 +583,11 @@ void JsonDbCachingListModelPrivate::fetchPartitionKeys(int index) if (p) { r.lastSize = -1; r.lastOffset = 0; - r.requestId = dbClient.query(queryForSortKeys, 0, chunkSize*2, p->name()); + QJsonDbReadRequest *request = keyRequests[index]->newRequest(index); + request->setQuery(queryForSortKeys); + request->setQueryLimit(chunkSize); + request->setPartition(p->name()); + JsonDatabase::sharedConnection().send(request); } } @@ -610,6 +601,9 @@ void JsonDbCachingListModelPrivate::initializeModel(bool reset) for (int i = 0; i < partitionObjectUuids.count(); i++) { partitionObjectUuids[i].clear(); } + for (int i = 0; i < partitionIndexDetails.count(); i++) { + partitionIndexDetails[i].clear(); + } } for (int i = 0; i < partitionObjects.count(); i++) { fetchIndexSpec(i); @@ -625,17 +619,26 @@ void JsonDbCachingListModelPrivate::fetchModel(bool reset) void JsonDbCachingListModelPrivate::fetchNextKeyChunk(int partitionIndex) { RequestInfo &r = partitionKeyRequestDetails[partitionIndex]; - r.lastOffset += chunkSize*2; - r.requestId = dbClient.query(queryForSortKeys, r.lastOffset, - chunkSize*2, partitionObjects[partitionIndex]->name()); + r.lastOffset += chunkSize; + QJsonDbReadRequest *request = keyRequests[partitionIndex]->newRequest(partitionIndex); + request->setQuery(queryForSortKeys); + request->setProperty("queryOffset", r.lastOffset); + request->setQueryLimit(chunkSize); + request->setPartition(partitionObjects[partitionIndex]->name()); + JsonDatabase::sharedConnection().send(request); + } void JsonDbCachingListModelPrivate::fetchNextChunk(int partitionIndex) { RequestInfo &r = partitionObjectDetails[partitionIndex]; - r.requestId = dbClient.query(query+sortOrder, r.lastOffset, - qMin(r.requestCount, chunkSize), - partitionObjects[partitionIndex]->name()); + QJsonDbReadRequest *request = valueRequests[partitionIndex]->newRequest(partitionIndex); + request->setQuery(query+sortOrder); + request->setProperty("queryOffset", r.lastOffset); + request->setQueryLimit(qMin(r.requestCount, chunkSize)); + request->setPartition(partitionObjects[partitionIndex]->name()); + JsonDatabase::sharedConnection().send(request); + } void JsonDbCachingListModelPrivate::prefetchNearbyPages(int index) @@ -688,15 +691,14 @@ void JsonDbCachingListModelPrivate::requestPageContaining(int index) } - void JsonDbCachingListModelPrivate::clearNotification(int index) { if (index >= partitionObjects.count()) return; RequestInfo &r = partitionObjectDetails[index]; - if (!r.notifyUuid.isEmpty()) { - dbClient.unregisterNotification(r.notifyUuid); + if (r.watcher) { + JsonDatabase::sharedConnection().removeWatcher(r.watcher); } r.clear(); } @@ -713,13 +715,16 @@ void JsonDbCachingListModelPrivate::createOrUpdateNotification(int index) if (index >= partitionObjects.count()) return; clearNotification(index); - JsonDbClient::NotifyTypes notifyActions = JsonDbClient::NotifyCreate - | JsonDbClient::NotifyUpdate| JsonDbClient::NotifyRemove; - partitionObjectDetails[index].notifyUuid= dbClient.registerNotification( - notifyActions , query, partitionObjects[index]->name(), - q, SLOT(_q_dbNotified(QString,QtAddOn::JsonDb::JsonDbNotification)), - q, SLOT(_q_dbNotifyReadyResponse(int,QVariant)), - SLOT(_q_dbNotifyErrorResponse(int,int,QString))); + QJsonDbWatcher *watcher = new QJsonDbWatcher(); + watcher->setQuery(query+sortOrder); + watcher->setWatchedActions(QJsonDbWatcher::Created | QJsonDbWatcher::Updated |QJsonDbWatcher::Removed); + watcher->setPartition(partitionObjects[index]->name()); + QObject::connect(watcher, SIGNAL(notificationsAvailable(int)), + q, SLOT(_q_notificationsAvailable())); + QObject::connect(watcher, SIGNAL(error(QtJsonDb::QJsonDbWatcher::ErrorCode,QString)), + q, SLOT(_q_notificationError(QtJsonDb::QJsonDbWatcher::ErrorCode,QString))); + JsonDatabase::sharedConnection().addWatcher(watcher); + partitionObjectDetails[index].watcher = watcher; } void JsonDbCachingListModelPrivate::createOrUpdateNotifications() @@ -733,23 +738,14 @@ void JsonDbCachingListModelPrivate::parseSortOrder() { Q_Q(JsonDbCachingListModel); QRegExp orderMatch("\\[([/\\\\[\\]])[ ]*([^\\[\\]]+)[ ]*\\]"); - ascendingOrders.clear(); - orderProperties.clear(); - orderPaths.clear(); - int matchIndex = 0, firstMatch = -1; - while ((matchIndex = orderMatch.indexIn(sortOrder, matchIndex)) >= 0) { - bool ascendingOrder = false; + if (orderMatch.indexIn(sortOrder, 0) >= 0) { + ascendingOrder = false; if (!orderMatch.cap(1).compare(QLatin1String("/"))) ascendingOrder = true; - ascendingOrders << ascendingOrder; - orderProperties << orderMatch.cap(2); - orderPaths << orderMatch.cap(2).split('.'); - if (firstMatch == -1) - firstMatch = matchIndex; - matchIndex += orderMatch.matchedLength(); - } - if (orderProperties.count()) { - queryForIndexSpec = QString(QLatin1String("[?_type=\"Index\"][?name=\"%1\"]")).arg(orderProperties[0]); + indexName = orderMatch.cap(2); + } + if (!indexName.isEmpty()) { + queryForIndexSpec = QString(QLatin1String("[?_type=\"Index\"][?name=\"%1\"]")).arg(indexName); } else { // Set default sort order (by _uuid) q->setSortOrder(QLatin1String("[/_uuid]")); @@ -760,45 +756,15 @@ void JsonDbCachingListModelPrivate::setQueryForSortKeys() { // Query to retrieve the sortKeys // TODO remove the "[= {}]" from query - queryForSortKeys = query + QLatin1String("[= [ _uuid"); - for (int i = 0; i < orderProperties.count() ; i++) { - queryForSortKeys += QLatin1String(", ") + orderProperties[i]; - } - queryForSortKeys += QLatin1String("]]"); + queryForSortKeys = query + QLatin1String("[= { _uuid: _uuid"); + queryForSortKeys += QLatin1String("}]"); queryForSortKeys += sortOrder; } -int JsonDbCachingListModelPrivate::indexOfKeyIndexSpecId(int requestId) -{ - for (int i = 0; i < partitionIndexDetails.count(); i++) { - if (requestId == partitionIndexDetails[i].requestId) - return i; - } - return -1; -} - -int JsonDbCachingListModelPrivate::indexOfKeyRequestId(int requestId) -{ - for (int i = 0; i < partitionKeyRequestDetails.count(); i++) { - if (requestId == partitionKeyRequestDetails[i].requestId) - return i; - } - return -1; -} - -int JsonDbCachingListModelPrivate::indexOfRequestId(int requestId) -{ - for (int i = 0; i < partitionObjectDetails.count(); i++) { - if (requestId == partitionObjectDetails[i].requestId) - return i; - } - return -1; -} - -int JsonDbCachingListModelPrivate::indexOfNotifyUUID(const QString& notifyUuid) +int JsonDbCachingListModelPrivate::indexOfWatcher(QJsonDbWatcher *watcher) { for (int i = 0; i < partitionObjectDetails.count(); i++) { - if (notifyUuid == partitionObjectDetails[i].notifyUuid) + if (watcher == partitionObjectDetails[i].watcher) return i; } return -1; @@ -841,7 +807,7 @@ QVariant JsonDbCachingListModelPrivate::getItem(int index) } if (state == JsonDbCachingListModel::Ready) // Pre-fetch only, if in Ready state prefetchNearbyPages(index); - return QVariant(objectCache.valueAtPage(page, uuid)); + return QVariant(objectCache.valueAtPage(page, uuid).toVariantMap()); } QVariant JsonDbCachingListModelPrivate::getItem(int index, int role) @@ -909,40 +875,66 @@ int JsonDbCachingListModelPrivate::indexOf(const QString &uuid) const return iterator_position(begin, end, i); } -void JsonDbCachingListModelPrivate::sendNotifications(const QString& currentNotifyUuid, const QVariant &v, JsonDbClient::NotifyType action) +void JsonDbCachingListModelPrivate::sendNotification(int partitionIndex, const QJsonObject &object, QJsonDbWatcher::Action action) { - int idx = indexOfNotifyUUID(currentNotifyUuid); - if (idx == -1) - return; - - const QVariantMap &item = v.toMap(); - if (action == JsonDbClient::NotifyCreate) { - addItem(item, idx); - } else if (action == JsonDbClient::NotifyRemove) { - deleteItem(item, idx); - } else if (action == JsonDbClient::NotifyUpdate) { - updateItem(item, idx); + if (action == QJsonDbWatcher::Created) { + addItem(object, partitionIndex); + } else if (action == QJsonDbWatcher::Removed) + deleteItem(object, partitionIndex); + else if (action == QJsonDbWatcher::Updated) { + updateItem(object, partitionIndex); } } -void JsonDbCachingListModelPrivate::_q_jsonDbResponse(int id, const QVariant &v) +void JsonDbCachingListModelPrivate::_q_keyResponse(int index, const QList<QJsonObject> &v, const QString &sortKey) { - int idx = -1; - if ((idx = indexOfKeyRequestId(id)) != -1) { - partitionKeyRequestDetails[idx].requestId = -1; - partitionObjectDetails[idx].requestId = -1; - fillKeys(v, idx); - } else if ((idx = indexOfRequestId(id)) != -1) { - partitionObjectDetails[idx].requestId = -1; - fillData(v, idx); - } else if ((idx = indexOfKeyIndexSpecId(id)) != -1) { - partitionIndexDetails[idx].requestId = -1; - verifyIndexSpec(v, idx); - } +#ifdef JSONDB_LISTMODEL_BENCHMARK + QElapsedTimer elt; + elt.start(); +#endif + Q_UNUSED(sortKey) + fillKeys(v, index); +#ifdef JSONDB_LISTMODEL_BENCHMARK + qint64 elap = elt.elapsed(); + if (elap > 3) + qDebug() << Q_FUNC_INFO << "took more than 3 ms (" << elap << "ms )"; +#endif +} + +void JsonDbCachingListModelPrivate::_q_valueResponse(int index, const QList<QJsonObject> &v) +{ +#ifdef JSONDB_LISTMODEL_BENCHMARK + QElapsedTimer elt; + elt.start(); +#endif + fillData(v, index); +#ifdef JSONDB_LISTMODEL_BENCHMARK + qint64 elap = elt.elapsed(); + if (elap > 3) + qDebug() << Q_FUNC_INFO << "took more than 3 ms (" << elap << "ms )"; +#endif } -void JsonDbCachingListModelPrivate::_q_jsonDbErrorResponse(int, int code, const QString &message) +void JsonDbCachingListModelPrivate::_q_indexResponse(int index, const QList<QJsonObject> &v) { +#ifdef JSONDB_LISTMODEL_BENCHMARK + QElapsedTimer elt; + elt.start(); +#endif + verifyIndexSpec(v, index); +#ifdef JSONDB_LISTMODEL_BENCHMARK + qint64 elap = elt.elapsed(); + if (elap > 3) + qDebug() << Q_FUNC_INFO << "took more than 3 ms (" << elap << "ms )"; +#endif +} + +void JsonDbCachingListModelPrivate::_q_readError(QtJsonDb::QJsonDbRequest::ErrorCode code, const QString & message) +{ +#ifdef JSONDB_LISTMODEL_BENCHMARK + QElapsedTimer elt; + elt.start(); +#endif Q_Q(JsonDbCachingListModel); qWarning() << QString("JsonDb error: %1 %2").arg(code).arg(message); int oldErrorCode = errorCode; @@ -950,28 +942,55 @@ void JsonDbCachingListModelPrivate::_q_jsonDbErrorResponse(int, int code, const errorString = message; if (oldErrorCode != errorCode) emit q->errorChanged(q->error()); +#ifdef JSONDB_LISTMODEL_BENCHMARK + qint64 elap = elt.elapsed(); + if (elap > 3) + qDebug() << Q_FUNC_INFO << "took more than 3 ms (" << elap << "ms )"; +#endif } -void JsonDbCachingListModelPrivate::_q_dbNotified(const QString ¬ify_uuid, const QtAddOn::JsonDb::JsonDbNotification &_notification) +void JsonDbCachingListModelPrivate::_q_notificationsAvailable() { - if (state == JsonDbCachingListModel::Querying) { - NotifyItem pending; - pending.notifyUuid = notify_uuid; - pending.item = _notification.object(); - pending.action = _notification.action(); - pendingNotifications.append(pending); - } else if (state == JsonDbCachingListModel::Ready) { - sendNotifications(notify_uuid, _notification.object(), _notification.action()); +#ifdef JSONDB_LISTMODEL_BENCHMARK + QElapsedTimer elt; + elt.start(); +#endif + Q_Q(JsonDbCachingListModel); + QJsonDbWatcher *watcher = qobject_cast<QJsonDbWatcher *>(q->sender()); + int partitionIndex = indexOfWatcher(watcher); + if (!watcher || partitionIndex == -1) + return; + QList<QJsonDbNotification> list = watcher->takeNotifications(); + for (int i = 0; i < list.count(); i++) { + const QJsonDbNotification & notification = list[i]; + QJsonObject object = notification.object(); + QJsonDbWatcher::Action action = notification.action(); + if (state == JsonDbCachingListModel::Querying) { + NotificationItem pending; + pending.partitionIndex = partitionIndex; + pending.item = object; + pending.action = action; + pendingNotifications.append(pending); + } else { + foreach (NotificationItem pending, pendingNotifications) + sendNotification(pending.partitionIndex, pending.item, pending.action); + pendingNotifications.clear(); + sendNotification(partitionIndex, object, action); + } } +#ifdef JSONDB_LISTMODEL_BENCHMARK + qint64 elap = elt.elapsed(); + if (elap > 3) + qDebug() << Q_FUNC_INFO << "took more than 3 ms (" << elap << "ms )"; +#endif } -void JsonDbCachingListModelPrivate::_q_dbNotifyReadyResponse(int /* id */, const QVariant &/* result */) -{ -} - -void JsonDbCachingListModelPrivate::_q_dbNotifyErrorResponse(int id, int code, const QString &message) +void JsonDbCachingListModelPrivate::_q_notificationError(QtJsonDb::QJsonDbWatcher::ErrorCode code, const QString &message) { - Q_UNUSED(id); +#ifdef JSONDB_LISTMODEL_BENCHMARK + QElapsedTimer elt; + elt.start(); +#endif Q_Q(JsonDbCachingListModel); qWarning() << QString("JsonDbCachingListModel Notification error: %1 %2").arg(code).arg(message); int oldErrorCode = errorCode; @@ -979,23 +998,27 @@ void JsonDbCachingListModelPrivate::_q_dbNotifyErrorResponse(int id, int code, c errorString = message; if (oldErrorCode != errorCode) emit q->errorChanged(q->error()); +#ifdef JSONDB_LISTMODEL_BENCHMARK + qint64 elap = elt.elapsed(); + if (elap > 3) + qDebug() << Q_FUNC_INFO << "took more than 3 ms (" << elap << "ms )"; +#endif } void JsonDbCachingListModelPrivate::_q_verifyDefaultIndexType(int index) { - if (!orderProperties.count()) - return; - QString indexName = orderProperties[0]; +#ifdef JSONDB_LISTMODEL_BENCHMARK + QElapsedTimer elt; + elt.start(); +#endif SortIndexSpec &indexSpec = partitionIndexDetails[index].spec; partitionIndexDetails[index].valid = true; if (!indexName.compare(QLatin1String("_uuid"))) { - indexSpec.propertyName = QLatin1String("_uuid"); - indexSpec.propertyType = QLatin1String("_uuid"); + indexSpec.name = QLatin1String("_uuid"); indexSpec.type = SortIndexSpec::UUID; indexSpec.caseSensitive = false; } else if (!indexName.compare(QLatin1String("_type"))) { - indexSpec.propertyName = QLatin1String("_type"); - indexSpec.propertyType = QLatin1String("_type"); + indexSpec.name = QLatin1String("_type"); indexSpec.type = SortIndexSpec::String; indexSpec.caseSensitive = true; } @@ -1009,12 +1032,56 @@ void JsonDbCachingListModelPrivate::_q_verifyDefaultIndexType(int index) } if (checkedAll) { //Start fetching the keys. - orderProperties[0] = indexSpec.propertyName; setQueryForSortKeys(); for (int i = 0; i < partitionKeyRequestDetails.count(); i++) { fetchPartitionKeys(i); } } +#ifdef JSONDB_LISTMODEL_BENCHMARK + qint64 elap = elt.elapsed(); + if (elap > 3) + qDebug() << Q_FUNC_INFO << "took more than 3 ms (" << elap << "ms )"; +#endif +} + +void JsonDbCachingListModelPrivate::appendPartition(JsonDbPartition *v) +{ + Q_Q(JsonDbCachingListModel); + partitionObjects.append(QPointer<JsonDbPartition>(v)); + + partitionObjectDetails.append(RequestInfo()); + ModelRequest *valueRequest = new ModelRequest(); + QObject::connect(valueRequest, SIGNAL(finished(int,QList<QJsonObject>,QString)), + q, SLOT(_q_valueResponse(int,QList<QJsonObject>))); + QObject::connect(valueRequest, SIGNAL(error(QtJsonDb::QJsonDbRequest::ErrorCode,QString)), + q, SLOT(_q_readError(QtJsonDb::QJsonDbRequest::ErrorCode,QString))); + valueRequests.append(valueRequest); + + partitionKeyRequestDetails.append(RequestInfo()); + ModelRequest *keyRequest = new ModelRequest(); + QObject::connect(keyRequest, SIGNAL(finished(int,QList<QJsonObject>,QString)), + q, SLOT(_q_keyResponse(int,QList<QJsonObject>,QString))); + QObject::connect(keyRequest, SIGNAL(error(QtJsonDb::QJsonDbRequest::ErrorCode,QString)), + q, SLOT(_q_readError(QtJsonDb::QJsonDbRequest::ErrorCode,QString))); + keyRequests.append(keyRequest); + + partitionObjectUuids.append(JsonDbModelIndexType()); + + partitionIndexDetails.append(IndexInfo()); + ModelRequest *indexRequest = new ModelRequest(); + QObject::connect(indexRequest, SIGNAL(finished(int,QList<QJsonObject>,QString)), + q, SLOT(_q_indexResponse(int,QList<QJsonObject>))); + QObject::connect(indexRequest, SIGNAL(error(QtJsonDb::QJsonDbRequest::ErrorCode,QString)), + q, SLOT(_q_readError(QtJsonDb::QJsonDbRequest::ErrorCode,QString))); + indexRequests.append(indexRequest); + + if (componentComplete && !query.isEmpty()) { + parseSortOrder(); + createOrUpdateNotification(partitionObjects.count()-1); + if (state == JsonDbCachingListModel::None) + resetModel = true; + fetchIndexSpec(partitionObjects.count()-1); + } } void JsonDbCachingListModelPrivate::partitions_append(QQmlListProperty<JsonDbPartition> *p, JsonDbPartition *v) @@ -1022,18 +1089,7 @@ void JsonDbCachingListModelPrivate::partitions_append(QQmlListProperty<JsonDbPar JsonDbCachingListModel *q = qobject_cast<JsonDbCachingListModel *>(p->object); JsonDbCachingListModelPrivate *pThis = (q) ? q->d_func() : 0; if (pThis) { - pThis->partitionObjects.append(QPointer<JsonDbPartition>(v));\ - pThis->partitionObjectDetails.append(RequestInfo()); - pThis->partitionKeyRequestDetails.append(RequestInfo()); - pThis->partitionObjectUuids.append(JsonDbModelIndexType()); - pThis->partitionIndexDetails.append(IndexInfo()); - if (pThis->componentComplete && !pThis->query.isEmpty()) { - pThis->parseSortOrder(); - pThis->createOrUpdateNotification(pThis->partitionObjects.count()-1); - if (pThis->state == JsonDbCachingListModel::None) - pThis->resetModel = true; - pThis->fetchIndexSpec(pThis->partitionObjects.count()-1); - } + pThis->appendPartition(v); } } @@ -1057,17 +1113,34 @@ JsonDbPartition* JsonDbCachingListModelPrivate::partitions_at(QQmlListProperty<J return 0; } +void JsonDbCachingListModelPrivate::clearPartitions() +{ + partitionObjects.clear(); + partitionObjectDetails.clear(); + partitionKeyRequestDetails.clear(); + partitionObjectUuids.clear(); + partitionIndexDetails.clear(); + while (!keyRequests.isEmpty()) { + delete keyRequests[0]; + keyRequests.removeFirst(); + } + while (!indexRequests.isEmpty()) { + delete indexRequests[0]; + indexRequests.removeFirst(); + } + while (!valueRequests.isEmpty()) { + delete valueRequests[0]; + valueRequests.removeFirst(); + } + reset(); +} + void JsonDbCachingListModelPrivate::partitions_clear(QQmlListProperty<JsonDbPartition> *p) { JsonDbCachingListModel *q = qobject_cast<JsonDbCachingListModel *>(p->object); JsonDbCachingListModelPrivate *pThis = (q) ? q->d_func() : 0; if (pThis) { - pThis->partitionObjects.clear(); - pThis->partitionObjectDetails.clear(); - pThis->partitionKeyRequestDetails.clear(); - pThis->partitionObjectUuids.clear(); - pThis->partitionIndexDetails.clear(); - pThis->reset(); + pThis->clearPartitions(); } } @@ -1124,8 +1197,17 @@ JsonDbCachingListModel::JsonDbCachingListModel(QObject *parent) : QAbstractListModel(parent) , d_ptr(new JsonDbCachingListModelPrivate(this)) { +#ifdef JSONDB_LISTMODEL_BENCHMARK + QElapsedTimer elt; + elt.start(); +#endif Q_D(JsonDbCachingListModel); d->init(); +#ifdef JSONDB_LISTMODEL_BENCHMARK + qint64 elap = elt.elapsed(); + if (elap > 3) + qDebug() << Q_FUNC_INFO << "took more than 3 ms (" << elap << "ms )"; +#endif } JsonDbCachingListModel::~JsonDbCachingListModel() @@ -1138,12 +1220,21 @@ void JsonDbCachingListModel::classBegin() void JsonDbCachingListModel::componentComplete() { +#ifdef JSONDB_LISTMODEL_BENCHMARK + QElapsedTimer elt; + elt.start(); +#endif Q_D(JsonDbCachingListModel); d->componentComplete = true; if (!d->query.isEmpty() && d->partitionObjects.count()) { d->createOrUpdateNotifications(); d->fetchModel(); } +#ifdef JSONDB_LISTMODEL_BENCHMARK + qint64 elap = elt.elapsed(); + if (elap > 3) + qDebug() << Q_FUNC_INFO << "took more than 3 ms (" << elap << "ms )"; +#endif } /*! @@ -1159,8 +1250,18 @@ int JsonDbCachingListModel::rowCount(const QModelIndex &parent) const QVariant JsonDbCachingListModel::data(const QModelIndex &modelIndex, int role) const { +#ifdef JSONDB_LISTMODEL_BENCHMARK + QElapsedTimer elt; + elt.start(); +#endif JsonDbCachingListModel *pThis = const_cast<JsonDbCachingListModel *>(this); - return pThis->d_func()->getItem(modelIndex.row(), role); + QVariant ret = pThis->d_func()->getItem(modelIndex.row(), role); +#ifdef JSONDB_LISTMODEL_BENCHMARK + qint64 elap = elt.elapsed(); + if (elap > 3) + qDebug() << Q_FUNC_INFO << "took more than 3 ms (" << elap << "ms )"; +#endif + return ret; } /*! @@ -1224,6 +1325,10 @@ QVariant JsonDbCachingListModel::scriptableRoleNames() const void JsonDbCachingListModel::setScriptableRoleNames(const QVariant &vroles) { +#ifdef JSONDB_LISTMODEL_BENCHMARK + QElapsedTimer elt; + elt.start(); +#endif Q_D(JsonDbCachingListModel); d->properties.clear(); d->roleNames.clear(); @@ -1247,6 +1352,11 @@ void JsonDbCachingListModel::setScriptableRoleNames(const QVariant &vroles) } } QAbstractItemModel::setRoleNames(d->roleNames); +#ifdef JSONDB_LISTMODEL_BENCHMARK + qint64 elap = elt.elapsed(); + if (elap > 3) + qDebug() << Q_FUNC_INFO << "took more than 3 ms (" << elap << "ms )"; +#endif } /*! @@ -1277,6 +1387,10 @@ QString JsonDbCachingListModel::query() const void JsonDbCachingListModel::setQuery(const QString &newQuery) { +#ifdef JSONDB_LISTMODEL_BENCHMARK + QElapsedTimer elt; + elt.start(); +#endif Q_D(JsonDbCachingListModel); const QString oldQuery = d->query; @@ -1292,6 +1406,11 @@ void JsonDbCachingListModel::setQuery(const QString &newQuery) return; d->createOrUpdateNotifications(); d->fetchModel(); +#ifdef JSONDB_LISTMODEL_BENCHMARK + qint64 elap = elt.elapsed(); + if (elap > 3) + qDebug() << Q_FUNC_INFO << "took more than 3 ms (" << elap << "ms )"; +#endif } /*! @@ -1319,6 +1438,10 @@ int JsonDbCachingListModel::cacheSize() const void JsonDbCachingListModel::setCacheSize(int newCacheSize) { +#ifdef JSONDB_LISTMODEL_BENCHMARK + QElapsedTimer elt; + elt.start(); +#endif Q_D(JsonDbCachingListModel); if (newCacheSize == d->cacheSize) return; @@ -1332,10 +1455,19 @@ void JsonDbCachingListModel::setCacheSize(int newCacheSize) #ifdef JSONDB_LISTMODEL_DEBUG d->objectCache.dumpCacheDetails(); #endif +#ifdef JSONDB_LISTMODEL_BENCHMARK + qint64 elap = elt.elapsed(); + if (elap > 3) + qDebug() << Q_FUNC_INFO << "took more than 3 ms (" << elap << "ms )"; +#endif } void JsonDbCachingListModel::partitionNameChanged(const QString &partitionName) { +#ifdef JSONDB_LISTMODEL_BENCHMARK + QElapsedTimer elt; + elt.start(); +#endif Q_UNUSED(partitionName); Q_D(JsonDbCachingListModel); @@ -1344,6 +1476,11 @@ void JsonDbCachingListModel::partitionNameChanged(const QString &partitionName) d->createOrUpdateNotifications(); d->fetchModel(); +#ifdef JSONDB_LISTMODEL_BENCHMARK + qint64 elap = elt.elapsed(); + if (elap > 3) + qDebug() << Q_FUNC_INFO << "took more than 3 ms (" << elap << "ms )"; +#endif } /*! @@ -1402,6 +1539,10 @@ QString JsonDbCachingListModel::sortOrder() const void JsonDbCachingListModel::setSortOrder(const QString &newSortOrder) { +#ifdef JSONDB_LISTMODEL_BENCHMARK + QElapsedTimer elt; + elt.start(); +#endif Q_D(JsonDbCachingListModel); const QString oldSortOrder = d->sortOrder; @@ -1413,6 +1554,11 @@ void JsonDbCachingListModel::setSortOrder(const QString &newSortOrder) d->createOrUpdateNotifications(); d->fetchModel(); } +#ifdef JSONDB_LISTMODEL_BENCHMARK + qint64 elap = elt.elapsed(); + if (elap > 3) + qDebug() << Q_FUNC_INFO << "took more than 3 ms (" << elap << "ms )"; +#endif } /*! @@ -1477,8 +1623,17 @@ int JsonDbCachingListModel::indexOf(const QString &uuid) const */ void JsonDbCachingListModel::get(int index, const QJSValue &callback) { +#ifdef JSONDB_LISTMODEL_BENCHMARK + QElapsedTimer elt; + elt.start(); +#endif Q_D(JsonDbCachingListModel); d->queueGetCallback(index, callback); +#ifdef JSONDB_LISTMODEL_BENCHMARK + qint64 elap = elt.elapsed(); + if (elap > 3) + qDebug() << Q_FUNC_INFO << "took more than 3 ms (" << elap << "ms )"; +#endif } /*! diff --git a/src/imports/jsondb/jsondbcachinglistmodel.h b/src/imports/jsondb/jsondbcachinglistmodel.h index 76b0311..84f66de 100644 --- a/src/imports/jsondb/jsondbcachinglistmodel.h +++ b/src/imports/jsondb/jsondbcachinglistmodel.h @@ -53,7 +53,6 @@ #include <QJSValue> #include <QScopedPointer> -#include "jsondb-global.h" #include "jsondbpartition.h" QT_BEGIN_NAMESPACE_JSONDB @@ -121,13 +120,14 @@ private: Q_DISABLE_COPY(JsonDbCachingListModel) Q_DECLARE_PRIVATE(JsonDbCachingListModel) QScopedPointer<JsonDbCachingListModelPrivate> d_ptr; - Q_PRIVATE_SLOT(d_func(), void _q_jsonDbResponse(int, const QVariant&)) - Q_PRIVATE_SLOT(d_func(), void _q_jsonDbErrorResponse(int, int, const QString&)) - Q_PRIVATE_SLOT(d_func(), void _q_dbNotified(QString, QtAddOn::JsonDb::JsonDbNotification)) - Q_PRIVATE_SLOT(d_func(), void _q_dbNotifyReadyResponse(int, QVariant)) - Q_PRIVATE_SLOT(d_func(), void _q_dbNotifyErrorResponse(int, int, QString)) - Q_PRIVATE_SLOT(d_func(), void _q_verifyDefaultIndexType(int)) + Q_PRIVATE_SLOT(d_func(), void _q_verifyDefaultIndexType(int)) + Q_PRIVATE_SLOT(d_func(), void _q_notificationsAvailable()) + Q_PRIVATE_SLOT(d_func(), void _q_notificationError(QtJsonDb::QJsonDbWatcher::ErrorCode, QString)) + Q_PRIVATE_SLOT(d_func(), void _q_keyResponse(int, QList<QJsonObject>, QString)) + Q_PRIVATE_SLOT(d_func(), void _q_valueResponse(int, QList<QJsonObject>)) + Q_PRIVATE_SLOT(d_func(), void _q_indexResponse(int, QList<QJsonObject>)) + Q_PRIVATE_SLOT(d_func(), void _q_readError(QtJsonDb::QJsonDbRequest::ErrorCode, QString)) }; QT_END_NAMESPACE_JSONDB diff --git a/src/imports/jsondb/jsondbcachinglistmodel_p.h b/src/imports/jsondb/jsondbcachinglistmodel_p.h index bf949dc..759440e 100644 --- a/src/imports/jsondb/jsondbcachinglistmodel_p.h +++ b/src/imports/jsondb/jsondbcachinglistmodel_p.h @@ -50,8 +50,9 @@ #include <QStringList> #include <QPointer> #include <QUuid> +#include <QJsonObject> -#include "jsondb-client.h" +#include "jsondatabase.h" #include "jsondbmodelutils.h" #include "jsondbmodelcache.h" @@ -93,9 +94,8 @@ public: QList<RequestInfo> partitionKeyRequestDetails; QList<JsonDbModelIndexType> partitionObjectUuids; - QList<bool> ascendingOrders; - QStringList orderProperties; - QList<QStringList> orderPaths; + bool ascendingOrder; + QString indexName; QString query; QVariant queryOptions; @@ -110,13 +110,15 @@ public: QHash<int, QByteArray> roleNames; QHash<int, QStringList> properties; - QList<NotifyItem> pendingNotifications; + QList<NotificationItem> pendingNotifications; QList<int> cacheMiss; QMap<int, QJSValue> getCallbacks; QList< QPair<int,int> > requestQueue; + QList< QPointer<ModelRequest> >keyRequests; + QList< QPointer<ModelRequest> >indexRequests; + QList< QPointer<ModelRequest> >valueRequests; JsonDbCachingListModel::State state; - JsonDbClient dbClient; QModelIndex parent; int errorCode; QString errorString; @@ -131,11 +133,11 @@ public: void clearCache(); void removeLastItem(); - void addItem(const QVariantMap &item, int partitionIndex); - void deleteItem(const QVariantMap &item, int partitionIndex); - void updateItem(const QVariantMap &item, int partitionIndex); - void fillKeys(const QVariant &v, int partitionIndex); - void fillData(const QVariant &v, int partitionIndex); + void addItem(const QJsonObject &item, int partitionIndex); + void deleteItem(const QJsonObject &item, int partitionIndex); + void updateItem(const QJsonObject &item, int partitionIndex); + void fillKeys(const QList<QJsonObject> &items, int partitionIndex); + void fillData(const QList<QJsonObject> &items, int partitionIndex); void reset(); void emitDataChanged(int from, int to); @@ -156,13 +158,12 @@ public: void createOrUpdateNotifications(); void parseSortOrder(); void setQueryForSortKeys(); - void verifyIndexSpec(const QVariant &v, int partitionIndex); + void verifyIndexSpec(const QList<QJsonObject> &items, int partitionIndex); - int indexOfKeyRequestId(int requestId); - int indexOfRequestId(int requestId); - int indexOfNotifyUUID(const QString& notifyUuid); - int indexOfKeyIndexSpecId(int requestId); + int indexOfWatcher(QJsonDbWatcher *watcher); + void appendPartition(JsonDbPartition *v); + void clearPartitions(); QVariant getItem(int index); QVariant getItem(int index, int role); void queueGetCallback(int index, const QJSValue &callback); @@ -172,14 +173,16 @@ public: void set(int index, const QJSValue& valuemap, const QJSValue &successCallback, const QJSValue &errorCallback); - void sendNotifications(const QString& currentNotifyUuid, const QVariant &v, JsonDbClient::NotifyType action); + void sendNotification(int partitionIndex, const QJsonObject &object, QJsonDbWatcher::Action action); + // private slots - void _q_jsonDbResponse(int , const QVariant &); - void _q_jsonDbErrorResponse(int , int, const QString&); - void _q_dbNotified(const QString ¬ify_uuid, const QtAddOn::JsonDb::JsonDbNotification &_notification); - void _q_dbNotifyReadyResponse(int id, const QVariant &result); - void _q_dbNotifyErrorResponse(int id, int code, const QString &message); void _q_verifyDefaultIndexType(int index); + void _q_notificationsAvailable(); + void _q_notificationError(QtJsonDb::QJsonDbWatcher::ErrorCode code, const QString &message); + void _q_readError(QtJsonDb::QJsonDbRequest::ErrorCode code, const QString & message); + void _q_keyResponse(int , const QList<QJsonObject>&, const QString&); + void _q_valueResponse(int , const QList<QJsonObject>&); + void _q_indexResponse(int , const QList<QJsonObject>&); static void partitions_append(QQmlListProperty<JsonDbPartition> *p, JsonDbPartition *v); static int partitions_count(QQmlListProperty<JsonDbPartition> *p); diff --git a/src/imports/jsondb/jsondbchangessinceobject.cpp b/src/imports/jsondb/jsondbchangessinceobject.cpp deleted file mode 100644 index 0872a46..0000000 --- a/src/imports/jsondb/jsondbchangessinceobject.cpp +++ /dev/null @@ -1,404 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtAddOn.JsonDb 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 "jsondb-global.h" -#include "jsondbchangessinceobject.h" -#include "jsondbpartition.h" -#include "private/jsondb-strings_p.h" -#include <qdebug.h> - -QT_BEGIN_NAMESPACE_JSONDB - -/*! - \qmlclass ChangesSince - \inqmlmodule QtJsonDb - \since 1.x - - This allows to query the list of changes that happened between the current state and a specified - stateNumber. Users can execute this by calling the start(). To retrieve the results, connect to - onResultsReady and/or onFinished. - - \code - JsonDb.Partition { - id: nokiaPartition - name: "com.nokia.shared" - } - JsonDb.ChangesSince { - id:contactChanges - partition:nokiaPartition - types: ["Contact"] - stateNumber : 10 - onFinished: { - var results = contactsQuery.takeResults(); - console.log("Results: Count + results.length ); - } - - onStatusChanged: { - if (status === JsonDb.ChangesSince.Error) - console.log("Failed " + error.code + " "+ error.message); - } - - } - - contactChanges.exec(); - \endcode - -*/ - -JsonDbChangesSinceObject::JsonDbChangesSinceObject(QObject *parent) - : QObject(parent) - , completed(false) - , startStateNumber(0) - , partitionObject(0) - , defaultPartitionObject(0) - , jsondbChangesSince(0) - , errorCode(0) - , objectStatus(JsonDbChangesSinceObject::Null) -{ -} - -JsonDbChangesSinceObject::~JsonDbChangesSinceObject() -{ - if (defaultPartitionObject) - delete defaultPartitionObject; - if (jsondbChangesSince) - delete jsondbChangesSince; -} - - -/*! - \qmlproperty list QtJsonDb::ChangesSince::types - Holds the list of object types which will be checked - while executing the ChangesSince. -*/ -QStringList JsonDbChangesSinceObject::types() const -{ - return filterTypes; -} - -void JsonDbChangesSinceObject::setTypes(const QStringList &newTypes) -{ - filterTypes = newTypes; - checkForReadyStatus(); -} - -/*! - \qmlproperty object QtJsonDb::ChangesSince::partition - Holds the partition object for the object. -*/ - -JsonDbPartition* JsonDbChangesSinceObject::partition() -{ - if (!partitionObject) { - defaultPartitionObject = new JsonDbPartition(); - setPartition(defaultPartitionObject); - } - checkForReadyStatus(); - return partitionObject; -} - -void JsonDbChangesSinceObject::setPartition(JsonDbPartition *newPartition) -{ - if (partitionObject == newPartition) - return; - if (partitionObject == defaultPartitionObject) - delete defaultPartitionObject; - partitionObject = newPartition; - checkForReadyStatus(); -} - -/*! - \qmlproperty int QtJsonDb::ChangesSince::stateNumber - State Number from which the changesSince is computed. -*/ -quint32 JsonDbChangesSinceObject::stateNumber() const -{ - return startStateNumber; -} - -void JsonDbChangesSinceObject::setStateNumber(quint32 newStateNumber) -{ - startStateNumber = newStateNumber; - checkForReadyStatus(); -} - -/*! - \qmlproperty int QtJsonDb::ChangesSince::startingStateNumber - State Number from which the changesSince is actually ccomputed. This - can be different from the QtJsonDb::ChangesSince::stateNumber. Only - valid after receiving the onResultsReady() -*/ -quint32 JsonDbChangesSinceObject::startingStateNumber() const -{ - if (jsondbChangesSince) - return jsondbChangesSince->startingStateNumber(); - return startStateNumber; -} - -/*! - \qmlproperty int QtJsonDb::ChangesSince::currentStateNumber - The current state number when the changesSince was executed. Only - valid after receiving the onResultsReady() -*/ -quint32 JsonDbChangesSinceObject::currentStateNumber() const -{ - if (jsondbChangesSince) - return jsondbChangesSince->currentStateNumber(); - return startStateNumber; -} - - -/*! - \qmlmethod list QtJsonDb::ChangesSince::takeResults() - - Retrieves the list of results available in the object. This can be called multiple - times for a single execution. Call this from onResultsReady or onFinished. This will - remove the returned results from the query object. - - If the request was successful, the response will be an array of objects. Each item in - the results array will be an object of type {"after" : {} , "before" : {}}. The \a after - sub-object will be undefined for deleted objects. For newly created objects, the \a before - sub-object will be undefined. If both sub-objects are valid the change, represents an update. - - - \code - property var objects : []; - JsonDb.ChangesSince { - id:contactChanges - partition:nokiaPartition - types: ["Contact"] - stateNumber : 10 - onResultsReady: { - objects = objects.concat(contactChanges.takeResults()); - console.log("Length :" + objects.length); - } - onFinished: { - objects = objects.concat(contactChanges.takeResults()); - console.log("Results: Count + objects.length ); - } - - onStatusChanged: { - if (status === JsonDb.ChangesSince.Error) - console.log("Failed " + error.code + " "+ error.message); - } - - } - \endcode - -*/ - -QVariantList JsonDbChangesSinceObject::takeResults() -{ - QVariantList list; - if (jsondbChangesSince) { - list = jsondbChangesSince->takeResults(); - } - return list; -} - -/*! - \qmlsignal QtJsonDb::ChangesSince::onResultsReady(int resultsAvailable) - - This handler is called when the a set of results are avaialable in the object. This - will be called multiple times for an execution of the changesSince. Results can be - retrievd here by calling takeResults() of the query object. - -*/ - -/*! - \qmlsignal QtJsonDb::ChangesSince::onFinished() - - This handler is called when the an execution of changesSince is finished. Results can be - retrievd here by calling takeResults() of the changesSince object. Users can wait for - onFinished to avoid chunked reading. -*/ - -/*! - \qmlproperty object QtJsonDb::ChangesSince::error - \readonly - - This property holds the current error information for the ChangesSince object. It contains: - \list - \li error.code - code for the current error. - \li error.message - detailed explanation of the error - \endlist -*/ - -QVariantMap JsonDbChangesSinceObject::error() const -{ - QVariantMap errorMap; - errorMap.insert(QLatin1String("code"), errorCode); - errorMap.insert(QLatin1String("message"), errorString); - return errorMap; -} - -/*! - \qmlproperty enumeration QtJsonDb::ChangesSince::status - \readonly - - This property holds the current status of the ChangesSince object. It can be one of: - \list - \li Query.Null - waiting for component to finish loading or for all the pararamters to be set. - \li Query.Loading - Executing the changes-since query - \li Query.Ready - object is ready, users can call start() - \li Query.Error - an error occurred while executing the query - \endlist - - \sa QtJsonDb::ChangesSince::error -*/ - -JsonDbChangesSinceObject::Status JsonDbChangesSinceObject::status() const -{ - return objectStatus; -} - -void JsonDbChangesSinceObject::componentComplete() -{ - completed = true; -} - -void JsonDbChangesSinceObject::clearError() -{ - int oldErrorCode = errorCode; - errorCode = 0; - errorString.clear(); - if (oldErrorCode != Error) { - emit errorChanged(error()); - } -} - -bool JsonDbChangesSinceObject::parametersReady() -{ - return (completed && partitionObject); -} - -void JsonDbChangesSinceObject::checkForReadyStatus() -{ - if (objectStatus != JsonDbChangesSinceObject::Null) - return; - - JsonDbChangesSinceObject::Status oldStatus = objectStatus; - - if (!partitionObject) - partitionObject = qobject_cast<JsonDbPartition*>(parent()); - if (!parametersReady()) { - objectStatus = JsonDbChangesSinceObject::Null; - if (objectStatus != oldStatus) - emit statusChanged(objectStatus); - return; - } else { - objectStatus = JsonDbChangesSinceObject::Ready; - if (objectStatus != oldStatus) - emit statusChanged(objectStatus); - } -} - -void JsonDbChangesSinceObject::setReadyStatus() -{ - JsonDbChangesSinceObject::Status oldStatus = objectStatus; - - objectStatus = JsonDbChangesSinceObject::Ready; - if (objectStatus != oldStatus) - emit statusChanged(objectStatus); -} - -void JsonDbChangesSinceObject::setError(QtAddOn::JsonDb::JsonDbError::ErrorCode code, const QString& message) -{ - int oldErrorCode = errorCode; - errorCode = code; - errorString = message; - if (objectStatus != JsonDbChangesSinceObject::Error) { - objectStatus = JsonDbChangesSinceObject::Error; - emit statusChanged(objectStatus); - } - if (oldErrorCode != JsonDbChangesSinceObject::Error) { - emit errorChanged(error()); - } -} - - -/*! - \qmlmethod object QtJsonDb::ChangesSince::start() - - Users should call this method to start the execution of changesSince on this partition. - Once there are some results ready on the object, the onResultsReady will be triggered. This - will be called whenever a new chunk of results is ready. Users can call takeResults() on - this object to retrieve the results at any time. The ChangesSince also emits an onFinished() - signal when the execution is finished. - -*/ -int JsonDbChangesSinceObject::start() -{ - if (!completed) { - qWarning("Component not ready"); - return -1; - } - checkForReadyStatus(); - if (!parametersReady()) { - qWarning("Missing properties"); - return -1; - } - - if (jsondbChangesSince) { - delete jsondbChangesSince; - } - jsondbChangesSince = partitionObject->jsonDb.changesSince(); - jsondbChangesSince->setTypes(filterTypes); - jsondbChangesSince->setStateNumber(startStateNumber); - jsondbChangesSince->setPartition(partitionObject->name()); - connect(jsondbChangesSince, SIGNAL(resultsReady(int)), - this, SIGNAL(resultsReady(int))); - connect(jsondbChangesSince, SIGNAL(finished()), - this, SLOT(setReadyStatus())); - connect(jsondbChangesSince, SIGNAL(finished()), - this, SIGNAL(finished())); - connect(jsondbChangesSince, SIGNAL(error(QtAddOn::JsonDb::JsonDbError::ErrorCode,QString)), - this, SLOT(setError(QtAddOn::JsonDb::JsonDbError::ErrorCode,QString))); - - jsondbChangesSince->start(); - objectStatus = JsonDbChangesSinceObject::Loading; - emit statusChanged(objectStatus); - - return jsondbChangesSince->requestId(); - -} - -#include "moc_jsondbchangessinceobject.cpp" -QT_END_NAMESPACE_JSONDB diff --git a/src/imports/jsondb/jsondbchangessinceobject.h b/src/imports/jsondb/jsondbchangessinceobject.h deleted file mode 100644 index 22649af..0000000 --- a/src/imports/jsondb/jsondbchangessinceobject.h +++ /dev/null @@ -1,131 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtAddOn.JsonDb 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$ -** -****************************************************************************/ - -#ifndef JSONDBCHANGESSINCEOBJECT_H -#define JSONDBCHANGESSINCEOBJECT_H - -#include <QObject> -#include <QVariant> -#include <QPointer> -#include <QJSValue> -#include <QQmlParserStatus> -#include <QQmlListProperty> -#include "jsondb-client.h" - -QT_BEGIN_NAMESPACE_JSONDB - -class JsonDbPartition; -class JsonDbPartitionPrivate; - -class JsonDbChangesSinceObject : public QObject, public QQmlParserStatus -{ - Q_OBJECT - Q_INTERFACES(QQmlParserStatus) - -public: - Q_ENUMS(Status) - enum Status { Null, Loading, Ready, Error }; - - Q_PROPERTY(JsonDbPartition* partition READ partition WRITE setPartition) - Q_PROPERTY(QStringList types READ types WRITE setTypes) - Q_PROPERTY(quint32 stateNumber READ stateNumber WRITE setStateNumber) - - Q_PROPERTY(quint32 startingStateNumber READ startingStateNumber) - Q_PROPERTY(quint32 currentStateNumber READ currentStateNumber) - Q_PROPERTY(Status status READ status NOTIFY statusChanged) - Q_PROPERTY(QVariantMap error READ error NOTIFY errorChanged) - - JsonDbChangesSinceObject(QObject *parent = 0); - ~JsonDbChangesSinceObject(); - - QStringList types() const; - void setTypes(const QStringList &newTypes); - - JsonDbPartition* partition(); - void setPartition(JsonDbPartition* newPartition); - - - quint32 stateNumber() const; - void setStateNumber(quint32 stateNumber); - - quint32 startingStateNumber() const; - quint32 currentStateNumber() const; - - JsonDbChangesSinceObject::Status status() const; - QVariantMap error() const; - - void classBegin() {} - void componentComplete(); - - Q_INVOKABLE int start(); - Q_INVOKABLE QVariantList takeResults(); - -Q_SIGNALS: - void resultsReady(int resultsAvailable); - void finished(); - void statusChanged(JsonDbChangesSinceObject::Status newStatus); - void errorChanged(const QVariantMap &newError); - -private Q_SLOTS: - void setError(QtAddOn::JsonDb::JsonDbError::ErrorCode code, const QString& message); - void setReadyStatus(); - -private: - bool completed; - quint32 startStateNumber; - QStringList filterTypes; - QPointer<JsonDbPartition> partitionObject; - QPointer<JsonDbPartition> defaultPartitionObject; - QPointer<JsonDbChangesSince> jsondbChangesSince; - int errorCode; - QString errorString; - Status objectStatus; - - void clearError(); - inline bool parametersReady(); - void checkForReadyStatus(); - friend class JsonDbPartition; - friend class JsonDbPartitionPrivate; -}; - -QT_END_NAMESPACE_JSONDB - -#endif //JSONDBCHANGESSINCEOBJECT_H diff --git a/src/imports/jsondb/jsondblistmodel.cpp b/src/imports/jsondb/jsondblistmodel.cpp index 7f184d7..c22a4f8 100644 --- a/src/imports/jsondb/jsondblistmodel.cpp +++ b/src/imports/jsondb/jsondblistmodel.cpp @@ -41,10 +41,13 @@ #include "jsondblistmodel.h" #include "jsondblistmodel_p.h" -#include "private/jsondb-strings_p.h" +#include "jsondatabase.h" #include <QJSEngine> #include <QJSValueIterator> +#include <QThread> +#include <QString> +#include <qdebug.h> #undef DEBUG_LIST_MODEL @@ -70,33 +73,34 @@ JsonDbListModelPrivate::JsonDbListModelPrivate(JsonDbListModel *q) , cacheStart(0) , cacheEnd(0) , newChunkOffset(0) - , totalCountRequestId(-1) , lastFetchedIndex(-1) , requestInProgress(false) , componentComplete(false) , resetModel(true) - , updateRecieved(false) + , updateReceived(false) , totalRowCountRecieved(false) , state(None) - , jsonDbConnection(JsonDbConnection::instance()) + , errorCode(0) { } void JsonDbListModelPrivate::init() { Q_Q(JsonDbListModel); - q->connect(&jsonDb, SIGNAL(response(int,const QVariant&)), - q, SLOT(_q_jsonDbResponse(int,const QVariant&))); - q->connect(&jsonDb, SIGNAL(error(int,int,const QString&)), - q, SLOT(_q_jsonDbErrorResponse(int,int,const QString&))); + QObject::connect(&valueRequest, SIGNAL(finished(int,QList<QJsonObject>,QString)), + q, SLOT(_q_valueResponse(int,QList<QJsonObject>))); + QObject::connect(&valueRequest, SIGNAL(error(QtJsonDb::QJsonDbRequest::ErrorCode,QString)), + q, SLOT(_q_readError(QtJsonDb::QJsonDbRequest::ErrorCode,QString))); + QObject::connect(&countRequest, SIGNAL(finished(int,QList<QJsonObject>,QString)), + q, SLOT(_q_countResponse(int,QList<QJsonObject>))); + QObject::connect(&countRequest, SIGNAL(error(QtJsonDb::QJsonDbRequest::ErrorCode,QString)), + q, SLOT(_q_readError(QtJsonDb::QJsonDbRequest::ErrorCode,QString))); + } JsonDbListModelPrivate::~JsonDbListModelPrivate() { - // Why do we need to do this while destroying the object - if (!notifyUuid.isEmpty()) { - jsonDb.unregisterNotification(notifyUuid); - } + clearNotification(); } void JsonDbListModelPrivate::clearCache(int newStart) @@ -217,7 +221,6 @@ void JsonDbListModelPrivate::insertItem(const QVariantMap &item, bool emitSignal // When a new item is added, the position of the item is not known // to the model. We will clear the cache and notify that an item // is added at the end + all data is changed. - QModelIndex parent; q->beginInsertRows(parent, totalRowCount-1, totalRowCount-1); q->endInsertRows(); emit q->countChanged(); @@ -239,7 +242,6 @@ void JsonDbListModelPrivate::deleteItem(const QVariantMap &item, bool emitSignal int index = cachedUuids.indexOf(uuid); if (index != -1) { // When item is in the cache emit signals using the exact position. - QModelIndex parent; if (emitSignals) q->beginRemoveRows(parent, cacheStart+index, cacheStart+index); removeItem(index); @@ -253,7 +255,6 @@ void JsonDbListModelPrivate::deleteItem(const QVariantMap &item, bool emitSignal // Model dosen't know the position from where the item is deleted. // We will clear the cache and notify that an item is removed // from the end + all data is changed. - QModelIndex parent; if (!totalRowCount) emitSignals = false; if (emitSignals) @@ -313,17 +314,68 @@ void JsonDbListModelPrivate::_q_requestAnotherChunk(int offset) newChunkOffset = cacheEnd; // now fetch more resetModel = false; - int id = jsonDb.query(query, newChunkOffset, maxItemsToFetch, partitionObject->name()); - requestIds.insert(id); - + QJsonDbReadRequest *request = valueRequest.newRequest(0); + request->setQuery(query); + request->setProperty("queryOffset", newChunkOffset); + request->setQueryLimit(maxItemsToFetch); + request->setPartition(partitionObject->name()); + JsonDatabase::sharedConnection().send(request); requestInProgress = true; } +ModelSyncCall::ModelSyncCall(const QString &_query, int _offset, int _maxItems, + const QString & _partitionName, QVariantList *_data) + : query(_query), + offset(_offset), + maxItems(_maxItems), + partitionName(_partitionName), + data(_data) +{ + +} +ModelSyncCall::~ModelSyncCall() +{ + if (request) + delete request; + if (connection) + delete connection; +} + +void ModelSyncCall::createSyncRequest() +{ + connection = new QJsonDbConnection(); + connection->connectToServer(); + request = new QJsonDbReadRequest; + connect(request, SIGNAL(finished()), this, SLOT(onQueryFinished())); + connect(request, SIGNAL(error(QtJsonDb::QJsonDbRequest::ErrorCode,QString)), + this, SLOT(onQueryError(QtJsonDb::QJsonDbRequest::ErrorCode,QString))); + request->setQuery(query); + request->setProperty("queryOffset", offset); + request->setQueryLimit(maxItems); + request->setPartition(partitionName); + connection->send(request); + //qDebug()<<"createSyncRequest Query :"<<query<<request->property("requestId"); +} + +void ModelSyncCall::onQueryFinished() +{ + *data = qjsonobject_list_to_qvariantlist(request->takeResults()); + //qDebug()<<"onQueryFinished Query :"<<query<<request->property("requestId"); + QThread::currentThread()->quit(); +} + +void ModelSyncCall::onQueryError(QtJsonDb::QJsonDbRequest::ErrorCode code, const QString &message) +{ + qWarning() << QString("JsonDbListModel error: %1 %2").arg(code).arg(message); + QThread::currentThread()->quit(); +} + void JsonDbListModelPrivate::fetchChunkSynchronous(int offset) { // Ignore previous reqests if (requestInProgress) { - requestIds.clear(); + //requestIds.clear(); + valueRequest.resetRequest(); } Q_ASSERT(!query.isEmpty()); int maxItemsToFetch = chunkSize; @@ -337,32 +389,49 @@ void JsonDbListModelPrivate::fetchChunkSynchronous(int offset) // now fetch more resetModel = false; requestInProgress = true; - QVariantMap request = JsonDbConnection::makeQueryRequest(query, newChunkOffset, maxItemsToFetch, - QMap<QString,QVariant>(), partitionObject->name()); - QVariant v = jsonDbConnection->sync(request); + QVariantList resultList; + QThread syncThread; + ModelSyncCall *call = new ModelSyncCall(query, newChunkOffset, maxItemsToFetch, + partitionObject->name(), &resultList); + QObject::connect(&syncThread, SIGNAL(started()), + call, SLOT(createSyncRequest())); + QObject::connect(&syncThread, SIGNAL(finished()), + call, SLOT(deleteLater())); + call->moveToThread(&syncThread); + syncThread.start(); + syncThread.wait(); + updateCache(resultList); requestInProgress = false; - updateCache(v.toMap()); } void JsonDbListModelPrivate::populateModel() { Q_Q(JsonDbListModel); clearCache(); - updateRecieved = false; + updateReceived = false; totalRowCountRecieved = false; totalRowCount = 0; + newChunkOffset = 0; // Request the total count QString countQuery = query+"[count]"; - totalCountRequestId = jsonDb.query(countQuery, 0, -1, partitionObject->name()); - + QJsonDbReadRequest *cRequest = countRequest.newRequest(0); + cRequest->setQuery(countQuery); + cRequest->setPartition(partitionObject->name()); + JsonDatabase::sharedConnection().send(cRequest); + //qDebug()<<"Count Query :"<<countQuery<<cRequest->property("requestId"); //Request at least 2 chunks of data int itemsToGet = chunkSize*2; if (maxCacheSize) itemsToGet = qMin(itemsToGet, maxCacheSize); resetModel = true; - - int id = jsonDb.query(query, newChunkOffset, itemsToGet, partitionObject->name()); - requestIds.insert(id); + QJsonDbReadRequest *request = valueRequest.newRequest(0); + request->setQuery(query); + request->setProperty("queryOffset", newChunkOffset); //TODO change newChunkOffset to 0 + request->setQueryLimit(itemsToGet); + request->setPartition(partitionObject->name()); + JsonDatabase::sharedConnection().send(request); + //qDebug()<<"Query :"<<query<<request->property("requestId")<<newChunkOffset; + createOrUpdateNotification(); requestInProgress = true; state = JsonDbListModelPrivate::Querying; emit q->stateChanged(); @@ -515,24 +584,28 @@ void JsonDbListModel::componentComplete() d->populateModel(); } -void JsonDbListModelPrivate::createOrUpdateNotification() +void JsonDbListModelPrivate::clearNotification() { - Q_Q(JsonDbListModel); - - if (!notifyUuid.isEmpty()) { - jsonDb.unregisterNotification(notifyUuid); - notifyUuid.clear(); + if (watcher) { + JsonDatabase::sharedConnection().removeWatcher(watcher); + delete watcher; + watcher = 0; } +} - JsonDbClient::NotifyTypes notifyActions = JsonDbClient::NotifyCreate - | JsonDbClient::NotifyUpdate| JsonDbClient::NotifyRemove; - - notifyUuid = jsonDb.registerNotification( - notifyActions , query, partitionObject->name(), - q, SLOT(_q_dbNotified(QString,QtAddOn::JsonDb::JsonDbNotification)), - q, SLOT(_q_dbNotifyReadyResponse(int,QVariant)), - SLOT(_q_dbNotifyErrorResponse(int,int,QString))); - +void JsonDbListModelPrivate::createOrUpdateNotification() +{ + Q_Q(JsonDbListModel); + clearNotification(); + watcher = new QJsonDbWatcher(); + watcher->setQuery(query); + watcher->setWatchedActions(QJsonDbWatcher::Created | QJsonDbWatcher::Updated |QJsonDbWatcher::Removed); + watcher->setPartition(partitionObject->name()); + QObject::connect(watcher, SIGNAL(notificationsAvailable(int)), + q, SLOT(_q_notificationsAvailable())); + QObject::connect(watcher, SIGNAL(error(QtJsonDb::QJsonDbWatcher::ErrorCode,QString)), + q, SLOT(_q_notificationError(QtJsonDb::QJsonDbWatcher::ErrorCode,QString))); + JsonDatabase::sharedConnection().addWatcher(watcher); } int JsonDbListModel::sectionIndex(const QString §ion, @@ -540,20 +613,69 @@ int JsonDbListModel::sectionIndex(const QString §ion, const QJSValue &errorCallback) { Q_D(JsonDbListModel); + if (!successCallback.isCallable()) { + qWarning("JsonDbListModel Cannot call sectionIndex without a success callbak function"); + return -1; + } // Find the count of items "< section" QString sectionCountQueryLT = d->queryWithoutSort+"[?"+d->orderProperties[0]+"<\""+section+"\"][count]"; - int id = d->jsonDb.query(sectionCountQueryLT, 0, -1, d->partitionObject->name()); - // Register any valid callbacks + + QJsonDbReadRequest *request = new QJsonDbReadRequest(); + connect(request, SIGNAL(finished()), this, SLOT(_q_sectionIndexResponse())); + connect(request, SIGNAL(error(QtJsonDb::QJsonDbRequest::ErrorCode,QString)), + this, SLOT(_q_sectionIndexError(QtJsonDb::QJsonDbRequest::ErrorCode,QString))); + request->setQuery(sectionCountQueryLT); + request->setPartition(d->partitionObject->name()); + JsonDatabase::sharedConnection().send(request); + int id = request->property("requestId").toInt(); CallbackInfo info; - if (successCallback.isCallable() - || errorCallback.isCallable()) { - info.successCallback = successCallback; - info.errorCallback = errorCallback; - d->sectionIndexRequestIds.insert(id, info); - } + info.successCallback = successCallback; + info.errorCallback = errorCallback; + d->sectionIndexCallbacks.insert(request, info); return id; } +void JsonDbListModelPrivate::_q_sectionIndexResponse() +{ + Q_Q(JsonDbListModel); + QJsonDbReadRequest *request = qobject_cast<QJsonDbReadRequest*>(q->sender()); + if (request) { + QList<QJsonObject> v = request->takeResults(); + if (v.count()) { + int id = request->property("requestId").toInt(); + int count = (int) v[0].value(QStringLiteral("count")).toDouble(); + CallbackInfo info = sectionIndexCallbacks.value(request); + if (info.successCallback.isCallable()) { + QJSValueList args; + args << info.successCallback.engine()->toScriptValue(id); + args << info.successCallback.engine()->toScriptValue(count); + info.successCallback.call(args); + } + } + sectionIndexCallbacks.remove(request); + request->deleteLater(); + } +} + +void JsonDbListModelPrivate::_q_sectionIndexError(QtJsonDb::QJsonDbRequest::ErrorCode code, const QString &message) +{ + Q_Q(JsonDbListModel); + QJsonDbReadRequest *request = qobject_cast<QJsonDbReadRequest*>(q->sender()); + if (request) { + int id = request->property("requestId").toInt(); + CallbackInfo info = sectionIndexCallbacks.value(request); + if (info.errorCallback.isCallable()) { + QJSValueList args; + args << info.successCallback.engine()->toScriptValue(id); + args << info.successCallback.engine()->toScriptValue(int(code)); + args << info.successCallback.engine()->toScriptValue(message); + info.errorCallback.call(args); + } + sectionIndexCallbacks.remove(request); + request->deleteLater(); + } +} + int JsonDbListModel::count() const { Q_D(const JsonDbListModel); @@ -638,17 +760,7 @@ void JsonDbListModelPrivate::set(int index, const QJSValue& valuemap, lastFetchedItem.clear(); lastFetchedIndex = -1; - // Item will be updated through the update notification - CallbackInfo info; - info.index = index; - int id = jsonDb.update(item, partitionObject->name()); // possibly change to variantToQson(item).. - // Register any valid callbacks - if (successCallback.isCallable() - || errorCallback.isCallable()) { - info.successCallback = successCallback; - info.errorCallback = errorCallback; - updateRequestIds.insert(id, info); - } + update(index, item, successCallback, errorCallback); } void JsonDbListModel::setProperty(int index, const QString& property, const QVariant& value, @@ -689,18 +801,61 @@ void JsonDbListModelPrivate::setProperty(int index, const QString& property, con lastFetchedItem.clear(); lastFetchedIndex = -1; + update(index, item, successCallback, errorCallback); +} + +void JsonDbListModelPrivate::update(int index, const QVariantMap &item, + const QJSValue &successCallback, const QJSValue &errorCallback) +{ + Q_Q(JsonDbListModel); + QJsonDbUpdateRequest *request = new QJsonDbUpdateRequest(QJsonObject::fromVariantMap(item)); + QObject::connect(request, SIGNAL(finished()), q, SLOT(_q_updateResponse())); + QObject::connect(request, SIGNAL(error(QtJsonDb::QJsonDbRequest::ErrorCode,QString)), + q, SLOT(_q_updateError(QtJsonDb::QJsonDbRequest::ErrorCode,QString))); + request->setPartition(partitionObject->name()); + JsonDatabase::sharedConnection().send(request); + CallbackInfo info; + info.index = index; + info.successCallback = successCallback; + info.errorCallback = errorCallback; + updateCallbacks.insert(request, info); +} - int id = jsonDb.update(item, partitionObject->name()); // possibly change to variantToQson(item).. - // Register any valid callbacks - if (successCallback.isCallable() - || errorCallback.isCallable()) { - - // Item will be updated through the update notification - CallbackInfo info; - info.index = index; - info.successCallback = successCallback; - info.errorCallback = errorCallback; - updateRequestIds.insert(id, info); +void JsonDbListModelPrivate::_q_updateResponse() +{ + Q_Q(JsonDbListModel); + QJsonDbWriteRequest *request = qobject_cast<QJsonDbWriteRequest*>(q->sender()); + if (request) { + int id = request->property("requestId").toInt(); + CallbackInfo info = updateCallbacks.value(request); + if (info.successCallback.isCallable()) { + QJSValueList args; + args << info.successCallback.engine()->toScriptValue(id); + args << info.successCallback.engine()->toScriptValue(info.index); + info.successCallback.call(args); + } + } + updateCallbacks.remove(request); + request->deleteLater(); +} + +void JsonDbListModelPrivate::_q_updateError(QtJsonDb::QJsonDbRequest::ErrorCode code, const QString &message) +{ + Q_Q(JsonDbListModel); + QJsonDbWriteRequest *request = qobject_cast<QJsonDbWriteRequest*>(q->sender()); + if (request) { + int id = request->property("requestId").toInt(); + CallbackInfo info = updateCallbacks.value(request); + if (info.errorCallback.isCallable()) { + QJSValueList args; + args << info.successCallback.engine()->toScriptValue(id); + args << info.successCallback.engine()->toScriptValue(info.index); + args << info.successCallback.engine()->toScriptValue(int(code)); + args << info.successCallback.engine()->toScriptValue(message); + info.errorCallback.call(args); + } + updateCallbacks.remove(request); + request->deleteLater(); } } @@ -963,94 +1118,66 @@ int JsonDbListModel::roleFromString(const QString &roleName) const return d->roleNames.key(roleName.toLatin1(), -1); } -void JsonDbListModelPrivate::updateCache(const QVariantMap &m) +void JsonDbListModelPrivate::updateCache(const QVariantList &items) { Q_Q(JsonDbListModel); - if (m.contains("data")) { - QVariantList items = m.value(QLatin1String("data")).toList(); - int size = items.size(); - int sizeAdded = 0; - if (size) { - DEBUG()<<"OLD Cache Start"<<cacheStart<<"Cache End:"<<cacheEnd; - if (resetModel) - q->beginResetModel(); - makeSpaceFor(size, newChunkOffset); - bool appendToCache = (newChunkOffset >= cacheEnd) ? true : false; - int insertAt = appendToCache ? itemsInCache() : 0; - DEBUG()<<"INSERT AT :"<<insertAt<<"Elements Retrieved:"<<size<<"ChunkOffset:"<<newChunkOffset<<appendToCache << itemsInCache(); - DEBUG()<<"Cache Start"<<cacheStart<<"Cache End:"<<cacheEnd<<"Total Rows = "<<totalRowCount; - // Add the new result to cache. - for (int i = 0; i < size; i++) { - QVariantMap item = items.at(i).toMap(); - const QString &uuid = item.value(JsonDbString::kUuidStr).toString(); - if (objectSortValues.contains(uuid)){ - break; - } - JsonDbSortKey key = sortKey(item); - objectUuids.insert(key, uuid); - objectSortValues.insert(uuid, key); - data[uuid] = item; - cachedUuids.insert(insertAt++, uuid); - sizeAdded++; + int size = items.size(); + int sizeAdded = 0; + if (size) { + DEBUG()<<"OLD Cache Start"<<cacheStart<<"Cache End:"<<cacheEnd; + if (resetModel) + q->beginResetModel(); + makeSpaceFor(size, newChunkOffset); + bool appendToCache = (newChunkOffset >= cacheEnd) ? true : false; + int insertAt = appendToCache ? itemsInCache() : 0; + DEBUG()<<"INSERT AT :"<<insertAt<<"Elements Retrieved:"<<size<<"ChunkOffset:"<<newChunkOffset<<appendToCache << itemsInCache(); + DEBUG()<<"Cache Start"<<cacheStart<<"Cache End:"<<cacheEnd<<"Total Rows = "<<totalRowCount; + // Add the new result to cache. + for (int i = 0; i < size; i++) { + QVariantMap item = items.at(i).toMap(); + const QString &uuid = item.value(QStringLiteral("_uuid")).toString(); + if (objectSortValues.contains(uuid)){ + break; } - DEBUG()<<"sizeAdded:"<<sizeAdded; - // Update the cache limits - if (!itemsInCache()) { - cacheStart = newChunkOffset; - cacheEnd = cacheStart + sizeAdded; - } else if (appendToCache) { - cacheEnd += sizeAdded; - } else { - cacheStart = qMax(0, cacheStart-sizeAdded); - } - Q_ASSERT(cachedUuids.count() == data.count()); + JsonDbSortKey key = sortKey(item); + objectUuids.insert(key, uuid); + objectSortValues.insert(uuid, key); + data[uuid] = item; + cachedUuids.insert(insertAt++, uuid); + sizeAdded++; } - if (resetModel && totalRowCountRecieved) - resetModelFinished(); - else - updateRecieved = true; + DEBUG()<<"sizeAdded:"<<sizeAdded; + // Update the cache limits + if (!itemsInCache()) { + cacheStart = newChunkOffset; + cacheEnd = cacheStart + sizeAdded; + } else if (appendToCache) { + cacheEnd += sizeAdded; + } else { + cacheStart = qMax(0, cacheStart-sizeAdded); + } + Q_ASSERT(cachedUuids.count() == data.count()); } + if (resetModel && totalRowCountRecieved) + resetModelFinished(); + else + updateReceived = true; } -void JsonDbListModelPrivate::_q_jsonDbResponse(int id, const QVariant &v) +void JsonDbListModelPrivate::_q_valueResponse(int, const QList<QJsonObject> &v) { - if (requestIds.contains(id)) { - requestIds.remove(id); - requestInProgress = false; - updateCache(v.toMap()); - } else if (totalCountRequestId == id) { - QVariantMap m = v.toMap(); - QVariantList items = m.value(QLatin1String("data")).toList(); - m = items.at(0).toMap(); - totalRowCount = m.value(QLatin1String("count")).toInt(); + requestInProgress = false; + updateCache(qjsonobject_list_to_qvariantlist(v)); +} + +void JsonDbListModelPrivate::_q_countResponse(int, const QList<QJsonObject> &v) +{ + if (v.count()) { + totalRowCount = (int) v[0].value(QStringLiteral("count")).toDouble(); totalRowCountRecieved = true; - if (updateRecieved) + + if (updateReceived) resetModelFinished(); - } else if (updateRequestIds.constFind(id) != updateRequestIds.constEnd()) { - CallbackInfo info = updateRequestIds.value(id); - if (info.successCallback.isCallable()) { - QJSValueList args; - QJSValue scriptResult = info.successCallback.engine()->toScriptValue(id); - args << scriptResult; - scriptResult = info.successCallback.engine()->toScriptValue(info.index); - args << scriptResult; - info.successCallback.call(args); - } - updateRequestIds.remove(id); - } else if (sectionIndexRequestIds.constFind(id) != sectionIndexRequestIds.constEnd()) { - CallbackInfo info = sectionIndexRequestIds.value(id); - if (info.successCallback.isCallable()) { - QVariantMap m = v.toMap(); - QVariantList items = m.value(QLatin1String("data")).toList(); - m = items.at(0).toMap(); - QJSValueList args; - QJSValue scriptResult = info.successCallback.engine()->toScriptValue(id); - args << scriptResult; - scriptResult = info.successCallback.engine()->toScriptValue(m.value(QLatin1String("count")).toInt()); - args << scriptResult; - info.successCallback.call(args); - } - sectionIndexRequestIds.remove(id); } } @@ -1063,8 +1190,12 @@ void JsonDbListModelPrivate::resetModelFinished() state = Ready; emit q->stateChanged(); resetModel = false; + for (int i = 0; i<pendingNotifications.size(); i++) { + const NotifyItem &pending = pendingNotifications[i]; + sendNotifications(pending.item, pending.action); + } pendingNotifications.clear(); - createOrUpdateNotification(); + //createOrUpdateNotification(); } bool operator<(const QVariant& a, const QVariant& b) @@ -1105,62 +1236,55 @@ bool JsonDbListModelPrivate::findSortOrder() return true; } -void JsonDbListModelPrivate::_q_dbNotified(const QString ¬ify_uuid, const QtAddOn::JsonDb::JsonDbNotification &_notification) +void JsonDbListModelPrivate::_q_notificationsAvailable() { - if (notify_uuid != notifyUuid) { - return; - } - if (resetModel) { - NotifyItem pending; - pending.notifyUuid = notify_uuid; - pending.item = _notification.object(); - pending.action = _notification.action(); - pendingNotifications.append(pending); - } else { - sendNotifications(_notification.object(), _notification.action()); + QList<QJsonDbNotification> list = watcher->takeNotifications(); + for (int i = 0; i < list.count(); i++) { + const QJsonDbNotification & notification = list[i]; + QVariantMap object = notification.object().toVariantMap(); + if (resetModel) { + NotifyItem pending; + pending.item = object; + pending.action = notification.action(); + pendingNotifications.append(pending); + } else { + //qDebug()<<"Notify "<<object<<notification.action(); + sendNotifications(object, notification.action()); + } } } -void JsonDbListModelPrivate::sendNotifications(const QVariant &v, JsonDbClient::NotifyType action) +void JsonDbListModelPrivate::sendNotifications(const QVariantMap &v, QJsonDbWatcher::Action action) { - const QVariantMap &item = v.toMap(); - if (action == JsonDbClient::NotifyCreate) { - insertItem(item); - } else if (action == JsonDbClient::NotifyRemove) { - deleteItem(item); - } else if (action == JsonDbClient::NotifyUpdate) { - updateItem(item); + if (action == QJsonDbWatcher::Created) { + insertItem(v); + } else if (action == QJsonDbWatcher::Removed) { + deleteItem(v); + } else if (action == QJsonDbWatcher::Updated) { + updateItem(v); } } -void JsonDbListModelPrivate::_q_dbNotifyReadyResponse(int /* id */, const QVariant &/* result */) +void JsonDbListModelPrivate::_q_notificationError(QtJsonDb::QJsonDbWatcher::ErrorCode code, const QString &message) { -} - -void JsonDbListModelPrivate::_q_dbNotifyErrorResponse(int id, int code, const QString &message) -{ - Q_UNUSED(id); + Q_Q(JsonDbListModel); qWarning() << QString("JsonDbListModel Notification error: %1 %2").arg(code).arg(message); + int oldErrorCode = errorCode; + errorCode = code; + errorString = message; + if (oldErrorCode != errorCode) + emit q->errorChanged(q->error()); } - -void JsonDbListModelPrivate::_q_jsonDbErrorResponse(int id, int code, const QString &message) +void JsonDbListModelPrivate::_q_readError(QtJsonDb::QJsonDbRequest::ErrorCode code, const QString & message) { - if (requestIds.contains(id)) { - requestIds.remove(id); - qWarning() << QString("JsonDb error: %1 %2").arg(code).arg(message); - } else if (updateRequestIds.constFind(id) != updateRequestIds.constEnd()) { - CallbackInfo info = updateRequestIds.value(id); - if (info.errorCallback.isCallable()) { - QJSValueList args; - args << info.errorCallback.engine()->toScriptValue(id); - args << info.errorCallback.engine()->toScriptValue(info.index); - args << info.errorCallback.engine()->toScriptValue(code); - args << info.errorCallback.engine()->toScriptValue(message); - info.errorCallback.call(args); - } - updateRequestIds.remove(id); - } + Q_Q(JsonDbListModel); + qWarning() << QString("JsonDbListModel error: %1 %2").arg(code).arg(message); + int oldErrorCode = errorCode; + errorCode = code; + errorString = message; + if (oldErrorCode != errorCode) + emit q->errorChanged(q->error()); } /*! @@ -1175,10 +1299,31 @@ QVariant JsonDbListModel::get(int idx, const QString &property) const int role = roleFromString(property); if (role >= 0) return data(index(idx, 0), role); - else + else { + qDebug()<<"JsonDbListModel::get Invalid role"; return QVariant(); + } } +/*! + \qmlproperty object QtJsonDb::JsonDbListModel::error + \readonly + + This property holds the current error information for the object. It contains: + \list + \o error.code - code for the current error. + \o error.message - detailed explanation of the error + \endlist +*/ + +QVariantMap JsonDbListModel::error() const +{ + Q_D(const JsonDbListModel); + QVariantMap errorMap; + errorMap.insert(QLatin1String("code"), d->errorCode); + errorMap.insert(QLatin1String("message"), d->errorString); + return errorMap; +} class JsonDbSortKeyPrivate : public QSharedData { public: diff --git a/src/imports/jsondb/jsondblistmodel.h b/src/imports/jsondb/jsondblistmodel.h index 36494e6..a054b52 100644 --- a/src/imports/jsondb/jsondblistmodel.h +++ b/src/imports/jsondb/jsondblistmodel.h @@ -52,7 +52,7 @@ #include <QJSValue> #include <QScopedPointer> -#include "jsondb-global.h" +#include <QJsonDbReadRequest> #include "jsondbpartition.h" QT_BEGIN_NAMESPACE_JSONDB @@ -92,6 +92,7 @@ public: Q_PROPERTY(int lowWaterMark READ lowWaterMark WRITE setLowWaterMark) Q_PROPERTY(QVariant roleNames READ scriptableRoleNames WRITE setScriptableRoleNames) Q_PROPERTY(JsonDbPartition* partition READ partition WRITE setPartition) + Q_PROPERTY(QVariantMap error READ error NOTIFY errorChanged) virtual void classBegin(); virtual void componentComplete(); @@ -136,11 +137,13 @@ public: const QJSValue &errorCallback = QJSValue(QJSValue::UndefinedValue)); Q_INVOKABLE int sectionIndex(const QString §ion, const QJSValue &successCallback = QJSValue(QJSValue::UndefinedValue), const QJSValue &errorCallback = QJSValue(QJSValue::UndefinedValue)); + QVariantMap error() const; signals: void stateChanged() const; void countChanged() const; void rowCountChanged() const; + void errorChanged(QVariantMap newError); private Q_SLOTS: void partitionNameChanged(const QString &partitionName); @@ -149,15 +152,39 @@ private: Q_DISABLE_COPY(JsonDbListModel) Q_DECLARE_PRIVATE(JsonDbListModel) QScopedPointer<JsonDbListModelPrivate> d_ptr; - Q_PRIVATE_SLOT(d_func(), void _q_jsonDbResponse(int, const QVariant&)) - Q_PRIVATE_SLOT(d_func(), void _q_jsonDbErrorResponse(int, int, const QString&)) Q_PRIVATE_SLOT(d_func(), void _q_requestAnotherChunk(int)) - Q_PRIVATE_SLOT(d_func(), void _q_dbNotified(QString, QtAddOn::JsonDb::JsonDbNotification)) - Q_PRIVATE_SLOT(d_func(), void _q_dbNotifyReadyResponse(int, QVariant)) - Q_PRIVATE_SLOT(d_func(), void _q_dbNotifyErrorResponse(int, int, QString)) + Q_PRIVATE_SLOT(d_func(), void _q_notificationsAvailable()) + Q_PRIVATE_SLOT(d_func(), void _q_notificationError(QtJsonDb::QJsonDbWatcher::ErrorCode, QString)) + Q_PRIVATE_SLOT(d_func(), void _q_valueResponse(int, QList<QJsonObject>)) + Q_PRIVATE_SLOT(d_func(), void _q_countResponse(int, QList<QJsonObject>)) + Q_PRIVATE_SLOT(d_func(), void _q_readError(QtJsonDb::QJsonDbRequest::ErrorCode, QString)) + Q_PRIVATE_SLOT(d_func(), void _q_sectionIndexResponse()) + Q_PRIVATE_SLOT(d_func(), void _q_sectionIndexError(QtJsonDb::QJsonDbRequest::ErrorCode, QString)) + Q_PRIVATE_SLOT(d_func(), void _q_updateResponse()) + Q_PRIVATE_SLOT(d_func(), void _q_updateError(QtJsonDb::QJsonDbRequest::ErrorCode, QString)) }; +class ModelSyncCall : public QObject +{ + Q_OBJECT +public: + ModelSyncCall(const QString &_query, int _offset, int _maxItems, const QString & _partitionName, QVariantList *_data); + ~ModelSyncCall(); +public Q_SLOTS: + void createSyncRequest(); + void onQueryFinished(); + void onQueryError(QtJsonDb::QJsonDbRequest::ErrorCode, const QString&); +private: + QString query; + int offset; + int maxItems; + QString partitionName; + QVariantList *data; + QPointer<QJsonDbConnection> connection; + QPointer<QJsonDbReadRequest> request; +}; + QT_END_NAMESPACE_JSONDB #endif diff --git a/src/imports/jsondb/jsondblistmodel_p.h b/src/imports/jsondb/jsondblistmodel_p.h index fd773b8..7852fa4 100644 --- a/src/imports/jsondb/jsondblistmodel_p.h +++ b/src/imports/jsondb/jsondblistmodel_p.h @@ -49,8 +49,10 @@ #include <QStringList> #include <QPointer> -#include "jsondb-client.h" -#include "private/jsondb-connection_p.h" + +#include <QJsonDbWatcher> +#include <QJsonDbReadRequest> +#include <QJsonDbUpdateRequest> #include "jsondbmodelutils.h" QT_BEGIN_NAMESPACE_JSONDB @@ -72,10 +74,8 @@ public: int cacheEnd; int newChunkOffset; - QSet<int> requestIds; - QMap<int, CallbackInfo> updateRequestIds; - QMap<int, CallbackInfo> sectionIndexRequestIds; - int totalCountRequestId; + QMap< QPointer<QJsonDbWriteRequest>, CallbackInfo> updateCallbacks; + QMap< QPointer<QJsonDbReadRequest>, CallbackInfo> sectionIndexCallbacks; QHash<QString,QVariantMap> data; // cache that holds all the items. QMultiMap<JsonDbSortKey,QString> objectUuids; // sort value -> uuid @@ -94,15 +94,17 @@ public: bool requestInProgress; bool componentComplete; bool resetModel; - bool updateRecieved; + bool updateReceived; bool totalRowCountRecieved; - QString notifyUuid; QVariantMap roleMap; QHash<int,QByteArray> roleNames; QHash<int,QStringList> properties; QList<NotifyItem> pendingNotifications; + ModelRequest valueRequest; + ModelRequest countRequest; + QPointer<QJsonDbWatcher> watcher; enum State { None, @@ -110,9 +112,9 @@ public: Ready }; State state; - - JsonDbClient jsonDb; - JsonDbConnection *jsonDbConnection; + QModelIndex parent; + int errorCode; + QString errorString; public: JsonDbListModelPrivate(JsonDbListModel *q); @@ -130,26 +132,31 @@ public: QVariantMap getItem(const QModelIndex &modelIndex, int role, bool handleCacheMiss, bool &cacheMiss); void set(int index, const QJSValue& valuemap, const QJSValue &successCallback, const QJSValue &errorCallback); - void setProperty(int index, const QString& property, const QVariant& value, const QJSValue &successCallback, - const QJSValue &errorCallback); + void setProperty(int index, const QString& property, const QVariant& value, + const QJSValue &successCallback, const QJSValue &errorCallback); void fetchChunkSynchronous(int offset); - void updateCache(const QVariantMap &v); + void updateCache(const QVariantList &items); void resetModelFinished(); - - // private slots - void _q_jsonDbResponse(int , const QVariant &); - void _q_jsonDbNotified(const QString&, const QVariant &, const QString &); - void _q_jsonDbErrorResponse(int , int, const QString&); + void update(int index, const QVariantMap &item, + const QJSValue &successCallback, const QJSValue &errorCallback); void _q_requestAnotherChunk(int offset); - void _q_dbNotified(const QString ¬ify_uuid, const QtAddOn::JsonDb::JsonDbNotification &_notification); - void _q_dbNotifyReadyResponse(int /* id */, const QVariant &/* result */); - void _q_dbNotifyErrorResponse(int id, int code, const QString &message); - void sendNotifications(const QVariant &v, JsonDbClient::NotifyType action); + void _q_notificationsAvailable(); + void _q_notificationError(QtJsonDb::QJsonDbWatcher::ErrorCode code, const QString &message); + void _q_valueResponse(int , const QList<QJsonObject>&); + void _q_countResponse(int , const QList<QJsonObject>&); + void _q_readError(QtJsonDb::QJsonDbRequest::ErrorCode code, const QString & message); + void _q_sectionIndexResponse(); + void _q_sectionIndexError(QtJsonDb::QJsonDbRequest::ErrorCode code, const QString & message); + void _q_updateResponse(); + void _q_updateError(QtJsonDb::QJsonDbRequest::ErrorCode code, const QString & message); + + void sendNotifications(const QVariantMap &v, QJsonDbWatcher::Action action); void populateModel(); + void clearNotification(); void createOrUpdateNotification(); bool findSortOrder(); diff --git a/src/imports/jsondb/jsondbmodelcache.cpp b/src/imports/jsondb/jsondbmodelcache.cpp index c9817ba..0e01cd9 100644 --- a/src/imports/jsondb/jsondbmodelcache.cpp +++ b/src/imports/jsondb/jsondbmodelcache.cpp @@ -62,7 +62,7 @@ bool ModelPage::hasIndex(int pos) return (pos >= index && pos < (index+count)); } -QVariantMap ModelPage::value(const QString &key) +QJsonObject ModelPage::value(const QString &key) { counter = ++ModelCache::currentCounter; return objects.value(key); @@ -74,7 +74,7 @@ bool ModelPage::hasValue(const QString &key) return objects.contains(key); } -bool ModelPage::insert(int pos, const QString &key, const QVariantMap &value) +bool ModelPage::insert(int pos, const QString &key, const QJsonObject &value) { // allow adding a consecutive item if (pos >= index && pos <= (index+count)) { @@ -86,7 +86,7 @@ bool ModelPage::insert(int pos, const QString &key, const QVariantMap &value) return false; } -bool ModelPage::update(const QString &key, const QVariantMap &value) +bool ModelPage::update(const QString &key, const QJsonObject &value) { bool ret = (objects.remove(key) >= 1); if (ret) { @@ -139,9 +139,10 @@ int ModelCache::findPage(int pos) return -1; } -QVariantMap ModelCache::valueAtPage(int page, const QString &key) +QJsonObject ModelCache::valueAtPage(int page, const QString &key) { Q_ASSERT(page >= 0 && page < pages.count()); + QJsonObject o = pages[page]->value(key); return pages[page]->value(key); } @@ -163,7 +164,7 @@ void ModelCache::splitPage(int page, const JsonDbModelIndexType &objectUuids) for (int i = halfPage->index; i < halfPage->index+halfPage->count; i++) { // transfer the items to the new page const QString &key = (begin+i).value(); - const QVariantMap &value = pages[page]->value(key); + const QJsonObject &value = pages[page]->value(key); halfPage->objects.insert(key, value); pages[page]->objects.remove(key); } @@ -171,7 +172,7 @@ void ModelCache::splitPage(int page, const JsonDbModelIndexType &objectUuids) pages.append(halfPage); } -bool ModelCache::insert(int pos, const QString &key, const QVariantMap &value, +bool ModelCache::insert(int pos, const QString &key, const QJsonObject &value, const JsonDbModelIndexType &objectUuids) { if (!pages.count()) { @@ -218,7 +219,7 @@ int ModelCache::count() return items; } -bool ModelCache::update(const QString &key, const QVariantMap &value) +bool ModelCache::update(const QString &key, const QJsonObject &value) { for (int i = 0; i < pages.count(); i++) { if (pages[i]->update(key, value)) @@ -296,7 +297,11 @@ void ModelCache::addObjects(int index, const JsonDbModelIndexType &objectUuids, newPage->index = j; for (; j < index+count && j < maxIndexForPage; j++) { const QString &key = (begin+j).value(); - const QVariantMap& value = objects.value(key); + const QJsonObject& value = objects.value(key); +#ifdef JSONDB_LISTMODEL_DEBUG + if (value.isEmpty()) // Could be an assert instead? + qDebug() << "##################Empty value###############" << key; +#endif newPage->objects.insert(key, value); } newPage->count = newPage->objects.count(); diff --git a/src/imports/jsondb/jsondbmodelcache.h b/src/imports/jsondb/jsondbmodelcache.h index 3b0e8ac..83ace7d 100644 --- a/src/imports/jsondb/jsondbmodelcache.h +++ b/src/imports/jsondb/jsondbmodelcache.h @@ -46,13 +46,13 @@ #include <QHash> #include <QObject> #include <QList> -#include <QVariantMap> +#include <QJsonObject> #include "jsondbmodelutils.h" QT_BEGIN_NAMESPACE_JSONDB typedef QMap<SortingKey, QString> JsonDbModelIndexType; -typedef QHash<QString, QVariantMap> JsonDbModelObjectType; +typedef QHash<QString, QJsonObject> JsonDbModelObjectType; class ModelPage { @@ -66,11 +66,11 @@ public: ModelPage(); ~ModelPage(); bool hasIndex(int pos); - QVariantMap value(const QString & key); + QJsonObject value(const QString & key); bool hasValue(const QString &key); - bool insert(int pos, const QString &key, const QVariantMap &vlaue); - bool update(const QString &key, const QVariantMap &value); + bool insert(int pos, const QString &key, const QJsonObject &vlaue); + bool update(const QString &key, const QJsonObject &value); bool remove(int pos, const QString &key); void dumpPageDetails(); }; @@ -88,12 +88,12 @@ public: void clear(); int findPage(int pos); - QVariantMap valueAtPage(int page, const QString & key); + QJsonObject valueAtPage(int page, const QString & key); bool hasValueAtPage(int page, const QString &key); - bool insert(int pos, const QString &key, const QVariantMap &vlaue, + bool insert(int pos, const QString &key, const QJsonObject &vlaue, const JsonDbModelIndexType &objectUuids); - bool update(const QString &key, const QVariantMap &value); + bool update(const QString &key, const QJsonObject &value); bool remove(int pos, const QString &key); void splitPage(int pageno, const JsonDbModelIndexType &objectUuids); diff --git a/src/imports/jsondb/jsondbmodelutils.cpp b/src/imports/jsondb/jsondbmodelutils.cpp index 2f48c4d..5cadd27 100644 --- a/src/imports/jsondb/jsondbmodelutils.cpp +++ b/src/imports/jsondb/jsondbmodelutils.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include "jsondbmodelutils.h" +#include <qdebug.h> QT_BEGIN_NAMESPACE_JSONDB @@ -59,6 +60,11 @@ SortingKey::SortingKey(int partitionIndex, const QVariantList &object, const QLi d = new SortingKeyPrivate(partitionIndex, uuid, directions, values, spec); } +SortingKey::SortingKey(int partitionIndex, const QByteArray &uuid, const QVariantList &object, const QList<bool> &directions, const SortIndexSpec &spec) +{ + d = new SortingKeyPrivate(partitionIndex, uuid, directions, object, spec); +} + SortingKey::SortingKey(const SortingKey &other) :d(other.d) { @@ -106,14 +112,17 @@ bool SortingKey::operator <(const SortingKey &rhs) const // The index spec is only applied to the first item if (!i && (dLhs->indexSpec.type == SortIndexSpec::String || dLhs->indexSpec.type == SortIndexSpec::UUID)) { if ((cmp = equalWithSpec(lhsValue, rhsValue, dLhs->indexSpec))) { - return (dLhs->directions[i] ? (cmp < 0) : !(cmp < 0)); + return (dLhs->directions[i] ? (cmp < 0) : (cmp > 0)); } } else if (lhsValue != rhsValue) { - bool result = lhsValue < rhsValue; - return (dLhs->directions[i] ? result :!result); + return (dLhs->directions[i] ? lhsValue < rhsValue : rhsValue < lhsValue); } } - return (memcmp(dLhs->uuid.constData(), dRhs->uuid.constData(), qMin(dLhs->uuid.size(), dRhs->uuid.size())) < 0); + int cmp = memcmp(dLhs->uuid.constData(), dRhs->uuid.constData(), qMin(dLhs->uuid.size(), dRhs->uuid.size())); + // In case of even score jsondb sorts according to _uuid in the same direction as the last sort item + if (nKeys) + return (dLhs->directions[0] ? (cmp < 0) : (cmp > 0)); + return (cmp < 0); } bool SortingKey::operator ==(const SortingKey &rhs) const @@ -200,4 +209,43 @@ QString removeArrayOperator(QString propertyName) return propertyName; } + +ModelRequest::ModelRequest(QObject *parent) + :QObject(parent) +{ +} + +ModelRequest::~ModelRequest() +{ + resetRequest(); +} + +QJsonDbReadRequest* ModelRequest::newRequest(int newIndex) +{ + resetRequest(); + index = newIndex; + request = new QJsonDbReadRequest(); + connect(request, SIGNAL(finished()), this, SLOT(onQueryFinished())); + connect(request, SIGNAL(finished()), request, SLOT(deleteLater())); + connect(request, SIGNAL(error(QtJsonDb::QJsonDbRequest::ErrorCode,QString)), + this, SIGNAL(error(QtJsonDb::QJsonDbRequest::ErrorCode,QString))); + connect(request, SIGNAL(error(QtJsonDb::QJsonDbRequest::ErrorCode,QString)), + request, SLOT(deleteLater())); + return request; +} + +void ModelRequest::resetRequest() +{ + if (request) { + delete request; + request = 0; + } +} + +void ModelRequest::onQueryFinished() +{ + emit finished(index, request->takeResults(), request->sortKey()); +} + +#include "moc_jsondbmodelutils.cpp" QT_END_NAMESPACE_JSONDB diff --git a/src/imports/jsondb/jsondbmodelutils.h b/src/imports/jsondb/jsondbmodelutils.h index 48ac8c3..10d2798 100644 --- a/src/imports/jsondb/jsondbmodelutils.h +++ b/src/imports/jsondb/jsondbmodelutils.h @@ -39,7 +39,6 @@ ** ****************************************************************************/ - #ifndef JSONDBMODELUTILS_H #define JSONDBMODELUTILS_H #include <QSharedData> @@ -47,7 +46,9 @@ #include <QUuid> #include <QJSValue> #include <QVariant> -#include "jsondb-client.h" +#include <QPointer> +#include <QJsonDbWatcher> +#include <QJsonDbReadRequest> QT_BEGIN_NAMESPACE_JSONDB @@ -57,16 +58,21 @@ struct CallbackInfo { QJSValue errorCallback; }; +struct NotificationItem { + int partitionIndex; + QJsonObject item; + QJsonDbWatcher::Action action; +}; + struct NotifyItem { - QString notifyUuid; - QVariant item; - JsonDbClient::NotifyType action; + int partitionIndex; + QVariantMap item; + QJsonDbWatcher::Action action; }; struct SortIndexSpec { QString propertyName; - QString propertyType; //### TODO remove QString name; bool caseSensitive; enum Type { None, String, Number, UUID }; @@ -75,13 +81,35 @@ struct SortIndexSpec SortIndexSpec() : caseSensitive(false), type(SortIndexSpec::None) {} SortIndexSpec(const SortIndexSpec &other) : propertyName(other.propertyName), - propertyType(other.propertyType), name(other.name), caseSensitive(other.caseSensitive), type(other.type) {} }; +class JsonDbListModelPrivate; +class ModelRequest : public QObject +{ + friend class JsonDbListModelPrivate; + Q_OBJECT +public: + + ModelRequest(QObject *parent = 0); + ~ModelRequest(); + + QJsonDbReadRequest* newRequest(int newIndex); + void resetRequest(); +Q_SIGNALS: + void finished(int index, const QList<QJsonObject> &items, const QString &sortKey); + void error(QtJsonDb::QJsonDbRequest::ErrorCode code, const QString &message); + +private Q_SLOTS: + void onQueryFinished(); + +private: + QPointer<QJsonDbReadRequest> request; + int index; +}; struct IndexInfo { @@ -102,6 +130,7 @@ class SortingKey { public: SortingKey(int partitionIndex, const QVariantMap &object, const QList<bool> &directions, const QList<QStringList> &paths, const SortIndexSpec &spec = SortIndexSpec()); SortingKey(int partitionIndex, const QVariantList &object, const QList<bool> &directions, const SortIndexSpec &spec = SortIndexSpec()); + SortingKey(int partitionIndex, const QByteArray &uuid, const QVariantList &object, const QList<bool> &directions, const SortIndexSpec &spec = SortIndexSpec()); SortingKey(const SortingKey&); SortingKey() {} int partitionIndex() const; @@ -113,20 +142,21 @@ private: struct RequestInfo { - int requestId; int lastOffset; - QString notifyUuid; int lastSize; int requestCount; + QPointer<QJsonDbWatcher> watcher; RequestInfo() { clear();} void clear() { - requestId = -1; lastOffset = 0; lastSize = -1; requestCount = 0; - notifyUuid.clear(); + if (watcher) { + delete watcher; + watcher = 0; + } } }; @@ -168,6 +198,8 @@ template <typename T> int iterator_position(T &begin, T &end, T &value) QVariant lookupProperty(QVariantMap object, const QStringList &path); QString removeArrayOperator(QString propertyName); +QList<QJsonObject> qvariantlist_to_qjsonobject_list(const QVariantList &list); +QVariantList qjsonobject_list_to_qvariantlist(const QList<QJsonObject> &list); QT_END_NAMESPACE_JSONDB diff --git a/src/imports/jsondb/jsondbnotification.cpp b/src/imports/jsondb/jsondbnotification.cpp index f55b607..65d74d7 100644 --- a/src/imports/jsondb/jsondbnotification.cpp +++ b/src/imports/jsondb/jsondbnotification.cpp @@ -38,11 +38,10 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ -#include "jsondb-global.h" #include "jsondbnotification.h" #include "jsondbpartition.h" -#include "private/jsondb-strings_p.h" #include "plugin.h" +#include <QJsonDbNotification> #include <qdebug.h> QT_BEGIN_NAMESPACE_JSONDB @@ -118,6 +117,10 @@ JsonDbNotify::JsonDbNotify(QObject *parent) JsonDbNotify::~JsonDbNotify() { + if (partitionObject && active && watcher) + partitionObject->removeNotification(this); + if (watcher) + delete watcher; if (defaultPartitionObject) delete defaultPartitionObject; } @@ -347,11 +350,32 @@ void JsonDbNotify::init() } if (partitionObject && active) { // remove the current notification - partitionObject->removeNotification(this); + if (watcher) { + partitionObject->removeNotification(this); + delete watcher; + } + watcher = new QJsonDbWatcher(); + watcher->setQuery(queryString); + QJsonDbWatcher::Actions actions; + if (actionsList.isEmpty()) { + actions = QJsonDbWatcher::Created | QJsonDbWatcher::Updated |QJsonDbWatcher::Removed; + } else { + if (actionsList.contains(JsonDbNotify::Create)) + actions |= QJsonDbWatcher::Created; + if (actionsList.contains(JsonDbNotify::Update)) + actions |= QJsonDbWatcher::Updated; + if (actionsList.contains(JsonDbNotify::Remove)) + actions |= QJsonDbWatcher::Removed; + } + watcher->setWatchedActions(actions); + watcher->setPartition(partitionObject->name()); + QObject::connect(watcher, SIGNAL(notificationsAvailable(int)), + this, SLOT(onNotificationsAvailable())); + QObject::connect(watcher, SIGNAL(statusChanged(QtJsonDb::QJsonDbWatcher::Status)), + this, SLOT(onStatusChanged(QtJsonDb::QJsonDbWatcher::Status))); + QObject::connect(watcher, SIGNAL(error(QtJsonDb::QJsonDbWatcher::ErrorCode,QString)), + this, SLOT(onNotificationError(QtJsonDb::QJsonDbWatcher::ErrorCode,QString))); partitionObject->updateNotification(this); - objectStatus = JsonDbNotify::Registering; - if (objectStatus != oldStatus) - emit statusChanged(objectStatus); } } @@ -370,42 +394,54 @@ bool JsonDbNotify::parametersReady() return (completed && !queryString.isEmpty() && actionsList.count() && partitionObject); } -void JsonDbNotify::dbNotified(const QString ¬ify_uuid, const QtAddOn::JsonDb::JsonDbNotification &_notification) +void JsonDbNotify::onNotificationsAvailable() { - Q_UNUSED(notify_uuid); if (objectStatus != JsonDbNotify::Ready) { clearError(); objectStatus = JsonDbNotify::Ready; emit statusChanged(objectStatus); } - if (active) { - QJSValue obj = g_declEngine->toScriptValue(QVariant(_notification.object())); - emit notification(obj, (Actions)_notification.action(), _notification.stateNumber()); + if (active && watcher) { + QList<QJsonDbNotification> list = watcher->takeNotifications(); + for (int i = 0; i < list.count(); i++) { + const QJsonDbNotification & _notification = list[i]; + QJSValue obj = g_declEngine->toScriptValue(_notification.object().toVariantMap()); + emit notification(obj, (Actions)_notification.action(), _notification.stateNumber()); + } } } -void JsonDbNotify::dbNotifyReadyResponse(int id, const QVariant &result) +void JsonDbNotify::onStatusChanged(QtJsonDb::QJsonDbWatcher::Status newStatus) { - Q_UNUSED(id); - Q_UNUSED(result); + JsonDbNotify::Status oldStatus = objectStatus; + switch (newStatus) { + case QJsonDbWatcher::Inactive: + objectStatus = JsonDbNotify::Null; + break; + case QJsonDbWatcher::Activating: + objectStatus = JsonDbNotify::Registering; + break; + case QJsonDbWatcher::Active: + objectStatus = JsonDbNotify::Ready; + break; + } clearError(); - if (objectStatus != JsonDbNotify::Ready) { - objectStatus = JsonDbNotify::Ready; + if (oldStatus != objectStatus) { emit statusChanged(objectStatus); } } -void JsonDbNotify::dbNotifyErrorResponse(int id, int code, const QString &message) +void JsonDbNotify::onNotificationError(QtJsonDb::QJsonDbWatcher::ErrorCode code, const QString &message) { - Q_UNUSED(id); int oldErrorCode = errorCode; errorCode = code; errorString = message; - if (objectStatus != JsonDbNotify::Error) { + bool changed = (objectStatus != JsonDbNotify::Error); + if (changed) { objectStatus = JsonDbNotify::Error; emit statusChanged(objectStatus); } - if (oldErrorCode != errorCode) { + if (oldErrorCode != errorCode || changed) { emit errorChanged(error()); } } diff --git a/src/imports/jsondb/jsondbnotification.h b/src/imports/jsondb/jsondbnotification.h index 3957cd5..87af992 100644 --- a/src/imports/jsondb/jsondbnotification.h +++ b/src/imports/jsondb/jsondbnotification.h @@ -48,7 +48,7 @@ #include <QJSValue> #include <QQmlParserStatus> #include <QQmlListProperty> -#include "jsondb-client.h" +#include <QJsonDbWatcher> QT_BEGIN_NAMESPACE_JSONDB @@ -102,10 +102,9 @@ Q_SIGNALS: private Q_SLOTS: void partitionNameChanged(const QString &partitionName); - void dbNotified(const QString ¬ify_uuid, const QtAddOn::JsonDb::JsonDbNotification &_notification); - void dbNotifyReadyResponse(int id, const QVariant &result); - void dbNotifyErrorResponse(int id, int code, const QString &message); - + void onNotificationsAvailable(); + void onStatusChanged(QtJsonDb::QJsonDbWatcher::Status newStatus); + void onNotificationError(QtJsonDb::QJsonDbWatcher::ErrorCode code, const QString &message); private: bool completed; QString queryString; @@ -118,6 +117,7 @@ private: QString errorString; Status objectStatus; bool active; + QPointer<QJsonDbWatcher> watcher; void init(); void clearError(); diff --git a/src/imports/jsondb/jsondbpartition.cpp b/src/imports/jsondb/jsondbpartition.cpp index 2302317..040e047 100644 --- a/src/imports/jsondb/jsondbpartition.cpp +++ b/src/imports/jsondb/jsondbpartition.cpp @@ -38,14 +38,13 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ - -#include "private/jsondb-strings_p.h" #include "jsondbpartition.h" +#include "jsondatabase.h" #include "jsondbnotification.h" #include "plugin.h" -#include "jsondb-client.h" #include "jsondbqueryobject.h" -#include "jsondbchangessinceobject.h" +#include <QJsonDbCreateRequest> +#include <private/qjsondbstrings_p.h> #include <qdebug.h> QT_BEGIN_NAMESPACE_JSONDB @@ -67,12 +66,9 @@ JsonDbPartition::JsonDbPartition(const QString &partitionName, QObject *parent) :QObject(parent) ,_name(partitionName) { - connect(&jsonDb, SIGNAL(response(int,const QVariant&)), - this, SLOT(dbResponse(int,const QVariant&))); - connect(&jsonDb, SIGNAL(error(int,int,QString)), - this, SLOT(dbErrorResponse(int,int,QString))); } + JsonDbPartition::~JsonDbPartition() { } @@ -91,10 +87,10 @@ void JsonDbPartition::setName(const QString &partitionName) { if (partitionName != _name) { _name = partitionName; - foreach (QPointer<JsonDbNotify> notify, notifications) { - removeNotification(notify); + foreach (QPointer<QJsonDbWatcher> watcher, watchers) { + JsonDatabase::sharedConnection().removeWatcher(watcher); } - notifications.clear(); + watchers.clear(); // tell notifications to resubscribe emit nameChanged(partitionName); } @@ -112,6 +108,27 @@ static QVariant qjsvalue_to_qvariant(const QJSValue &value) } } } + +QList<QJsonObject> qvariantlist_to_qjsonobject_list(const QVariantList &list) +{ + QList<QJsonObject> objects; + int count = list.count(); + for (int i = 0; i < count; i++) { + objects.append(QJsonObject::fromVariantMap(list[i].toMap())); + } + return objects; +} + +QVariantList qjsonobject_list_to_qvariantlist(const QList<QJsonObject> &list) +{ + QVariantList objects; + int count = list.count(); + for (int i = 0; i < count; i++) { + objects.append(list[i].toVariantMap()); + } + return objects; +} + /*! \qmlmethod int QtJsonDb::Partition::create(object newObject, object options, function callback) @@ -168,9 +185,23 @@ int JsonDbPartition::create(const QJSValue &object, const QJSValue &options, co actualOptions = QJSValue(QJSValue::UndefinedValue); } //#TODO ADD options - int id = jsonDb.create(qjsvalue_to_qvariant(object), _name); - createCallbacks.insert(id, actualCallback); - return id; + QVariant obj = qjsvalue_to_qvariant(object); + QJsonDbWriteRequest *request(0); + if (obj.type() == QVariant::List) { + request = new QJsonDbCreateRequest(qvariantlist_to_qjsonobject_list(obj.toList())); + } else { + request = new QJsonDbCreateRequest(QJsonObject::fromVariantMap(obj.toMap())); + } + request->setPartition(_name); + connect(request, SIGNAL(finished()), this, SLOT(requestFinished())); + connect(request, SIGNAL(finished()), request, SLOT(deleteLater())); + connect(request, SIGNAL(error(QtJsonDb::QJsonDbRequest::ErrorCode,QString)), + this, SLOT(requestError(QtJsonDb::QJsonDbRequest::ErrorCode,QString))); + connect(request, SIGNAL(error(QtJsonDb::QJsonDbRequest::ErrorCode,QString)), + request, SLOT(deleteLater())); + JsonDatabase::sharedConnection().send(request); + writeCallbacks.insert(request, actualCallback); + return request->property("requestId").toInt(); } /*! @@ -241,9 +272,23 @@ int JsonDbPartition::update(const QJSValue &object, const QJSValue &options, co actualOptions = QJSValue(QJSValue::UndefinedValue); } //#TODO ADD options - int id = jsonDb.update(qjsvalue_to_qvariant(object), _name); - updateCallbacks.insert(id, actualCallback); - return id; + QVariant obj = qjsvalue_to_qvariant(object); + QJsonDbWriteRequest *request(0); + if (obj.type() == QVariant::List) { + request = new QJsonDbUpdateRequest(qvariantlist_to_qjsonobject_list(obj.toList())); + } else { + request = new QJsonDbUpdateRequest(QJsonObject::fromVariantMap(obj.toMap())); + } + request->setPartition(_name); + connect(request, SIGNAL(finished()), this, SLOT(requestFinished())); + connect(request, SIGNAL(finished()), request, SLOT(deleteLater())); + connect(request, SIGNAL(error(QtJsonDb::QJsonDbRequest::ErrorCode,QString)), + this, SLOT(requestError(QtJsonDb::QJsonDbRequest::ErrorCode,QString))); + connect(request, SIGNAL(error(QtJsonDb::QJsonDbRequest::ErrorCode,QString)), + request, SLOT(deleteLater())); + JsonDatabase::sharedConnection().send(request); + writeCallbacks.insert(request, actualCallback); + return request->property("requestId").toInt(); } /*! @@ -306,9 +351,23 @@ int JsonDbPartition::remove(const QJSValue &object, const QJSValue &options, co actualOptions = QJSValue(QJSValue::UndefinedValue); } //#TODO ADD options - int id = jsonDb.remove(qjsvalue_to_qvariant(object), _name); - removeCallbacks.insert(id, actualCallback); - return id; + QVariant obj = qjsvalue_to_qvariant(object); + QJsonDbWriteRequest *request(0); + if (obj.type() == QVariant::List) { + request = new QJsonDbRemoveRequest(qvariantlist_to_qjsonobject_list(obj.toList())); + } else { + request = new QJsonDbRemoveRequest(QJsonObject::fromVariantMap(obj.toMap())); + } + request->setPartition(_name); + connect(request, SIGNAL(finished()), this, SLOT(requestFinished())); + connect(request, SIGNAL(finished()), request, SLOT(deleteLater())); + connect(request, SIGNAL(error(QtJsonDb::QJsonDbRequest::ErrorCode,QString)), + this, SLOT(requestError(QtJsonDb::QJsonDbRequest::ErrorCode,QString))); + connect(request, SIGNAL(error(QtJsonDb::QJsonDbRequest::ErrorCode,QString)), + request, SLOT(deleteLater())); + JsonDatabase::sharedConnection().send(request); + writeCallbacks.insert(request, actualCallback); + return request->property("requestId").toInt(); } /*! @@ -457,45 +516,6 @@ JsonDbQueryObject* JsonDbPartition::createQuery(const QString &query, int limit, return queryObject; } -/*! - \qmlmethod object QtJsonDb::Partition::createChangesSince(stateNumber, types) - - Create the ChangesSince object. It will set the \a stateNumber, filter \a types parameters - of the object. Users have to call start() to start the changesSince query in this partition. - The script engine decides the life time of the returned object. The returned object can be - saved in a 'property var' until it is required. - - \code - import QtJsonDb 1.0 as JsonDb - property var changesObject; - function onFinished() - { - var results = queryObject.takeResults(); - console.log("Results: Count + results.length ); - } - - Component.onCompleted: { - changesObject = nokiaPartition.createChangesSince(10, ["Contact"]); - changesObject.finished.connect(onFinished); - changesObject.start(); - - } - \endcode - \sa QtJsonDb::ChangesSince - -*/ - -JsonDbChangesSinceObject* JsonDbPartition::createChangesSince(int stateNumber, const QStringList &types) -{ - JsonDbChangesSinceObject* changesSinceObject = new JsonDbChangesSinceObject(); - changesSinceObject->setTypes(types); - changesSinceObject->setStateNumber(stateNumber); - changesSinceObject->setPartition(this); - changesSinceObject->componentComplete(); - QQmlEngine::setObjectOwnership(changesSinceObject, QQmlEngine::JavaScriptOwnership); - return changesSinceObject; -} - QQmlListProperty<QObject> JsonDbPartition::childElements() { return QQmlListProperty<QObject>(this, childQMLElements); @@ -503,65 +523,47 @@ QQmlListProperty<QObject> JsonDbPartition::childElements() void JsonDbPartition::updateNotification(JsonDbNotify *notify) { - JsonDbClient::NotifyTypes notifyActions = JsonDbClient::NotifyCreate - | JsonDbClient::NotifyUpdate| JsonDbClient::NotifyRemove; - notify->uuid= jsonDb.registerNotification(notifyActions, notify->query(), _name - , notify, SLOT(dbNotified(QString,QtAddOn::JsonDb::JsonDbNotification)) - , notify, SLOT(dbNotifyReadyResponse(int,QVariant)) - , SLOT(dbNotifyErrorResponse(int,int,QString))); - notifications.insert(notify->uuid, notify); + JsonDatabase::sharedConnection().addWatcher(notify->watcher); + watchers.append(notify->watcher); } - void JsonDbPartition::removeNotification(JsonDbNotify *notify) { - if (notifications.contains(notify->uuid)) { - jsonDb.unregisterNotification(notify->uuid); - notifications.remove(notify->uuid); + if (watchers.contains(notify->watcher)) { + JsonDatabase::sharedConnection().removeWatcher(notify->watcher); + watchers.removeAll(notify->watcher); } } -void JsonDbPartition::call(QMap<int, QJSValue> &callbacks, int id, const QVariant &result) +void JsonDbPartition::call(QMap<QJsonDbWriteRequest*, QJSValue> &callbacks, QJsonDbWriteRequest *request) { - // Make sure that id exists in the map. - QJSValue callback = callbacks[id]; + QJSValue callback = callbacks[request]; QJSEngine *engine = callback.engine(); if (!engine) { - callbacks.remove(id); + callbacks.remove(request); return; } + QList<QJsonObject> objects = request->takeResults(); QJSValueList args; - QVariantMap object = result.toMap(); // object : id , statenumber , items QJSValue response= engine->newObject(); - response.setProperty(JsonDbString::kStateNumberStr, object.value(JsonDbString::kStateNumberStr).toInt()); - response.setProperty(JsonDbString::kIdStr, id); + response.setProperty(JsonDbStrings::Protocol::stateNumber(), request->stateNumber()); + response.setProperty(JsonDbStrings::Protocol::requestId(), request->property("requestId").toInt()); + QJSValue items = engine->toScriptValue(qjsonobject_list_to_qvariantlist(objects)); + response.setProperty(QLatin1String("items"), items); - // response object : object { _version & _uuid } (can be a list) - if (object.contains(QLatin1String("data"))) { - QJSValue items = engine->toScriptValue(object.value(QLatin1String("data"))); - response.setProperty(QLatin1String("items"), items); - } else { - // Create an array with a single element - QJSValue responseObject = engine->newObject(); - responseObject.setProperty(JsonDbString::kUuidStr, object.value(JsonDbString::kUuidStr).toString()); - responseObject.setProperty(JsonDbString::kVersionStr, object.value(JsonDbString::kVersionStr).toString()); - QJSValue items = engine->newArray(1); - items.setProperty(0, responseObject); - response.setProperty(QLatin1String("items"), items); - } args << QJSValue(QJSValue::UndefinedValue) << response; callback.call(args); - callbacks.remove(id); + callbacks.remove(request); } -void JsonDbPartition::callErrorCallback(QMap<int, QJSValue> &callbacks, int id, int code, const QString &message) +void JsonDbPartition::callErrorCallback(QMap<QJsonDbWriteRequest*, QJSValue> &callbacks, QJsonDbWriteRequest *request, + QtJsonDb::QJsonDbRequest::ErrorCode code, const QString &message) { - // Make sure that id exists in the map. - QJSValue callback = callbacks[id]; + QJSValue callback = callbacks[request]; QJSEngine *engine = callback.engine(); if (!engine) { - callbacks.remove(id); + callbacks.remove(request); return; } QJSValueList args; @@ -571,36 +573,13 @@ void JsonDbPartition::callErrorCallback(QMap<int, QJSValue> &callbacks, int id, // object : id QJSValue response = engine->newObject(); - response.setProperty(JsonDbString::kStateNumberStr, -1); - response.setProperty(JsonDbString::kIdStr, id); + response.setProperty(JsonDbStrings::Protocol::stateNumber(), -1); + response.setProperty(JsonDbStrings::Protocol::requestId(), request->property("requestId").toInt()); response.setProperty(QLatin1String("items"), engine->newArray()); args << engine->toScriptValue(QVariant(error))<< response; callback.call(args); - callbacks.remove(id); -} - - -void JsonDbPartition::dbResponse(int id, const QVariant &result) -{ - if (createCallbacks.contains(id)) { - call(createCallbacks, id, result); - } else if (updateCallbacks.contains(id)) { - call(updateCallbacks, id, result); - } else if (removeCallbacks.contains(id)) { - call(removeCallbacks, id, result); - } -} - -void JsonDbPartition::dbErrorResponse(int id, int code, const QString &message) -{ - if (createCallbacks.contains(id)) { - callErrorCallback(createCallbacks, id, code, message); - } else if (removeCallbacks.contains(id)) { - callErrorCallback(removeCallbacks, id, code, message); - } else if (updateCallbacks.contains(id)) { - callErrorCallback(updateCallbacks, id, code, message); - } + callbacks.remove(request); } void JsonDbPartition::queryFinished() @@ -614,8 +593,8 @@ void JsonDbPartition::queryFinished() QJSValueList args; // object : id , statenumber , items QJSValue response= engine->newObject(); - response.setProperty(JsonDbString::kStateNumberStr, object->stateNumber()); - response.setProperty(JsonDbString::kIdStr, id); + response.setProperty(JsonDbStrings::Protocol::stateNumber(), object->stateNumber()); + response.setProperty(JsonDbStrings::Protocol::requestId(), id); response.setProperty(QLatin1String("items"), engine->toScriptValue(object->takeResults())); args << QJSValue(QJSValue::UndefinedValue) << response; callback.call(args); @@ -637,8 +616,8 @@ void JsonDbPartition::queryStatusChanged() QJSValueList args; QJSValue response = engine->newObject(); - response.setProperty(JsonDbString::kStateNumberStr, -1); - response.setProperty(JsonDbString::kIdStr, id); + response.setProperty(JsonDbStrings::Protocol::stateNumber(), -1); + response.setProperty(JsonDbStrings::Protocol::requestId(), id); response.setProperty(QLatin1String("items"), engine->newArray()); args << engine->toScriptValue(object->error())<< response; @@ -650,6 +629,22 @@ void JsonDbPartition::queryStatusChanged() } } +void JsonDbPartition::requestFinished() +{ + QJsonDbWriteRequest *request = qobject_cast<QJsonDbWriteRequest *>(sender()); + if (writeCallbacks.contains(request)) { + call(writeCallbacks, request); + } +} + +void JsonDbPartition::requestError(QtJsonDb::QJsonDbRequest::ErrorCode code, const QString &message) +{ + QJsonDbWriteRequest *request = qobject_cast<QJsonDbWriteRequest *>(sender()); + if (writeCallbacks.contains(request)) { + callErrorCallback(writeCallbacks, request, code, message); + } + +} #include "moc_jsondbpartition.cpp" QT_END_NAMESPACE_JSONDB diff --git a/src/imports/jsondb/jsondbpartition.h b/src/imports/jsondb/jsondbpartition.h index 1c831c2..008cb0f 100644 --- a/src/imports/jsondb/jsondbpartition.h +++ b/src/imports/jsondb/jsondbpartition.h @@ -49,8 +49,8 @@ #include <QJSValue> #include <QJSEngine> #include <QQmlListProperty> - -#include "jsondb-client.h" +#include <QJsonDbConnection> +#include <QJsonDbWriteRequest> QT_BEGIN_NAMESPACE_JSONDB @@ -58,7 +58,6 @@ class JsonDatabase; class JsonDbNotify; class JsonDbPartitionPrivate; class JsonDbQueryObject; -class JsonDbChangesSinceObject; class JsonDbPartition: public QObject { @@ -89,8 +88,6 @@ public: Q_INVOKABLE JsonDbQueryObject* createQuery(const QString &query, int limit, QVariantMap bindings); - Q_INVOKABLE JsonDbChangesSinceObject* createChangesSince(int stateNumber, const QStringList &types); - QString name() const; void setName(const QString &partitionName); @@ -105,32 +102,29 @@ private: QString _name; QString _file; QString _uuid; - JsonDbClient jsonDb; - QMap<int, QJSValue> createCallbacks; - QMap<int, QJSValue> updateCallbacks; - QMap<int, QJSValue> removeCallbacks; - QMap<QString, QPointer<JsonDbNotify> > notifications; + QList<QPointer<QJsonDbWatcher> > watchers; QList<QObject*> childQMLElements; QMap<JsonDbQueryObject*, QJSValue> findCallbacks; QMap<JsonDbQueryObject*, int> findIds; + QMap<QJsonDbWriteRequest*, QJSValue> writeCallbacks; void updateNotification(JsonDbNotify *notify); void removeNotification(JsonDbNotify *notify); - void call(QMap<int, QJSValue> &callbacks, int id, const QVariant &result); - void callErrorCallback(QMap<int, QJSValue> &callbacks, int id, int code, const QString &message); + void call(QMap<QJsonDbWriteRequest*, QJSValue> &callbacks, QJsonDbWriteRequest *request); + void callErrorCallback(QMap<QJsonDbWriteRequest*, QJSValue> &callbacks, QJsonDbWriteRequest *request, + QtJsonDb::QJsonDbRequest::ErrorCode code, const QString &message); private Q_SLOTS: - void dbResponse(int id, const QVariant &result); - void dbErrorResponse(int id, int code, const QString &message); void queryFinished(); void queryStatusChanged(); + void requestFinished(); + void requestError(QtJsonDb::QJsonDbRequest::ErrorCode code, const QString &message); friend class JsonDatabase; friend class JsonDbNotify; friend class JsonDbQueryObject; - friend class JsonDbChangesSinceObject; }; QT_END_NAMESPACE_JSONDB diff --git a/src/imports/jsondb/jsondbqueryobject.cpp b/src/imports/jsondb/jsondbqueryobject.cpp index b42daaa..ac00e69 100644 --- a/src/imports/jsondb/jsondbqueryobject.cpp +++ b/src/imports/jsondb/jsondbqueryobject.cpp @@ -38,10 +38,11 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ -#include "jsondb-global.h" #include "jsondbqueryobject.h" #include "jsondbpartition.h" -#include "private/jsondb-strings_p.h" +#include "jsondatabase.h" +#include <private/qjsondbstrings_p.h> +#include <jsondbmodelutils.h> #include <qdebug.h> QT_BEGIN_NAMESPACE_JSONDB @@ -84,7 +85,6 @@ JsonDbQueryObject::JsonDbQueryObject(QObject *parent) , queryLimit(-1) , partitionObject(0) , defaultPartitionObject(0) - , jsondbQuery(0) , errorCode(0) , objectStatus(JsonDbQueryObject::Null) { @@ -94,8 +94,8 @@ JsonDbQueryObject::~JsonDbQueryObject() { if (defaultPartitionObject) delete defaultPartitionObject; - if (jsondbQuery) - delete jsondbQuery; + if (readRequest) + delete readRequest; } @@ -145,8 +145,8 @@ void JsonDbQueryObject::setPartition(JsonDbPartition *newPartition) */ quint32 JsonDbQueryObject::stateNumber() const { - if (jsondbQuery) - return jsondbQuery->stateNumber(); + if (readRequest) + return readRequest->stateNumber(); return 0; } @@ -240,8 +240,8 @@ void JsonDbQueryObject::setBindings(const QVariantMap &newBindings) QVariantList JsonDbQueryObject::takeResults() { QVariantList list; - if (jsondbQuery) { - list = jsondbQuery->takeResults(); + if (readRequest) { + list = qjsonobject_list_to_qvariantlist(readRequest->takeResults()); } return list; } @@ -329,32 +329,29 @@ int JsonDbQueryObject::start() return -1; } - if (jsondbQuery) { - delete jsondbQuery; + if (readRequest) { + delete readRequest; } - jsondbQuery = partitionObject->jsonDb.query(); - jsondbQuery->setQuery(queryString); - jsondbQuery->setQueryLimit(queryLimit); - jsondbQuery->setQueryOffset(0); - jsondbQuery->setPartition(partitionObject->name()); + QJsonDbReadRequest *request = new QJsonDbReadRequest; + request->setQuery(queryString); + request->setQueryLimit(queryLimit); + request->setPartition(partitionObject->name()); QVariantMap::ConstIterator i = queryBindings.constBegin(); while (i != queryBindings.constEnd()) { - jsondbQuery->bindValue(i.key(), i.value()); + request->bindValue(i.key(), QJsonValue::fromVariant(i.value())); ++i; } - connect(jsondbQuery, SIGNAL(resultsReady(int)), - this, SIGNAL(resultsReady(int))); - connect(jsondbQuery, SIGNAL(finished()), - this, SLOT(setReadyStatus())); - connect(jsondbQuery, SIGNAL(finished()), - this, SIGNAL(finished())); - connect(jsondbQuery, SIGNAL(error(QtAddOn::JsonDb::JsonDbError::ErrorCode,QString)), - this, SLOT(setError(QtAddOn::JsonDb::JsonDbError::ErrorCode,QString))); - - jsondbQuery->start(); + connect(request, SIGNAL(resultsAvailable(int)), this, SIGNAL(resultsReady(int))); + connect(request, SIGNAL(finished()), this, SLOT(setReadyStatus())); + connect(request, SIGNAL(finished()), this, SIGNAL(finished())); + connect(request, SIGNAL(error(QtJsonDb::QJsonDbRequest::ErrorCode,QString)), + this, SLOT(setError(QtJsonDb::QJsonDbRequest::ErrorCode,QString))); + objectStatus = JsonDbQueryObject::Loading; emit statusChanged(objectStatus); - return jsondbQuery->requestId(); + JsonDatabase::sharedConnection().send(request); + readRequest = request; + return request->property("requestId").toInt(); } @@ -405,16 +402,17 @@ void JsonDbQueryObject::setReadyStatus() emit statusChanged(objectStatus); } -void JsonDbQueryObject::setError(QtAddOn::JsonDb::JsonDbError::ErrorCode code, const QString& message) +void JsonDbQueryObject::setError(QtJsonDb::QJsonDbRequest::ErrorCode code, const QString & message) { int oldErrorCode = errorCode; errorCode = code; errorString = message; - if (objectStatus != JsonDbQueryObject::Error) { + bool changed = (objectStatus != JsonDbQueryObject::Error); + if (changed) { objectStatus = JsonDbQueryObject::Error; emit statusChanged(objectStatus); } - if (oldErrorCode != errorCode) { + if (oldErrorCode != errorCode || changed) { emit errorChanged(error()); } } diff --git a/src/imports/jsondb/jsondbqueryobject.h b/src/imports/jsondb/jsondbqueryobject.h index d629d26..d7845c5 100644 --- a/src/imports/jsondb/jsondbqueryobject.h +++ b/src/imports/jsondb/jsondbqueryobject.h @@ -48,7 +48,7 @@ #include <QJSValue> #include <QQmlParserStatus> #include <QQmlListProperty> -#include "jsondb-client.h" +#include <QJsonDbReadRequest> QT_BEGIN_NAMESPACE_JSONDB @@ -106,7 +106,7 @@ Q_SIGNALS: void errorChanged(const QVariantMap &newError); private Q_SLOTS: - void setError(QtAddOn::JsonDb::JsonDbError::ErrorCode code, const QString& message); + void setError(QtJsonDb::QJsonDbRequest::ErrorCode code, const QString & message); void setReadyStatus(); private: @@ -116,11 +116,11 @@ private: QVariantList results; QPointer<JsonDbPartition> partitionObject; QPointer<JsonDbPartition> defaultPartitionObject; - QPointer<JsonDbQuery> jsondbQuery; int errorCode; QString errorString; Status objectStatus; QVariantMap queryBindings; + QPointer<QJsonDbReadRequest> readRequest; void clearError(); inline bool parametersReady(); diff --git a/src/imports/jsondb/jsondbsortinglistmodel.cpp b/src/imports/jsondb/jsondbsortinglistmodel.cpp index c70b19e..8bb84c3 100644 --- a/src/imports/jsondb/jsondbsortinglistmodel.cpp +++ b/src/imports/jsondb/jsondbsortinglistmodel.cpp @@ -41,12 +41,9 @@ #include "jsondbsortinglistmodel.h" #include "jsondbsortinglistmodel_p.h" -#include "private/jsondb-strings_p.h" #include "plugin.h" - -#include <QJSEngine> -#include <QJSValueIterator> - +#include "jsondatabase.h" +#include <qdebug.h> /*! \internal \class JsonDbSortingListModel @@ -62,16 +59,12 @@ JsonDbSortingListModelPrivate::JsonDbSortingListModelPrivate(JsonDbSortingListMo , limit(-1) , chunkSize(100) , state(JsonDbSortingListModel::None) + , errorCode(0) { } void JsonDbSortingListModelPrivate::init() { - Q_Q(JsonDbSortingListModel); - q->connect(&dbClient, SIGNAL(response(int,const QVariant&)), - q, SLOT(_q_jsonDbResponse(int,const QVariant&))); - q->connect(&dbClient, SIGNAL(error(int,int,const QString&)), - q, SLOT(_q_jsonDbErrorResponse(int,int,const QString&))); } JsonDbSortingListModelPrivate::~JsonDbSortingListModelPrivate() @@ -218,13 +211,9 @@ void JsonDbSortingListModelPrivate::updateItem(const QVariantMap &item, int part } } -void JsonDbSortingListModelPrivate::fillData(const QVariant &v, int partitionIndex) +void JsonDbSortingListModelPrivate::fillData(const QVariantList &items, int partitionIndex) { Q_Q(JsonDbSortingListModel); - QVariantMap m = v.toMap(); - QVariantList items; - if (m.contains(QLatin1String("data"))) - items = m.value(QLatin1String("data")).toList(); RequestInfo &r = partitionObjectDetails[partitionIndex]; r.lastSize = items.size(); if (resetModel) { @@ -280,7 +269,7 @@ void JsonDbSortingListModelPrivate::fillData(const QVariant &v, int partitionInd emit q->stateChanged(state); for (int i = 0; i<pendingNotifications.size(); i++) { const NotifyItem &pending = pendingNotifications[i]; - sendNotifications(pending.notifyUuid, pendingNotifications[i].item, pendingNotifications[i].action); + sendNotifications(pending.partitionIndex, pending.item, pending.action); } pendingNotifications.clear(); // overflow status is used when handling notifications. @@ -290,7 +279,7 @@ void JsonDbSortingListModelPrivate::fillData(const QVariant &v, int partitionInd overflow = false; } else if (r.lastSize >= chunkSize){ // more items, fetch next chunk - fetchNextChunk(partitionIndex); + fetchPartition(partitionIndex, false); } } @@ -333,7 +322,7 @@ void JsonDbSortingListModelPrivate::reset() emit q->stateChanged(state); } -void JsonDbSortingListModelPrivate::fetchPartition(int index) +void JsonDbSortingListModelPrivate::fetchPartition(int index, bool reset) { Q_Q(JsonDbSortingListModel); if (index >= partitionObjects.count()) @@ -345,11 +334,19 @@ void JsonDbSortingListModelPrivate::fetchPartition(int index) } RequestInfo &r = partitionObjectDetails[index]; QPointer<JsonDbPartition> p = partitionObjects[index]; - if (p) { + Q_ASSERT(p); + if (reset) { r.lastSize = -1; r.lastOffset = 0; - r.requestId = dbClient.query(query, r.lastOffset, chunkSize, p->name()); + } else { + r.lastOffset += chunkSize; } + QJsonDbReadRequest *request = valueRequests[index]->newRequest(index); + request->setQuery(query); + request->setProperty("queryOffset", r.lastOffset); + request->setQueryLimit(chunkSize); + request->setPartition(p->name()); + JsonDatabase::sharedConnection().send(request); } void JsonDbSortingListModelPrivate::fetchModel(bool reset) @@ -365,21 +362,14 @@ void JsonDbSortingListModelPrivate::fetchModel(bool reset) } } -void JsonDbSortingListModelPrivate::fetchNextChunk(int partitionIndex) -{ - RequestInfo &r = partitionObjectDetails[partitionIndex]; - r.lastOffset += chunkSize; - r.requestId = dbClient.query(query, r.lastOffset, chunkSize, partitionObjects[partitionIndex]->name()); -} - void JsonDbSortingListModelPrivate::clearNotification(int index) { if (index >= partitionObjects.count()) return; RequestInfo &r = partitionObjectDetails[index]; - if (!r.notifyUuid.isEmpty()) { - dbClient.unregisterNotification(r.notifyUuid); + if (r.watcher) { + JsonDatabase::sharedConnection().removeWatcher(r.watcher); } r.clear(); } @@ -396,14 +386,16 @@ void JsonDbSortingListModelPrivate::createOrUpdateNotification(int index) if (index >= partitionObjects.count()) return; clearNotification(index); - JsonDbClient::NotifyTypes notifyActions = JsonDbClient::NotifyCreate - | JsonDbClient::NotifyUpdate| JsonDbClient::NotifyRemove; - partitionObjectDetails[index].notifyUuid= dbClient.registerNotification( - notifyActions , query, partitionObjects[index]->name(), - q, SLOT(_q_dbNotified(QString,QtAddOn::JsonDb::JsonDbNotification)), - q, SLOT(_q_dbNotifyReadyResponse(int,QVariant)), - SLOT(_q_dbNotifyErrorResponse(int,int,QString))); - + QJsonDbWatcher *watcher = new QJsonDbWatcher(); + watcher->setQuery(query); + watcher->setWatchedActions(QJsonDbWatcher::Created | QJsonDbWatcher::Updated |QJsonDbWatcher::Removed); + watcher->setPartition(partitionObjects[index]->name()); + QObject::connect(watcher, SIGNAL(notificationsAvailable(int)), + q, SLOT(_q_notificationsAvailable())); + QObject::connect(watcher, SIGNAL(error(QtJsonDb::QJsonDbWatcher::ErrorCode,QString)), + q, SLOT(_q_notificationError(QtJsonDb::QJsonDbWatcher::ErrorCode,QString))); + JsonDatabase::sharedConnection().addWatcher(watcher); + partitionObjectDetails[index].watcher = watcher; } void JsonDbSortingListModelPrivate::createOrUpdateNotifications() @@ -433,19 +425,10 @@ void JsonDbSortingListModelPrivate::parseSortOrder() } } -int JsonDbSortingListModelPrivate::indexOfrequestId(int requestId) -{ - for (int i = 0; i<partitionObjectDetails.count(); i++) { - if (requestId == partitionObjectDetails[i].requestId) - return i; - } - return -1; -} - -int JsonDbSortingListModelPrivate::indexOfNotifyUUID(const QString& notifyUuid) +int JsonDbSortingListModelPrivate::indexOfWatcher(QJsonDbWatcher *watcher) { - for (int i = 0; i<partitionObjectDetails.count(); i++) { - if (notifyUuid == partitionObjectDetails[i].notifyUuid) + for (int i = 0; i < partitionObjectDetails.count(); i++) { + if (watcher == partitionObjectDetails[i].watcher) return i; } return -1; @@ -489,38 +472,31 @@ int JsonDbSortingListModelPrivate::indexOf(const QString &uuid) const return iterator_position(begin, end, i); } -void JsonDbSortingListModelPrivate::sendNotifications(const QString& currentNotifyUuid, const QVariant &v, JsonDbClient::NotifyType action) +void JsonDbSortingListModelPrivate::sendNotifications(int partitionIndex, const QVariantMap &v, QJsonDbWatcher::Action action) { - int idx = indexOfNotifyUUID(currentNotifyUuid); - if (idx == -1) - return; - - const QVariantMap &item = v.toMap(); - if (action == JsonDbClient::NotifyCreate) { - addItem(item, idx); - } else if (action == JsonDbClient::NotifyRemove) { - deleteItem(item, idx); - } else if (action == JsonDbClient::NotifyUpdate) { - updateItem(item, idx); + if (action == QJsonDbWatcher::Created) { + addItem(v, partitionIndex); + } else if (action == QJsonDbWatcher::Removed) { + deleteItem(v, partitionIndex); + } else if (action == QJsonDbWatcher::Updated) { + updateItem(v, partitionIndex); } } -void JsonDbSortingListModelPrivate::_q_jsonDbResponse(int id, const QVariant &v) +void JsonDbSortingListModelPrivate::_q_valueResponse(int index, const QList<QJsonObject> &v) { - int idx = indexOfrequestId(id); - if (idx != -1) { - partitionObjectDetails[idx].requestId = -1; - fillData(v, idx); - } + fillData(qjsonobject_list_to_qvariantlist(v), index); } -void JsonDbSortingListModelPrivate::_q_jsonDbErrorResponse(int id, int code, const QString &message) +void JsonDbSortingListModelPrivate::_q_readError(QtJsonDb::QJsonDbRequest::ErrorCode code, const QString & message) { - int idx = -1; - if ((idx = indexOfrequestId(id)) != -1) { - partitionObjectDetails[idx].requestId = -1; - qWarning() << QString("JsonDb error: %1 %2").arg(code).arg(message); - } + Q_Q(JsonDbSortingListModel); + qWarning() << QString("JsonDb error: %1 %2").arg(code).arg(message); + int oldErrorCode = errorCode; + errorCode = code; + errorString = message; + if (oldErrorCode != errorCode) + emit q->errorChanged(q->error()); } void JsonDbSortingListModelPrivate::_q_refreshModel() @@ -529,27 +505,58 @@ void JsonDbSortingListModelPrivate::_q_refreshModel() fetchModel(false); } -void JsonDbSortingListModelPrivate::_q_dbNotified(const QString ¬ify_uuid, const QtAddOn::JsonDb::JsonDbNotification &_notification) +void JsonDbSortingListModelPrivate::_q_notificationsAvailable() { - if (state == JsonDbSortingListModel::Querying) { - NotifyItem pending; - pending.notifyUuid = notify_uuid; - pending.item = _notification.object(); - pending.action = _notification.action(); - pendingNotifications.append(pending); - } else if (state == JsonDbSortingListModel::Ready) { - sendNotifications(notify_uuid, _notification.object(), _notification.action()); + Q_Q(JsonDbSortingListModel); + QJsonDbWatcher *watcher = qobject_cast<QJsonDbWatcher *>(q->sender()); + int partitionIndex = indexOfWatcher(watcher); + if (!watcher || partitionIndex == -1) + return; + QList<QJsonDbNotification> list = watcher->takeNotifications(); + for (int i = 0; i < list.count(); i++) { + const QJsonDbNotification & notification = list[i]; + QVariantMap object = notification.object().toVariantMap(); + if (state == JsonDbSortingListModel::Querying) { + NotifyItem pending; + pending.partitionIndex = partitionIndex; + pending.item = object; + pending.action = notification.action(); + pendingNotifications.append(pending); + } else if (state == JsonDbSortingListModel::Ready) { + sendNotifications(partitionIndex, object, notification.action()); + } } } -void JsonDbSortingListModelPrivate::_q_dbNotifyReadyResponse(int /* id */, const QVariant &/* result */) +void JsonDbSortingListModelPrivate::_q_notificationError(QtJsonDb::QJsonDbWatcher::ErrorCode code, const QString &message) { + Q_Q(JsonDbSortingListModel); + qWarning() << QString("JsonDbSortingListModel Notification error: %1 %2").arg(code).arg(message); + int oldErrorCode = errorCode; + errorCode = code; + errorString = message; + if (oldErrorCode != errorCode) + emit q->errorChanged(q->error()); } -void JsonDbSortingListModelPrivate::_q_dbNotifyErrorResponse(int id, int code, const QString &message) +void JsonDbSortingListModelPrivate::appendPartition(JsonDbPartition *v) { - Q_UNUSED(id); - qWarning() << QString("JsonDbSortingListModel Notification error: %1 %2").arg(code).arg(message); + Q_Q(JsonDbSortingListModel); + partitionObjects.append(QPointer<JsonDbPartition>(v)); + partitionObjectDetails.append(RequestInfo()); + ModelRequest *valueRequest = new ModelRequest(); + QObject::connect(valueRequest, SIGNAL(finished(int,QList<QJsonObject>,QString)), + q, SLOT(_q_valueResponse(int,QList<QJsonObject>))); + QObject::connect(valueRequest, SIGNAL(error(QtJsonDb::QJsonDbRequest::ErrorCode,QString)), + q, SLOT(_q_readError(QtJsonDb::QJsonDbRequest::ErrorCode,QString))); + valueRequests.append(valueRequest); + if (componentComplete && !query.isEmpty()) { + createOrUpdateNotification(partitionObjects.count()-1); + if (state == JsonDbSortingListModel::None) { + resetModel = true; + } + fetchPartition(partitionObjects.count()-1); + } } void JsonDbSortingListModelPrivate::partitions_append(QQmlListProperty<JsonDbPartition> *p, JsonDbPartition *v) @@ -557,15 +564,7 @@ void JsonDbSortingListModelPrivate::partitions_append(QQmlListProperty<JsonDbPar JsonDbSortingListModel *q = qobject_cast<JsonDbSortingListModel *>(p->object); JsonDbSortingListModelPrivate *pThis = (q) ? q->d_func() : 0; if (pThis) { - pThis->partitionObjects.append(QPointer<JsonDbPartition>(v));\ - pThis->partitionObjectDetails.append(RequestInfo()); - if (pThis->componentComplete && !pThis->query.isEmpty()) { - pThis->createOrUpdateNotification(pThis->partitionObjects.count()-1); - if (pThis->state == JsonDbSortingListModel::None) { - pThis->resetModel = true; - } - pThis->fetchPartition(pThis->partitionObjects.count()-1); - } + pThis->appendPartition(v); } } @@ -589,14 +588,23 @@ JsonDbPartition* JsonDbSortingListModelPrivate::partitions_at(QQmlListProperty<J return 0; } +void JsonDbSortingListModelPrivate::clearPartitions() +{ + partitionObjects.clear(); + partitionObjectDetails.clear(); + while (!valueRequests.isEmpty()) { + delete valueRequests[0]; + valueRequests.removeFirst(); + } + reset(); +} + void JsonDbSortingListModelPrivate::partitions_clear(QQmlListProperty<JsonDbPartition> *p) { JsonDbSortingListModel *q = qobject_cast<JsonDbSortingListModel *>(p->object); JsonDbSortingListModelPrivate *pThis = (q) ? q->d_func() : 0; if (pThis) { - pThis->partitionObjects.clear(); - pThis->partitionObjectDetails.clear(); - pThis->reset(); + pThis->clearPartitions(); } } @@ -859,6 +867,7 @@ void JsonDbSortingListModel::setQueryLimit(int newQueryLimit) /*! \qmlproperty bool QtJsonDb::JsonDbSortingListModel::overflow + \readonly This will be true if actual numer of results is more than the queryLimit */ @@ -954,6 +963,7 @@ void JsonDbSortingListModel::setSortOrder(const QString &newSortOrder) /*! \qmlproperty State QtJsonDb::JsonDbSortingListModel::state + \readonly The current state of the model. \list \li State.None - The model is not initialized @@ -1045,5 +1055,25 @@ JsonDbPartition* JsonDbSortingListModel::getPartition(int index) const This handler is called when the number of items in the model has changed. */ +/*! + \qmlproperty object QtJsonDb::JsonDbSortingListModel::error + \readonly + + This property holds the current error information for the object. It contains: + \list + \o error.code - code for the current error. + \o error.message - detailed explanation of the error + \endlist +*/ + +QVariantMap JsonDbSortingListModel::error() const +{ + Q_D(const JsonDbSortingListModel); + QVariantMap errorMap; + errorMap.insert(QLatin1String("code"), d->errorCode); + errorMap.insert(QLatin1String("message"), d->errorString); + return errorMap; +} + #include "moc_jsondbsortinglistmodel.cpp" QT_END_NAMESPACE_JSONDB diff --git a/src/imports/jsondb/jsondbsortinglistmodel.h b/src/imports/jsondb/jsondbsortinglistmodel.h index 99ef405..cdd9f7a 100644 --- a/src/imports/jsondb/jsondbsortinglistmodel.h +++ b/src/imports/jsondb/jsondbsortinglistmodel.h @@ -53,7 +53,6 @@ #include <QJSValue> #include <QScopedPointer> -#include "jsondb-global.h" #include "jsondbpartition.h" QT_BEGIN_NAMESPACE_JSONDB @@ -79,8 +78,8 @@ public: Q_PROPERTY(QVariant roleNames READ scriptableRoleNames WRITE setScriptableRoleNames) Q_PROPERTY(int queryLimit READ queryLimit WRITE setQueryLimit) Q_PROPERTY(bool overflow READ overflow) - Q_PROPERTY(QQmlListProperty<JsonDbPartition> partitions READ partitions) + Q_PROPERTY(QVariantMap error READ error NOTIFY errorChanged) virtual void classBegin(); virtual void componentComplete(); @@ -111,10 +110,12 @@ public: Q_INVOKABLE QJSValue get(int index) const; Q_INVOKABLE QVariant get(int index, const QString &property) const; Q_INVOKABLE JsonDbPartition* getPartition(int index) const; + QVariantMap error() const; signals: void stateChanged(State state) const; void rowCountChanged(int newCount) const; + void errorChanged(QVariantMap newError); private Q_SLOTS: void partitionNameChanged(const QString &partitionName); @@ -123,12 +124,12 @@ private: Q_DISABLE_COPY(JsonDbSortingListModel) Q_DECLARE_PRIVATE(JsonDbSortingListModel) QScopedPointer<JsonDbSortingListModelPrivate> d_ptr; - Q_PRIVATE_SLOT(d_func(), void _q_jsonDbResponse(int, const QVariant&)) - Q_PRIVATE_SLOT(d_func(), void _q_jsonDbErrorResponse(int, int, const QString&)) + Q_PRIVATE_SLOT(d_func(), void _q_refreshModel()) - Q_PRIVATE_SLOT(d_func(), void _q_dbNotified(QString, QtAddOn::JsonDb::JsonDbNotification)) - Q_PRIVATE_SLOT(d_func(), void _q_dbNotifyReadyResponse(int, QVariant)) - Q_PRIVATE_SLOT(d_func(), void _q_dbNotifyErrorResponse(int, int, QString)) + Q_PRIVATE_SLOT(d_func(), void _q_notificationsAvailable()) + Q_PRIVATE_SLOT(d_func(), void _q_notificationError(QtJsonDb::QJsonDbWatcher::ErrorCode, QString)) + Q_PRIVATE_SLOT(d_func(), void _q_valueResponse(int, QList<QJsonObject>)) + Q_PRIVATE_SLOT(d_func(), void _q_readError(QtJsonDb::QJsonDbRequest::ErrorCode, QString)) }; diff --git a/src/imports/jsondb/jsondbsortinglistmodel_p.h b/src/imports/jsondb/jsondbsortinglistmodel_p.h index 0cd45d0..29837a7 100644 --- a/src/imports/jsondb/jsondbsortinglistmodel_p.h +++ b/src/imports/jsondb/jsondbsortinglistmodel_p.h @@ -49,9 +49,9 @@ #include <QStringList> #include <QPointer> #include <QUuid> +#include <QJSEngine> +#include <QJSValueIterator> -#include "jsondb-client.h" -#include "private/jsondb-connection_p.h" #include "jsondbmodelutils.h" QT_BEGIN_NAMESPACE_JSONDB @@ -88,10 +88,12 @@ public: QHash<int, QStringList> properties; QList<NotifyItem> pendingNotifications; + QList< QPointer<ModelRequest> >valueRequests; JsonDbSortingListModel::State state; - JsonDbClient dbClient; QModelIndex parent; + int errorCode; + QString errorString; public: JsonDbSortingListModelPrivate(JsonDbSortingListModel *q); @@ -102,13 +104,12 @@ public: void addItem(const QVariantMap &item, int partitionIndex); void deleteItem(const QVariantMap &item, int partitionIndex); void updateItem(const QVariantMap &item, int partitionIndex); - void fillData(const QVariant &v, int partitionIndex); + void fillData(const QVariantList &items, int partitionIndex); void sortObjects(); void reset(); - void fetchPartition(int index); + void fetchPartition(int index, bool reset = true); void fetchModel(bool reset = true); - void fetchNextChunk(int partitionIndex); void clearNotification(int index); void clearNotifications(); @@ -118,7 +119,10 @@ public: int indexOfrequestId(int requestId); int indexOfNotifyUUID(const QString& notifyUuid); + int indexOfWatcher(QJsonDbWatcher *watcher); + void appendPartition(JsonDbPartition *v); + void clearPartitions(); QVariant getItem(int index); QVariant getItem(int index, int role); JsonDbPartition* getItemPartition(int index); @@ -126,15 +130,14 @@ public: void set(int index, const QJSValue& valuemap, const QJSValue &successCallback, const QJSValue &errorCallback); - void sendNotifications(const QString&, const QVariant &, JsonDbClient::NotifyType); + void sendNotifications(int partitionIndex, const QVariantMap &v, QJsonDbWatcher::Action action); // private slots - void _q_jsonDbResponse(int , const QVariant &); - void _q_jsonDbErrorResponse(int , int, const QString&); void _q_refreshModel(); - void _q_dbNotified(const QString ¬ify_uuid, const QtAddOn::JsonDb::JsonDbNotification &_notification); - void _q_dbNotifyReadyResponse(int id, const QVariant &result); - void _q_dbNotifyErrorResponse(int id, int code, const QString &message); + void _q_notificationsAvailable(); + void _q_notificationError(QtJsonDb::QJsonDbWatcher::ErrorCode code, const QString &message); + void _q_readError(QtJsonDb::QJsonDbRequest::ErrorCode code, const QString & message); + void _q_valueResponse(int , const QList<QJsonObject>&); static void partitions_append(QQmlListProperty<JsonDbPartition> *p, JsonDbPartition *v); static int partitions_count(QQmlListProperty<JsonDbPartition> *p); diff --git a/src/imports/jsondb/plugin.cpp b/src/imports/jsondb/plugin.cpp index 3264b26..5988d62 100644 --- a/src/imports/jsondb/plugin.cpp +++ b/src/imports/jsondb/plugin.cpp @@ -41,18 +41,16 @@ #include "plugin.h" -#include "jsondblistmodel.h" -#include "jsondbsortinglistmodel.h" #include "jsondatabase.h" #include "jsondbpartition.h" #include "jsondbnotification.h" #include "jsondbqueryobject.h" -#include "jsondbchangessinceobject.h" +#include "jsondblistmodel.h" +#include "jsondbsortinglistmodel.h" #include "jsondbcachinglistmodel.h" QT_USE_NAMESPACE_JSONDB -Q_EXPORT_PLUGIN2(jsondbplugin, JsonDbPlugin) QQmlEngine *g_declEngine = 0; static QObject *jsondb_new_module_api_provider(QQmlEngine *engine, QJSEngine *scriptEngine) @@ -74,11 +72,10 @@ void JsonDbPlugin::registerTypes(const char *uri) { Q_ASSERT(uri == QLatin1String("QtJsonDb")); qmlRegisterModuleApi(uri, 1, 0, jsondb_new_module_api_provider); - qmlRegisterType<JsonDbListModel>(uri, 1, 0, "JsonDbListModel"); - qmlRegisterType<JsonDbSortingListModel>(uri, 1, 0, "JsonDbSortingListModel"); qmlRegisterType<JsonDbPartition>(uri, 1, 0, "Partition"); qmlRegisterType<JsonDbNotify>(uri, 1, 0, "Notification"); qmlRegisterType<JsonDbQueryObject>(uri, 1, 0, "Query"); - qmlRegisterType<JsonDbChangesSinceObject>(uri, 1, 0, "ChangesSince"); + qmlRegisterType<JsonDbListModel>(uri, 1, 0, "JsonDbListModel"); + qmlRegisterType<JsonDbSortingListModel>(uri, 1, 0, "JsonDbSortingListModel"); qmlRegisterType<JsonDbCachingListModel>(uri, 1, 0, "JsonDbCachingListModel"); } diff --git a/src/imports/jsondb/plugin.h b/src/imports/jsondb/plugin.h index bc6b03a..7db4b1e 100644 --- a/src/imports/jsondb/plugin.h +++ b/src/imports/jsondb/plugin.h @@ -51,6 +51,7 @@ extern QQmlEngine *g_declEngine; class JsonDbPlugin : public QQmlExtensionPlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface" FILE "jsondb.json") public: void initializeEngine(QQmlEngine *engine, const char *uri); void registerTypes(const char *uri); |