2
Akonadi Google - Calendar Resource
3
Copyright (C) 2011 Dan Vratil <dan@progdan.cz>
5
This program is free software: you can redistribute it and/or modify
6
it under the terms of the GNU General Public License as published by
7
the Free Software Foundation, either version 3 of the License, or
8
(at your option) any later version.
10
This program is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
GNU General Public License for more details.
15
You should have received a copy of the GNU General Public License
16
along with this program. If not, see <http://www.gnu.org/licenses/>.
20
#include "calendarresource.h"
23
#include <libkgoogle/accessmanager.h>
24
#include <libkgoogle/auth.h>
25
#include <libkgoogle/fetchlistjob.h>
26
#include <libkgoogle/reply.h>
27
#include <libkgoogle/objects/task.h>
28
#include <libkgoogle/objects/tasklist.h>
29
#include <libkgoogle/services/tasks.h>
31
#include <KDE/KLocalizedString>
34
#include <KDE/Akonadi/ItemModifyJob>
35
#include <KDE/Akonadi/ItemFetchJob>
36
#include <KDE/Akonadi/EntityDisplayAttribute>
37
#include <KDE/Akonadi/CollectionModifyJob>
38
#include <KDE/Akonadi/ItemFetchScope>
41
using namespace Akonadi;
42
using namespace KGoogle;
46
#define TODO_MIMETYPE "application/x-vnd.akonadi.calendar.todo"
48
using namespace KCalCore;
49
#define TODO_MIMETYPE Todo::todoMimeType()
53
void CalendarResource::taskDoUpdate(Reply* reply)
55
Account::Ptr account = getAccount();
56
if (account.isNull()) {
61
Item item = reply->request()->property("Item").value< Item >();
62
TodoPtr todo = item.payload< TodoPtr >();
63
Objects::Task ktodo(*todo);
65
QUrl url = Services::Tasks::updateTaskUrl(item.parentCollection().remoteId(), item.remoteId());
67
Services::Tasks service;
68
QByteArray data = service.objectToJSON(static_cast< KGoogle::Object *>(&ktodo));
70
Request *request = new Request(url, Request::Update, "Tasks", account);
71
request->setRequestData(data, "application/json");
72
request->setProperty("Item", QVariant::fromValue(item));
73
m_gam->sendRequest(request);
77
void CalendarResource::taskListReceived(KJob *job)
81
Q_EMIT status(Broken, i18n("Failed to fetch task lists"));
85
FetchListJob *fetchJob = dynamic_cast< FetchListJob* >(job);
87
QStringList taskLists = Settings::self()->taskLists();
89
QList< Object* > data = fetchJob->items();
90
Q_FOREACH(Object * replyData, data) {
92
Objects::TaskList *taskList = static_cast< Objects::TaskList* >(replyData);
94
if (!taskLists.contains(taskList->uid()))
97
Collection collection;
98
collection.setRemoteId(taskList->uid());
99
collection.setParentCollection(m_collections.first());
100
collection.setContentMimeTypes(QStringList() << TODO_MIMETYPE);
101
collection.setName(taskList->title());
102
collection.setRights(Collection::AllRights);
104
EntityDisplayAttribute *attr = new EntityDisplayAttribute;
105
attr->setDisplayName(taskList->title());
106
attr->setIconName("text-calendar");
107
collection.addAttribute(attr);
109
m_collections.append(collection);
113
m_fetchedTaskLists = true;
115
if (m_fetchedTaskLists && m_fetchedCalendars) {
116
collectionsRetrieved(m_collections);
117
m_collections.clear();
119
m_fetchedCalendars = false;
120
m_fetchedTaskLists = false;
124
void CalendarResource::taskReceived(KGoogle::Reply *reply)
126
if (reply->error() != OK) {
127
cancelTask(i18n("Failed to fetch task: %1").arg(reply->errorString()));
131
QList< Object* > data = reply->replyData();
132
if (data.length() != 1) {
133
kWarning() << "Server send " << data.length() << "items, which is not OK";
134
cancelTask(i18n("Expected a single item, server sent %1 items.").arg(data.length()));
138
Objects::Task *task = static_cast< Objects::Task* >(data.first());
140
Item item = reply->request()->property("Item").value<Item>();
141
item.setRemoteId(task->uid());
142
item.setRemoteRevision(task->etag());
143
item.setMimeType(TODO_MIMETYPE);
144
item.setPayload< TodoPtr >(TodoPtr(task));
146
if (static_cast< Objects::Task* >(task)->deleted()) {
147
itemsRetrievedIncremental(Item::List(), Item::List() << item);
153
void CalendarResource::tasksReceived(KJob *job)
156
cancelTask(i18n("Failed to fetch tasks: %1").arg(job->errorString()));
160
FetchListJob *fetchJob = dynamic_cast< FetchListJob* >(job);
161
Collection collection = fetchJob->property("collection").value< Collection >();
166
QList< Object* > data = fetchJob->items();
167
Q_FOREACH(Object * replyData, data) {
169
Objects::Task *task = static_cast< Objects::Task* >(replyData);
172
item.setRemoteId(task->uid());
173
item.setRemoteRevision(task->etag());
174
item.setPayload< TodoPtr >(TodoPtr(task));
175
item.setMimeType(TODO_MIMETYPE);
176
item.setParentCollection(collection);
178
if (task->deleted()) {
186
itemsRetrievedIncremental(changed, removed);
188
collection.setRemoteRevision(QString::number(KDateTime::currentUtcDateTime().toTime_t()));
189
CollectionModifyJob *modifyJob = new CollectionModifyJob(collection, this);
190
modifyJob->setAutoDelete(true);
194
void CalendarResource::taskCreated(KGoogle::Reply *reply)
196
if (reply->error() != OK) {
197
cancelTask(i18n("Failed to create a task: %1").arg(reply->errorString()));
201
QList< Object* > data = reply->replyData();
202
if (data.length() != 1) {
203
kWarning() << "Server send " << data.length() << "items, which is not OK";
204
cancelTask(i18n("Expected a single item, server sent %1 items.").arg(data.length()));
208
Objects::Task *task = static_cast< Objects::Task* >(data.first());
210
Item item = reply->request()->property("Item").value<Item>();
211
item.setRemoteId(task->uid());
212
item.setRemoteRevision(task->etag());
213
item.setMimeType(TODO_MIMETYPE);
214
item.setParentCollection(reply->request()->property("Collection").value<Collection>());
216
changeCommitted(item);
219
void CalendarResource::taskUpdated(KGoogle::Reply *reply)
221
if (reply->error() != OK) {
222
cancelTask(i18n("Failed to update task: %1").arg(reply->errorString()));
226
QList< Object* > data = reply->replyData();
227
if (data.length() != 1) {
228
kWarning() << "Server send " << data.length() << "items, which is not OK";
229
cancelTask(i18n("Expected a single item, server sent %1 items.").arg(data.length()));
233
Objects::Task *task = static_cast< Objects::Task* >(data.first());
235
Item item = reply->request()->property("Item").value<Item>();
236
item.setRemoteRevision(task->etag());
238
changeCommitted(item);
241
void CalendarResource::removeTaskFetchJobFinished(KJob *job)
244
cancelTask(i18n("Failed to delete task (1): %1").arg(job->errorString()));
248
ItemFetchJob *fetchJob = dynamic_cast< ItemFetchJob* >(job);
249
Item removedItem = fetchJob->property("Item").value< Item >();
251
Item::List detachItems;
253
Item::List items = fetchJob->items();
254
Q_FOREACH (Item item, items)
256
if (!item.hasPayload< TodoPtr >()) {
257
kDebug() << "Item " << item.remoteId() << " does not have Todo payload";
261
TodoPtr todo = item.payload< TodoPtr >();
262
/* If this item is child of the item we want to remove then add it to detach list */
264
if (todo->relatedToUid() == removedItem.remoteId()) {
265
todo->setRelatedToUid(QString());
266
item.setPayload(todo);
270
if (todo->relatedTo(KCalCore::Incidence::RelTypeParent) == removedItem.remoteId()) {
271
todo->setRelatedTo(QString(), KCalCore::Incidence::RelTypeParent);
272
item.setPayload(todo);
278
/* If there are no items do detach, then delete the task right now */
279
if (detachItems.isEmpty()) {
284
/* Send modify request to detach all the sub-tasks from the task that is about to be
287
ItemModifyJob *modifyJob = new ItemModifyJob(detachItems);
288
modifyJob->setProperty("Item", qVariantFromValue(removedItem));
289
modifyJob->setAutoDelete(true);
290
connect(modifyJob, SIGNAL(finished(KJob*)), this, SLOT(doRemoveTask(KJob*)));
294
void CalendarResource::doRemoveTask(KJob *job)
297
cancelTask(i18n("Failed to delete task (2): %1").arg(job->errorString()));
301
Account::Ptr account = getAccount();
302
if (account.isNull()) {
307
Item item = job->property("Item").value< Item >();
309
/* Now finally we can safely remove the task we wanted to */
310
Request *request = new Request(Services::Tasks::removeTaskUrl(item.parentCollection().remoteId(), item.remoteId()),
311
KGoogle::Request::Remove, "Tasks", account);
312
request->setProperty("Item", qVariantFromValue(item));
313
m_gam->sendRequest(request);
316
void CalendarResource::taskRemoved(KGoogle::Reply *reply)
318
if (reply->error() != NoContent) {
319
cancelTask(i18n("Failed to delete task (5): %1").arg(reply->errorString()));
323
Item item = reply->request()->property("Item").value<Item>();
324
changeCommitted(item);