summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrederik Gladhorn <frederik.gladhorn@digia.com>2013-12-30 12:42:47 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-04-29 17:54:15 +0200
commitcd6204e77c4ff454030529a5c02be184965bb9e1 (patch)
tree32dbbb4a7fdf32135c6be30da22473634f6f0c24
parentd3f14ec2b3d7fbb1dd840775df6b2dec71827a81 (diff)
downloadqtenginio-cd6204e77c4ff454030529a5c02be184965bb9e1.tar.gz
Introduce EnginioModel::reload
[ChangeLog][EnginioModel] Added reload() function to EnginioModel to force a refresh of all model data. Change-Id: I7b1a3fdd6e63950f5494d4bab8511feb9f80d9fb Reviewed-by: Jędrzej Nowacki <jedrzej.nowacki@digia.com>
-rw-r--r--src/enginio_client/enginiobasemodel_p.h25
-rw-r--r--src/enginio_client/enginiomodel.cpp20
-rw-r--r--src/enginio_client/enginiomodel.h2
-rw-r--r--src/enginio_plugin/enginioqmlmodel.cpp6
-rw-r--r--src/enginio_plugin/enginioqmlmodel_p.h1
-rw-r--r--tests/auto/enginiomodel/tst_enginiomodel.cpp130
-rw-r--r--tests/auto/qmltests/tst_model.qml31
7 files changed, 205 insertions, 10 deletions
diff --git a/src/enginio_client/enginiobasemodel_p.h b/src/enginio_client/enginiobasemodel_p.h
index bd6bd2f..c615a23 100644
--- a/src/enginio_client/enginiobasemodel_p.h
+++ b/src/enginio_client/enginiobasemodel_p.h
@@ -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..644b9a6 100644
--- a/src/enginio_client/enginiomodel.cpp
+++ b/src/enginio_client/enginiomodel.cpp
@@ -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/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/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/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)
+ }
+ }
}