diff --git a/src/calendar/calendarservice.cpp b/src/calendar/calendarservice.cpp --- a/src/calendar/calendarservice.cpp +++ b/src/calendar/calendarservice.cpp @@ -207,6 +207,7 @@ static const auto idParam = QStringLiteral("id"); static const auto etagParam = QStringLiteral("etag"); +static const auto nextSyncTokenParam = QStringLiteral("nextSyncToken"); static const auto nextPageTokenParam = QStringLiteral("nextPageToken"); static const auto pageTokenParam = QStringLiteral("pageToken"); static const auto itemsParam = QStringLiteral("items"); @@ -807,6 +808,9 @@ // This should always be in Olson format timezone = data.value(timeZoneParam).toString(); } + if (data.contains(nextSyncTokenParam)) { + feedData.syncToken = data[nextSyncTokenParam].toString(); + } } else { return {}; } diff --git a/src/calendar/eventfetchjob.h b/src/calendar/eventfetchjob.h --- a/src/calendar/eventfetchjob.h +++ b/src/calendar/eventfetchjob.h @@ -114,6 +114,16 @@ */ Q_PROPERTY(QString filter READ filter WRITE setFilter) + /** + * @brief A token to fetch updates incrementally + * + * By default the property is empty. Properties timeMin, timeMax, + * updatedMin will be ignored if sync token is specified + * + * @see setSyncToken, syncToken + */ + Q_PROPERTY(QString syncToken READ syncToken WRITE setSyncToken) + public: /** @@ -214,6 +224,18 @@ */ quint64 timeMin() const; + /** + * @brief Sets token for incremental updates + * + * @param syncToken + */ + void setSyncToken(const QString& syncToken); + + /** + * @brief Token for next incremental update + */ + QString syncToken(); + protected: /** diff --git a/src/calendar/eventfetchjob.cpp b/src/calendar/eventfetchjob.cpp --- a/src/calendar/eventfetchjob.cpp +++ b/src/calendar/eventfetchjob.cpp @@ -39,6 +39,7 @@ QString calendarId; QString eventId; QString filter; + QString syncToken; bool fetchDeleted = true; quint64 updatedTimestamp = 0; quint64 timeMin = 0; @@ -107,6 +108,16 @@ return d->timeMax; } +void EventFetchJob::setSyncToken(const QString& syncToken) +{ + d->syncToken = syncToken; +} + +QString EventFetchJob::syncToken() +{ + return d->syncToken; +} + void EventFetchJob::setTimeMin(quint64 timestamp) { if (isRunning()) { @@ -147,14 +158,18 @@ if (!d->filter.isEmpty()) { query.addQueryItem(QStringLiteral("q"), d->filter); } - if (d->updatedTimestamp > 0) { - query.addQueryItem(QStringLiteral("updatedMin"), Utils::ts2Str(d->updatedTimestamp)); - } - if (d->timeMin > 0) { - query.addQueryItem(QStringLiteral("timeMin"), Utils::ts2Str(d->timeMin)); - } - if (d->timeMax > 0) { - query.addQueryItem(QStringLiteral("timeMax"), Utils::ts2Str(d->timeMax)); + if (d->syncToken.isEmpty()) { + if (d->updatedTimestamp > 0) { + query.addQueryItem(QStringLiteral("updatedMin"), Utils::ts2Str(d->updatedTimestamp)); + } + if (d->timeMin > 0) { + query.addQueryItem(QStringLiteral("timeMin"), Utils::ts2Str(d->timeMin)); + } + if (d->timeMax > 0) { + query.addQueryItem(QStringLiteral("timeMax"), Utils::ts2Str(d->timeMax)); + } + } else { + query.addQueryItem(QStringLiteral("syncToken"), d->syncToken); } url.setQuery(query); } else { @@ -168,8 +183,9 @@ { if (reply->error() == QNetworkReply::ContentGoneError || reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() == Gone) { - // Full sync required by server, redo request with no updatedMin + // Full sync required by server, redo request with no updatedMin and no syncToken d->updatedTimestamp = 0; + d->syncToken.clear(); start(); // Errors are not cleared on success // Do it here or else the job will fail @@ -189,6 +205,7 @@ } else { items << CalendarService::JSONToEvent(rawData).dynamicCast(); } + d->syncToken = feedData.syncToken; } else { setError(KGAPI2::InvalidResponse); setErrorString(tr("Invalid response content type")); diff --git a/src/core/types.h b/src/core/types.h --- a/src/core/types.h +++ b/src/core/types.h @@ -53,6 +53,8 @@ QUrl requestUrl; /**< Original URL of the request. This value is filled by AccessManager when passing the structure to a service */ + QString syncToken; /**< Sync token that can be used for incremental + updates by some of the services.*/ };