summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.qmake.conf2
-rw-r--r--doc/qtenginiooverview.qdocconf1
-rw-r--r--src/enginio_client/doc/qtenginio.qdocconf1
-rw-r--r--src/enginio_client/enginio_client.pro2
-rw-r--r--src/enginio_client/enginiobasemodel_p.h27
-rw-r--r--src/enginio_client/enginiomodel.cpp22
-rw-r--r--src/enginio_client/enginiomodel.h2
-rw-r--r--src/enginio_plugin/doc/qtenginioqml.qdocconf3
-rw-r--r--src/enginio_plugin/enginio_plugin.pro4
-rw-r--r--src/enginio_plugin/enginioqmlmodel.cpp6
-rw-r--r--src/enginio_plugin/enginioqmlmodel_p.h1
-rw-r--r--src/src.pro4
-rw-r--r--tests/auto/auto.pro5
-rw-r--r--tests/auto/enginiomodel/tst_enginiomodel.cpp130
-rw-r--r--tests/auto/files/files.pro1
-rw-r--r--tests/auto/qmltests/tst_model.qml31
16 files changed, 217 insertions, 25 deletions
diff --git a/.qmake.conf b/.qmake.conf
index 4a96a7b..65bfdeb 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -2,4 +2,4 @@ load(qt_build_config)
CONFIG += warning_clean
CONFIG += qt_example_installs
-MODULE_VERSION = 1.0.6
+MODULE_VERSION = 1.1.0
diff --git a/doc/qtenginiooverview.qdocconf b/doc/qtenginiooverview.qdocconf
index 638fa00..abc7a99 100644
--- a/doc/qtenginiooverview.qdocconf
+++ b/doc/qtenginiooverview.qdocconf
@@ -4,7 +4,6 @@ include(enginio_global.qdocconf)
project = QtEnginioOverview
description = Enginio Client Library
-url = http://qt-project.org/doc/qt-$QT_VER
version = $QT_VERSION
sourcedirs += .
diff --git a/src/enginio_client/doc/qtenginio.qdocconf b/src/enginio_client/doc/qtenginio.qdocconf
index b4f7f2b..ca1385c 100644
--- a/src/enginio_client/doc/qtenginio.qdocconf
+++ b/src/enginio_client/doc/qtenginio.qdocconf
@@ -4,7 +4,6 @@ include(../../../doc/enginio_global.qdocconf)
project = QtEnginio
description = Client library for Enginio
-url = http://qt-project.org/doc/qt-$QT_VER
version = $QT_VERSION
sourcedirs += .. \
diff --git a/src/enginio_client/enginio_client.pro b/src/enginio_client/enginio_client.pro
index ef3f868..f3a158d 100644
--- a/src/enginio_client/enginio_client.pro
+++ b/src/enginio_client/enginio_client.pro
@@ -1,5 +1,5 @@
TARGET = Enginio
-QT += core-private network
+QT = core-private network
DEFINES += ENGINIOCLIENT_LIBRARY
MODULE = enginio
diff --git a/src/enginio_client/enginiobasemodel_p.h b/src/enginio_client/enginiobasemodel_p.h
index bd6bd2f..cf0fd49 100644
--- a/src/enginio_client/enginiobasemodel_p.h
+++ b/src/enginio_client/enginiobasemodel_p.h
@@ -418,7 +418,7 @@ public:
_notifications.disable();
}
- void receivedNotification(QJsonObject data);
+ void receivedNotification(const QJsonObject &data);
void receivedRemoveNotification(const QJsonObject &object, int rowHint = NoHintRow);
void receivedUpdateNotification(const QJsonObject &object, const QString &idHint = QString(), int row = NoHintRow);
void receivedCreateNotification(const QJsonObject &object);
@@ -586,21 +586,27 @@ public:
filter.insert(EnginioString::data, objectType);
_notifications.connectToBackend(this, _enginio, filter);
- // send full query
- QJsonObject query = queryAsJson();
- ObjectAdaptor<QJsonObject> aQuery(query);
- QNetworkReply *nreply = _enginio->query(aQuery, static_cast<Enginio::Operation>(_operation));
- EnginioReplyState *ereply = _enginio->createReply(nreply);
- if (_canFetchMore)
- _latestRequestedOffset = query[EnginioString::limit].toDouble();
- FinishedFullQueryRequest finshedRequest = { this, ereply };
- QObject::connect(ereply, &EnginioReplyState::dataChanged, _replyConnectionConntext, finshedRequest);
+ EnginioReplyState *ereply = reload();
QObject::connect(ereply, &EnginioReplyState::dataChanged, ereply, &EnginioReplyState::deleteLater);
} else {
fullQueryReset(QJsonArray());
}
}
+ EnginioReplyState *reload()
+ {
+ // send full query
+ QJsonObject query = queryAsJson();
+ ObjectAdaptor<QJsonObject> aQuery(query);
+ QNetworkReply *nreply = _enginio->query(aQuery, static_cast<Enginio::Operation>(_operation));
+ EnginioReplyState *ereply = _enginio->createReply(nreply);
+ if (_canFetchMore)
+ _latestRequestedOffset = query[EnginioString::limit].toDouble();
+ FinishedFullQueryRequest finshedRequest = { this, ereply };
+ QObject::connect(ereply, &EnginioReplyState::dataChanged, _replyConnectionConntext, finshedRequest);
+ return ereply;
+ }
+
void finishedIncrementalUpdateRequest(const EnginioReplyState *reply, const QJsonObject &query)
{
Q_ASSERT(_canFetchMore);
@@ -993,6 +999,7 @@ struct EnginioModelPrivateT : public EnginioBaseModelPrivate
Reply *append(const QJsonObject &value) { return static_cast<Reply*>(Base::append(value)); }
Reply *remove(int row) { return static_cast<Reply*>(Base::remove(row)); }
Reply *setValue(int row, const QString &role, const QVariant &value) { return static_cast<Reply*>(Base::setValue(row, role, value)); }
+ Reply *reload() { return static_cast<Reply*>(Base::reload()); }
bool queryIsEmpty() const Q_DECL_OVERRIDE
{
diff --git a/src/enginio_client/enginiomodel.cpp b/src/enginio_client/enginiomodel.cpp
index 3d5f93d..722a2fc 100644
--- a/src/enginio_client/enginiomodel.cpp
+++ b/src/enginio_client/enginiomodel.cpp
@@ -161,7 +161,7 @@ EnginioBaseModelPrivate::~EnginioBaseModelPrivate()
delete _replyConnectionConntext;
}
-void EnginioBaseModelPrivate::receivedNotification(QJsonObject data)
+void EnginioBaseModelPrivate::receivedNotification(const QJsonObject &data)
{
const QJsonObject origin = data[EnginioString::origin].toObject();
const QString requestId = origin[EnginioString::apiRequestId].toString();
@@ -480,6 +480,25 @@ void EnginioModel::setOperation(Enginio::Operation operation)
}
/*!
+ Reload the model data from the server.
+ This is similar to reset and will emit \l modelAboutToBeReset() and \l modelReset().
+ This function invalidated the internal state of the model, reloads it from the backend
+ and resets all views.
+
+ \note when using this function while other requests to the server are made the result
+ is undefined. For example when calling append() and then reset() before append finished,
+ the model may or may not contain the result of the append operation.
+
+ \return reply from backend
+ \since 1.1
+*/
+EnginioReply *EnginioModel::reload()
+{
+ Q_D(EnginioModel);
+ return d->reload();
+}
+
+/*!
\include model-append.qdocinc
\sa EnginioClient::create()
*/
@@ -543,7 +562,6 @@ EnginioReply *EnginioModel::setData(int row, const QVariant &value, const QStrin
return d->setValue(row, role, value);
}
-
Qt::ItemFlags EnginioBaseModel::flags(const QModelIndex &index) const
{
return QAbstractListModel::flags(index) | Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;
diff --git a/src/enginio_client/enginiomodel.h b/src/enginio_client/enginiomodel.h
index 81c7eeb..f3cb0ca 100644
--- a/src/enginio_client/enginiomodel.h
+++ b/src/enginio_client/enginiomodel.h
@@ -82,6 +82,8 @@ public:
Q_INVOKABLE EnginioReply *setData(int row, const QVariant &value, const QString &role);
using EnginioBaseModel::setData;
+ Q_INVOKABLE EnginioReply *reload();
+
Q_SIGNALS:
void queryChanged(const QJsonObject &query);
void clientChanged(EnginioClient *client);
diff --git a/src/enginio_plugin/doc/qtenginioqml.qdocconf b/src/enginio_plugin/doc/qtenginioqml.qdocconf
index bd7b333..7546037 100644
--- a/src/enginio_plugin/doc/qtenginioqml.qdocconf
+++ b/src/enginio_plugin/doc/qtenginioqml.qdocconf
@@ -4,7 +4,6 @@ include(../../../doc/enginio_global.qdocconf)
project = QtEnginioQml
description = Client library for Enginio from QML
-url = http://qt-project.org/doc/qt-$QT_VER
version = $QT_VERSION
sourcedirs += .. \
@@ -46,7 +45,7 @@ qhp.QtEnginioQml.subprojects = qmltypes examples
qhp.QtEnginioQml.subprojects.qmltypes.title = QML Types
qhp.QtEnginioQml.subprojects.qmltypes.indexTitle = Enginio QML Types and Examples
-qhp.QtEnginioQml.subprojects.qmltypes.selectors = fake:qmlclass
+qhp.QtEnginioQml.subprojects.qmltypes.selectors = qmlclass
qhp.QtEnginioQml.subprojects.qmltypes.sortPages = true
qhp.QtEnginioQml.subprojects.examples.title = Examples
diff --git a/src/enginio_plugin/enginio_plugin.pro b/src/enginio_plugin/enginio_plugin.pro
index eef4dfb..89fa978 100644
--- a/src/enginio_plugin/enginio_plugin.pro
+++ b/src/enginio_plugin/enginio_plugin.pro
@@ -1,8 +1,8 @@
-requires(qtHaveModule(quick))
+requires(qtHaveModule(qml))
TARGETPATH = Enginio
-QT += qml quick enginio enginio-private core-private
+QT = qml enginio enginio-private core-private
QMAKE_DOCS = $$PWD/doc/qtenginioqml.qdocconf
OTHER_FILES += \
diff --git a/src/enginio_plugin/enginioqmlmodel.cpp b/src/enginio_plugin/enginioqmlmodel.cpp
index 43d0198..05410cf 100644
--- a/src/enginio_plugin/enginioqmlmodel.cpp
+++ b/src/enginio_plugin/enginioqmlmodel.cpp
@@ -255,6 +255,12 @@ EnginioQmlReply *EnginioQmlModel::setProperty(int row, const QString &role, cons
return d->setValue(row, role, value);
}
+EnginioQmlReply *EnginioQmlModel::reload()
+{
+ Q_D(EnginioQmlModel);
+ return d->reload();
+}
+
EnginioQmlClient *EnginioQmlModel::client() const
{
Q_D(const EnginioQmlModel);
diff --git a/src/enginio_plugin/enginioqmlmodel_p.h b/src/enginio_plugin/enginioqmlmodel_p.h
index 9b52308..c78d9af 100644
--- a/src/enginio_plugin/enginioqmlmodel_p.h
+++ b/src/enginio_plugin/enginioqmlmodel_p.h
@@ -79,6 +79,7 @@ public:
Q_INVOKABLE EnginioQmlReply *append(const QJSValue &value);
Q_INVOKABLE EnginioQmlReply *remove(int row);
Q_INVOKABLE EnginioQmlReply *setProperty(int row, const QString &role, const QVariant &value);
+ Q_INVOKABLE EnginioQmlReply *reload();
Q_SIGNALS:
void queryChanged(const QJSValue &query);
diff --git a/src/src.pro b/src/src.pro
index c3f8a69..e20d0b4 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -1,10 +1,8 @@
-requires(qtHaveModule(network))
-
TEMPLATE = subdirs
SUBDIRS += enginio_client
-qtHaveModule(quick) {
+qtHaveModule(qml) {
SUBDIRS += enginio_plugin
enginio_plugin.depends = enginio_client
}
diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro
index 817c5f6..ebe3dcd 100644
--- a/tests/auto/auto.pro
+++ b/tests/auto/auto.pro
@@ -3,10 +3,13 @@ TEMPLATE = subdirs
SUBDIRS += \
# cmake \
enginioclient \
- files \
notifications \
identity \
+qtHaveModule(gui) {
+ SUBDIRS += files
+}
+
qtHaveModule(quick) {
SUBDIRS += qmltests
}
diff --git a/tests/auto/enginiomodel/tst_enginiomodel.cpp b/tests/auto/enginiomodel/tst_enginiomodel.cpp
index 5edc707..744ce12 100644
--- a/tests/auto/enginiomodel/tst_enginiomodel.cpp
+++ b/tests/auto/enginiomodel/tst_enginiomodel.cpp
@@ -98,6 +98,8 @@ private slots:
void deleteModelDurringRequests();
void updatingRoles();
void setData();
+ void reload();
+
private:
template<class T>
void externallyRemovedImpl();
@@ -119,6 +121,23 @@ void tst_EnginioModel::initTestCase()
// The test operates on user data.
EnginioTests::prepareTestUsersAndUserGroups(_backendId);
EnginioTests::prepareTestObjectType(_backendName);
+
+ // Object types for the reload test
+ QJsonObject reload1;
+ reload1["name"] = QStringLiteral("reload1");
+ QJsonObject title;
+ title["name"] = QStringLiteral("title");
+ title["type"] = QStringLiteral("string");
+ title["indexed"] = false;
+ QJsonArray properties;
+ properties.append(title);
+ reload1["properties"] = properties;
+ QVERIFY(_backendManager.createObjectType(_backendName, EnginioTests::TESTAPP_ENV, reload1));
+
+ QJsonObject reload2;
+ reload2["name"] = QStringLiteral("reload2");
+ reload2["properties"] = properties;
+ QVERIFY(_backendManager.createObjectType(_backendName, EnginioTests::TESTAPP_ENV, reload2));
}
void tst_EnginioModel::cleanupTestCase()
@@ -1557,5 +1576,116 @@ void tst_EnginioModel::deleteReply()
QTRY_COMPARE(counter, replies.count());
}
+QJsonObject createTestObject(const QString &name, const QString &type)
+{
+ QJsonObject obj;
+ obj.insert("title", name);
+ obj.insert("objectType", type);
+ return obj;
+}
+
+void tst_EnginioModel::reload()
+{
+ QString objectType = "objects.reload1";
+
+ EnginioClient client;
+ client.setBackendId(_backendId);
+ client.setServiceUrl(EnginioTests::TESTAPP_URL);
+
+ QJsonObject query;
+ query.insert("objectType", objectType);
+
+ EnginioModel model;
+ model.disableNotifications();
+ model.setQuery(query);
+ model.setClient(&client);
+
+ QCOMPARE(model.rowCount(), 0);
+
+ // create an object, since notification are disabled the model cannot know about it
+ EnginioReply *r1(client.create(createTestObject(QString::fromLatin1("o1"), objectType)));
+ QTRY_VERIFY(r1->isFinished());
+ CHECK_NO_ERROR(r1);
+ QCOMPARE(model.rowCount(), 0);
+
+ // reload and verify that the object appears
+ EnginioReply *reload(model.reload());
+ QTRY_VERIFY(reload->isFinished());
+ CHECK_NO_ERROR(reload);
+ QCOMPARE(model.rowCount(), 1);
+
+ // this test mostly checks that we don't crash
+ // when calling reload while other operations are on-going it is undefined
+ // if the result contains the data of them or not
+
+ // create object and reload before that is finished
+ EnginioReply *r2(client.create(createTestObject(QString::fromLatin1("o2"), objectType)));
+ EnginioReply *reload2 = model.reload();
+ QVERIFY(reload2);
+ QTRY_VERIFY(r2->isFinished());
+ CHECK_NO_ERROR(r2);
+ QTRY_VERIFY(reload2->isFinished());
+ CHECK_NO_ERROR(reload2);
+
+ // create object bug delay it's response until reload is done
+ EnginioReply *r3(client.create(createTestObject(QString::fromLatin1("o3"), objectType)));
+ QVERIFY(r3);
+ r3->setDelayFinishedSignal(true);
+ EnginioReply *reload3(model.reload());
+ QVERIFY(reload3);
+ QTRY_VERIFY(reload3->isFinished());
+ r3->setDelayFinishedSignal(false);
+ QTRY_VERIFY(r3->isFinished());
+
+ // make sure we are in a defined state again
+ reload = model.reload();
+ QTRY_VERIFY(reload->isFinished());
+ QCOMPARE(model.rowCount(), 3);
+
+ EnginioReply *r4(model.append(createTestObject(QString::fromLatin1("o4"), objectType)));
+ EnginioReply *reload4(model.reload());
+ EnginioReply *r5(model.append(createTestObject(QString::fromLatin1("o5"), objectType)));
+ EnginioReply *reload5(model.reload());
+ QTRY_VERIFY(r4->isFinished() && reload4->isFinished() && r5->isFinished() && reload5->isFinished());
+
+ reload = model.reload();
+ QTRY_VERIFY(reload->isFinished());
+ QCOMPARE(model.rowCount(), 5);
+
+ // randomly reordered append and reset calls
+ EnginioReply *r6(model.append(createTestObject(QString::fromLatin1("o6"), objectType)));
+ r6->setDelayFinishedSignal(true);
+ EnginioReply *reload6(model.reload());
+ reload6->setDelayFinishedSignal(true);
+ EnginioReply *r7(model.append(createTestObject(QString::fromLatin1("o7"), objectType)));
+ r7->setDelayFinishedSignal(true);
+ EnginioReply *reload7(model.reload());
+ EnginioReply *c7(model.setData(6, QString::fromLatin1("object7"), QString::fromLatin1("title")));
+ EnginioReply *c5(model.setData(4, QString::fromLatin1("object5"), QString::fromLatin1("title")));
+ QTRY_VERIFY(reload7->isFinished());
+ r6->setDelayFinishedSignal(false);
+ r7->setDelayFinishedSignal(false);
+ reload6->setDelayFinishedSignal(false);
+ QTRY_VERIFY(c5->isFinished() && c7->isFinished() && r6->isFinished() && r7->isFinished() && reload6->isFinished());
+
+ reload = model.reload();
+ QTRY_VERIFY(reload->isFinished());
+ QCOMPARE(model.rowCount(), 7);
+
+ // completely try to mess it up by changing the query
+ // object type reload2 is empty
+ EnginioReply *reload8 = model.reload();
+ reload8->setDelayFinishedSignal(true);
+ QJsonObject query2;
+ query2.insert("objectTypes", "objects.reload2");
+ model.setQuery(query2);
+
+ QSignalSpy spy(&model, SIGNAL(modelReset()));
+ QTRY_VERIFY(spy.count());
+ reload8->setDelayFinishedSignal(false);
+ QTRY_VERIFY(reload8->isFinished());
+ QCOMPARE(model.rowCount(), 0);
+}
+
QTEST_MAIN(tst_EnginioModel)
#include "tst_enginiomodel.moc"
diff --git a/tests/auto/files/files.pro b/tests/auto/files/files.pro
index 7907092..ae191b7 100644
--- a/tests/auto/files/files.pro
+++ b/tests/auto/files/files.pro
@@ -1,5 +1,4 @@
QT += testlib enginio enginio-private core-private
-QT -= gui
DEFINES += TEST_FILE_PATH=\\\"$$_PRO_FILE_PWD_/../common/enginio.png\\\"
diff --git a/tests/auto/qmltests/tst_model.qml b/tests/auto/qmltests/tst_model.qml
index e98b41a..b7535bf 100644
--- a/tests/auto/qmltests/tst_model.qml
+++ b/tests/auto/qmltests/tst_model.qml
@@ -511,4 +511,35 @@ Item {
tryCompare(modelRowCount, "rowCountChangedCounter", initialRowCountChangedCounter + 4)
}
}
+
+ TestCase {
+ name: "EnginioModel: reload"
+
+ EnginioModel {
+ id: model
+ client: EnginioClient {
+ id: client
+ serviceUrl: AppConfig.backendData.serviceUrl
+
+ property int errorCount: 0
+ onError: {
+ ++errorCount
+ replyDumpDebugInfo(reply)
+ }
+
+ backendId: AppConfig.backendData.id
+ }
+ query: {
+ "objectType": AppConfig.testObjectType,
+ "query": {"testCase": "EnginioModel: rowCount"}
+ }
+ }
+
+ function test_rowCount()
+ {
+ var r = model.reload();
+ tryCompare(r, "isFinished", true);
+ compare(client.errorCount, 0)
+ }
+ }
}