Changeset View
Changeset View
Standalone View
Standalone View
resources/google-groupware/contacthandler.cpp
- This file was added.
1 | /* | ||||
---|---|---|---|---|---|
2 | Copyright (C) 2011-2013 Daniel Vrátil <dvratil@redhat.com> | ||||
3 | 2020 Igor Poboiko <igor.poboiko@gmail.com> | ||||
4 | | ||||
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. | ||||
9 | | ||||
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. | ||||
14 | | ||||
15 | You should have received a copy of the GNU General Public License | ||||
16 | along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||
17 | */ | ||||
18 | | ||||
19 | #include "contacthandler.h" | ||||
20 | #include "googleresource.h" | ||||
21 | | ||||
22 | #include <AkonadiCore/CollectionModifyJob> | ||||
23 | #include <AkonadiCore/EntityDisplayAttribute> | ||||
24 | #include <AkonadiCore/EntityHiddenAttribute> | ||||
25 | #include <AkonadiCore/ItemFetchJob> | ||||
26 | #include <AkonadiCore/ItemFetchScope> | ||||
27 | #include <AkonadiCore/ItemModifyJob> | ||||
28 | #include <AkonadiCore/LinkJob> | ||||
29 | #include <AkonadiCore/VectorHelper> | ||||
30 | | ||||
31 | #include <KContacts/Addressee> | ||||
32 | #include <KContacts/Picture> | ||||
33 | | ||||
34 | #include <KGAPI/Account> | ||||
35 | #include <KGAPI/Contacts/Contact> | ||||
36 | #include <KGAPI/Contacts/ContactCreateJob> | ||||
37 | #include <KGAPI/Contacts/ContactDeleteJob> | ||||
38 | #include <KGAPI/Contacts/ContactFetchJob> | ||||
39 | #include <KGAPI/Contacts/ContactFetchPhotoJob> | ||||
40 | #include <KGAPI/Contacts/ContactModifyJob> | ||||
41 | #include <KGAPI/Contacts/ContactsGroup> | ||||
42 | #include <KGAPI/Contacts/ContactsGroupCreateJob> | ||||
43 | #include <KGAPI/Contacts/ContactsGroupDeleteJob> | ||||
44 | #include <KGAPI/Contacts/ContactsGroupFetchJob> | ||||
45 | #include <KGAPI/Contacts/ContactsGroupModifyJob> | ||||
46 | | ||||
47 | #include "googlecontacts_debug.h" | ||||
48 | | ||||
49 | #define OTHERCONTACTS_REMOTEID QStringLiteral("OtherContacts") | ||||
50 | | ||||
51 | using namespace KGAPI2; | ||||
52 | using namespace Akonadi; | ||||
53 | | ||||
54 | QString ContactHandler::mimetype() | ||||
55 | { | ||||
56 | return KContacts::Addressee::mimeType(); | ||||
57 | } | ||||
58 | | ||||
59 | bool ContactHandler::canPerformTask(const Item &item) | ||||
60 | { | ||||
61 | return m_resource->canPerformTask<KContacts::Addressee>(item, mimetype()); | ||||
62 | } | ||||
63 | | ||||
64 | QString ContactHandler::myContactsRemoteId() const | ||||
65 | { | ||||
66 | return QStringLiteral("http://www.google.com/m8/feeds/groups/%1/base/6").arg(QString::fromLatin1(QUrl::toPercentEncoding(m_settings->accountPtr()->accountName()))); | ||||
67 | } | ||||
68 | | ||||
69 | void ContactHandler::setupCollection(Collection &collection, const ContactsGroupPtr &group) | ||||
70 | { | ||||
71 | collection.setContentMimeTypes({ KContacts::Addressee::mimeType() }); | ||||
72 | collection.setName(group->id()); | ||||
73 | collection.setRemoteId(group->id()); | ||||
74 | collection.setParentCollection(m_resource->rootCollection()); | ||||
75 | | ||||
76 | QString realName = group->title(); | ||||
77 | if (group->isSystemGroup()) { | ||||
78 | if (group->title().contains(QLatin1String("Coworkers"))) { | ||||
79 | realName = i18nc("Name of a group of contacts", "Coworkers"); | ||||
80 | } else if (group->title().contains(QLatin1String("Friends"))) { | ||||
81 | realName = i18nc("Name of a group of contacts", "Friends"); | ||||
82 | } else if (group->title().contains(QLatin1String("Family"))) { | ||||
83 | realName = i18nc("Name of a group of contacts", "Family"); | ||||
84 | } else if (group->title().contains(QLatin1String("My Contacts"))) { | ||||
85 | realName = i18nc("Name of a group of contacts", "My Contacts"); | ||||
86 | } | ||||
87 | } | ||||
88 | | ||||
89 | // "My Contacts" is the only one not virtual | ||||
90 | if (group->id() == myContactsRemoteId()) { | ||||
91 | collection.setRights(Collection::CanCreateItem | ||||
92 | |Collection::CanChangeItem | ||||
93 | |Collection::CanDeleteItem); | ||||
94 | } else { | ||||
95 | collection.setRights(Collection::CanLinkItem | ||||
96 | |Collection::CanUnlinkItem | ||||
97 | |Collection::CanChangeItem); | ||||
98 | collection.setVirtual(true); | ||||
99 | if (!group->isSystemGroup()) { | ||||
100 | collection.setRights(collection.rights() | ||||
101 | |Collection::CanChangeCollection | ||||
102 | |Collection::CanDeleteCollection); | ||||
103 | } | ||||
104 | } | ||||
105 | | ||||
106 | auto attr = collection.attribute<EntityDisplayAttribute>(Collection::AddIfMissing); | ||||
107 | attr->setDisplayName(realName); | ||||
108 | attr->setIconName(QStringLiteral("view-pim-contacts")); | ||||
109 | } | ||||
110 | | ||||
111 | void ContactHandler::retrieveCollections() | ||||
112 | { | ||||
113 | Q_EMIT m_resource->status(AgentBase::Running, i18nc("@info:status", "Retrieving contacts groups")); | ||||
114 | qCDebug(GOOGLE_CONTACTS_LOG) << "Retrieving contacts groups..."; | ||||
115 | m_collections.clear(); | ||||
116 | | ||||
117 | Collection otherCollection; | ||||
118 | otherCollection.setContentMimeTypes({ KContacts::Addressee::mimeType() }); | ||||
119 | otherCollection.setName(i18n("Other Contacts")); | ||||
120 | otherCollection.setParentCollection(m_resource->rootCollection()); | ||||
121 | otherCollection.setRights(Collection::CanCreateItem | ||||
122 | |Collection::CanChangeItem | ||||
123 | |Collection::CanDeleteItem); | ||||
124 | otherCollection.setRemoteId(OTHERCONTACTS_REMOTEID); | ||||
125 | | ||||
126 | auto attr = otherCollection.attribute<EntityDisplayAttribute>(Collection::AddIfMissing); | ||||
127 | attr->setDisplayName(i18n("Other Contacts")); | ||||
128 | attr->setIconName(QStringLiteral("view-pim-contacts")); | ||||
129 | | ||||
130 | m_resource->collectionsRetrieved({ otherCollection }); | ||||
131 | m_collections[ OTHERCONTACTS_REMOTEID ] = otherCollection; | ||||
132 | | ||||
133 | auto job = new ContactsGroupFetchJob(m_settings->accountPtr(), this); | ||||
134 | connect(job, &ContactFetchJob::finished, this, &ContactHandler::slotCollectionsRetrieved); | ||||
135 | } | ||||
136 | | ||||
137 | void ContactHandler::slotCollectionsRetrieved(KGAPI2::Job *job) | ||||
138 | { | ||||
139 | if (!m_resource->handleError(job)) { | ||||
140 | return; | ||||
141 | } | ||||
142 | qCDebug(GOOGLE_CONTACTS_LOG) << "Contacts groups retrieved"; | ||||
143 | | ||||
144 | const ObjectsList objects = qobject_cast<ContactsGroupFetchJob *>(job)->items(); | ||||
145 | Collection::List collections; | ||||
146 | collections.reserve(objects.count()); | ||||
147 | std::transform(objects.cbegin(), objects.cend(), std::back_inserter(collections), | ||||
148 | [this](const ObjectPtr &object){ | ||||
149 | const ContactsGroupPtr group = object.dynamicCast<ContactsGroup>(); | ||||
150 | qCDebug(GOOGLE_CONTACTS_LOG) << " -" << group->title() << "(" << group->id() << ")"; | ||||
151 | Collection collection; | ||||
152 | setupCollection(collection, group); | ||||
153 | m_collections[ collection.remoteId() ] = collection; | ||||
154 | return collection; | ||||
155 | }); | ||||
156 | m_resource->collectionsRetrievedFromHandler(collections); | ||||
157 | } | ||||
158 | | ||||
159 | void ContactHandler::retrieveItems(const Collection &collection) | ||||
160 | { | ||||
161 | // Contacts are stored inside "My Contacts" and "Other Contacts" only | ||||
162 | if ((collection.remoteId() != OTHERCONTACTS_REMOTEID) | ||||
163 | && (collection.remoteId() != myContactsRemoteId())) { | ||||
164 | m_resource->itemsRetrievalDone(); | ||||
165 | return; | ||||
166 | } | ||||
167 | Q_EMIT m_resource->status(AgentBase::Running, i18nc("@info:status", "Retrieving contacts for group '%1'", collection.displayName())); | ||||
168 | qCDebug(GOOGLE_CONTACTS_LOG) << "Retreiving contacts for group" << collection.remoteId() << "..."; | ||||
169 | | ||||
170 | auto job = new ContactFetchJob(m_settings->accountPtr(), this); | ||||
171 | if (!collection.remoteRevision().isEmpty()) { | ||||
172 | job->setFetchOnlyUpdated(collection.remoteRevision().toLongLong()); | ||||
173 | job->setFetchDeleted(true); | ||||
174 | } else { | ||||
175 | // No need to fetch deleted items for a non-incremental update | ||||
176 | job->setFetchDeleted(false); | ||||
177 | } | ||||
178 | connect(job, &ContactFetchJob::finished, this, &ContactHandler::slotItemsRetrieved); | ||||
179 | } | ||||
180 | | ||||
181 | void ContactHandler::slotItemsRetrieved(KGAPI2::Job *job) | ||||
182 | { | ||||
183 | if (!m_resource->handleError(job)) { | ||||
184 | return; | ||||
185 | } | ||||
186 | | ||||
187 | Collection collection = m_resource->currentCollection(); | ||||
188 | | ||||
189 | Item::List changedItems, removedItems; | ||||
190 | QHash<QString, Item::List> groupsMap; | ||||
191 | QStringList changedPhotos; | ||||
192 | | ||||
193 | auto fetchJob = qobject_cast<ContactFetchJob *>(job); | ||||
194 | bool isIncremental = (fetchJob->fetchOnlyUpdated() > 0); | ||||
195 | const ObjectsList objects = fetchJob->items(); | ||||
196 | qCDebug(GOOGLE_CONTACTS_LOG) << "Retrieved" << objects.count() << "contacts"; | ||||
197 | for (const ObjectPtr &object : objects) { | ||||
198 | const ContactPtr contact = object.dynamicCast<Contact>(); | ||||
199 | | ||||
200 | Item item; | ||||
201 | item.setMimeType( mimetype() ); | ||||
202 | item.setParentCollection(collection); | ||||
203 | item.setRemoteId(contact->uid()); | ||||
204 | item.setRemoteRevision(contact->etag()); | ||||
205 | item.setPayload<KContacts::Addressee>(*contact.dynamicCast<KContacts::Addressee>()); | ||||
206 | | ||||
207 | if (contact->deleted() | ||||
208 | || (collection.remoteId() == OTHERCONTACTS_REMOTEID && !contact->groups().isEmpty()) | ||||
209 | || (collection.remoteId() == myContactsRemoteId() && contact->groups().isEmpty())) { | ||||
210 | qCDebug(GOOGLE_CONTACTS_LOG) << " - removed" << contact->uid(); | ||||
211 | removedItems << item; | ||||
212 | } else { | ||||
213 | qCDebug(GOOGLE_CONTACTS_LOG) << " - changed" << contact->uid(); | ||||
214 | changedItems << item; | ||||
215 | changedPhotos << contact->uid(); | ||||
216 | } | ||||
217 | | ||||
218 | const QStringList groups = contact->groups(); | ||||
219 | for (const QString &group : groups) { | ||||
220 | // We don't link contacts to "My Contacts" | ||||
221 | if (group != myContactsRemoteId()) { | ||||
222 | groupsMap[group] << item; | ||||
223 | } | ||||
224 | } | ||||
225 | } | ||||
226 | | ||||
227 | if (isIncremental) { | ||||
228 | m_resource->itemsRetrievedIncremental(changedItems, removedItems); | ||||
229 | } else { | ||||
230 | m_resource->itemsRetrieved(changedItems); | ||||
231 | } | ||||
232 | | ||||
233 | for (auto iter = groupsMap.constBegin(), iterEnd = groupsMap.constEnd(); iter != iterEnd; ++iter) { | ||||
234 | new LinkJob(m_collections[iter.key()], iter.value(), this); | ||||
235 | } | ||||
236 | // TODO: unlink if the group was removed! | ||||
237 | | ||||
238 | if (!changedPhotos.isEmpty()) { | ||||
239 | QVariantMap map; | ||||
240 | map[QStringLiteral("collection")] = QVariant::fromValue(collection); | ||||
241 | map[QStringLiteral("modified")] = QVariant::fromValue(changedPhotos); | ||||
242 | m_resource->scheduleCustomTask(this, "retrieveContactsPhotos", map); | ||||
243 | } | ||||
244 | | ||||
245 | const QDateTime local(QDateTime::currentDateTime()); | ||||
246 | const QDateTime UTC(local.toUTC()); | ||||
247 | | ||||
248 | collection.setRemoteRevision(QString::number(UTC.toSecsSinceEpoch())); | ||||
249 | new CollectionModifyJob(collection, this); | ||||
250 | | ||||
251 | m_resource->emitReadyStatus(); | ||||
252 | } | ||||
253 | | ||||
254 | void ContactHandler::retrieveContactsPhotos(const QVariant &argument) | ||||
255 | { | ||||
256 | if (!m_resource->canPerformTask()) { | ||||
257 | return; | ||||
258 | } | ||||
259 | const auto map = argument.value<QVariantMap>(); | ||||
260 | const auto collection = map[QStringLiteral("collection")].value<Collection>(); | ||||
261 | const auto changedPhotos = map[QStringLiteral("modified")].toStringList(); | ||||
262 | Q_EMIT m_resource->status(AgentBase::Running, i18ncp("@info:status", "Retrieving %1 contacts photos for group '%2'", | ||||
263 | "Retrieving %1 contact photo for group '%2'", | ||||
264 | changedPhotos.count(), collection.displayName())); | ||||
265 | | ||||
266 | Item::List items; | ||||
267 | items.reserve(changedPhotos.size()); | ||||
268 | std::transform(changedPhotos.cbegin(), changedPhotos.cend(), std::back_inserter(items), | ||||
269 | [](const QString &contact){ | ||||
270 | Item item; | ||||
271 | item.setRemoteId(contact); | ||||
272 | return item; | ||||
273 | }); | ||||
274 | auto job = new ItemFetchJob(items, this); | ||||
275 | job->setCollection(collection); | ||||
276 | job->fetchScope().fetchFullPayload(true); | ||||
277 | connect(job, &ItemFetchJob::finished, this, &ContactHandler::slotUpdatePhotosItemsRetrieved); | ||||
278 | } | ||||
279 | | ||||
280 | void ContactHandler::slotUpdatePhotosItemsRetrieved(KJob *job) | ||||
281 | { | ||||
282 | // Make sure account is still valid | ||||
283 | if (!m_resource->canPerformTask()) { | ||||
284 | return; | ||||
285 | } | ||||
286 | const Item::List items = qobject_cast<ItemFetchJob *>(job)->items(); | ||||
287 | ContactsList contacts; | ||||
288 | qCDebug(GOOGLE_CONTACTS_LOG) << "Fetched" << items.count() << "contacts for photo update"; | ||||
289 | contacts.reserve(items.size()); | ||||
290 | std::transform(items.cbegin(), items.cend(), std::back_inserter(contacts), | ||||
291 | [](const Item &item){ | ||||
292 | const KContacts::Addressee addressee = item.payload<KContacts::Addressee>(); | ||||
293 | const ContactPtr contact(new Contact(addressee)); | ||||
294 | return contact; | ||||
295 | }); | ||||
296 | | ||||
297 | qCDebug(GOOGLE_CONTACTS_LOG) << "Starting fetching photos..."; | ||||
298 | auto photoJob = new ContactFetchPhotoJob(contacts, m_settings->accountPtr(), this); | ||||
299 | photoJob->setProperty("processedItems", 0); | ||||
300 | connect(photoJob, &ContactFetchPhotoJob::photoFetched, this, [this, items](KGAPI2::Job *job, const ContactPtr &contact){ | ||||
301 | qCDebug(GOOGLE_CONTACTS_LOG) << " - fetched photo for contact" << contact->uid(); | ||||
302 | int processedItems = job->property("processedItems").toInt(); | ||||
303 | processedItems++; | ||||
304 | job->setProperty("processedItems", processedItems); | ||||
305 | Q_EMIT m_resource->percent(100.0f*processedItems / items.count()); | ||||
306 | | ||||
307 | auto it = std::find_if(items.cbegin(), items.cend(), [&contact](const Item &item){ | ||||
308 | return item.remoteId() == contact->uid(); | ||||
309 | }); | ||||
310 | if (it != items.cend()) { | ||||
311 | Item newItem(*it); | ||||
312 | newItem.setPayload<KContacts::Addressee>(*contact.dynamicCast<KContacts::Addressee>()); | ||||
313 | new ItemModifyJob(newItem, this); | ||||
314 | } | ||||
315 | }); | ||||
316 | | ||||
317 | connect(photoJob, &ContactFetchPhotoJob::finished, m_resource, &GoogleResource::slotGenericJobFinished); | ||||
318 | } | ||||
319 | | ||||
320 | void ContactHandler::itemAdded(const Item &item, const Collection &collection) | ||||
321 | { | ||||
322 | Q_EMIT m_resource->status(AgentBase::Running, i18nc("@info:status", "Adding contact to group '%1'", collection.displayName())); | ||||
323 | auto addressee = item.payload< KContacts::Addressee >(); | ||||
324 | ContactPtr contact(new Contact(addressee)); | ||||
325 | qCDebug(GOOGLE_CONTACTS_LOG) << "Creating contact"; | ||||
326 | | ||||
327 | if (collection.remoteId() == myContactsRemoteId()) { | ||||
328 | contact->addGroup(myContactsRemoteId()); | ||||
329 | } | ||||
330 | | ||||
331 | auto job = new ContactCreateJob(contact, m_settings->accountPtr(), this); | ||||
332 | connect(job, &ContactCreateJob::finished, this, [this, item](KGAPI2::Job *job){ | ||||
333 | if (!m_resource->handleError(job)) { | ||||
334 | return; | ||||
335 | } | ||||
336 | ContactPtr contact = qobject_cast<ContactCreateJob *>(job)->items().first().dynamicCast<Contact>(); | ||||
337 | Item newItem = item; | ||||
338 | qCDebug(GOOGLE_CONTACTS_LOG) << "Contact" << contact->uid() << "created"; | ||||
339 | newItem.setRemoteId(contact->uid()); | ||||
340 | newItem.setRemoteRevision(contact->etag()); | ||||
341 | m_resource->changeCommitted(newItem); | ||||
342 | newItem.setPayload<KContacts::Addressee>(*contact.dynamicCast<KContacts::Addressee>()); | ||||
343 | new ItemModifyJob(newItem, this); | ||||
344 | m_resource->emitReadyStatus(); | ||||
345 | }); | ||||
346 | } | ||||
347 | | ||||
348 | void ContactHandler::itemChanged(const Item &item, const QSet< QByteArray > &partIdentifiers) | ||||
349 | { | ||||
350 | Q_UNUSED(partIdentifiers); | ||||
351 | Q_EMIT m_resource->status(AgentBase::Running, i18nc("@info:status", "Changing contact")); | ||||
352 | qCDebug(GOOGLE_CONTACTS_LOG) << "Changing contact" << item.remoteId(); | ||||
353 | KContacts::Addressee addressee = item.payload< KContacts::Addressee >(); | ||||
354 | ContactPtr contact(new Contact(addressee)); | ||||
355 | auto job = new ContactModifyJob(contact, m_settings->accountPtr(), this); | ||||
356 | job->setProperty(ITEM_PROPERTY, QVariant::fromValue(item)); | ||||
357 | connect(job, &ContactModifyJob::finished, m_resource, &GoogleResource::slotGenericJobFinished); | ||||
358 | } | ||||
359 | | ||||
360 | void ContactHandler::itemsRemoved(const Item::List &items) | ||||
361 | { | ||||
362 | Q_EMIT m_resource->status(AgentBase::Running, i18ncp("@info:status", "Removing %1 contacts", "Removing %1 contact", items.count())); | ||||
363 | QStringList contactIds; | ||||
364 | contactIds.reserve(items.count()); | ||||
365 | std::transform(items.cbegin(), items.cend(), std::back_inserter(contactIds), | ||||
366 | [](const Item &item){ | ||||
367 | return item.remoteId(); | ||||
368 | }); | ||||
369 | qCDebug(GOOGLE_CONTACTS_LOG) << "Removing contacts" << contactIds; | ||||
370 | auto job = new ContactDeleteJob(contactIds, m_settings->accountPtr(), this); | ||||
371 | job->setProperty(ITEMS_PROPERTY, QVariant::fromValue(items)); | ||||
372 | connect(job, &ContactDeleteJob::finished, m_resource, &GoogleResource::slotGenericJobFinished); | ||||
373 | } | ||||
374 | | ||||
375 | void ContactHandler::itemsMoved(const Item::List &items, const Collection &collectionSource, const Collection &collectionDestination) | ||||
376 | { | ||||
377 | qCDebug(GOOGLE_CONTACTS_LOG) << "Moving contacts from" << collectionSource.remoteId() << "to" << collectionDestination.remoteId(); | ||||
378 | if (!(((collectionSource.remoteId() == myContactsRemoteId()) && (collectionDestination.remoteId() == OTHERCONTACTS_REMOTEID)) || | ||||
379 | ((collectionSource.remoteId() == OTHERCONTACTS_REMOTEID) && (collectionDestination.remoteId() == myContactsRemoteId())))) { | ||||
380 | m_resource->cancelTask(i18n("Invalid source or destination collection")); | ||||
381 | } | ||||
382 | | ||||
383 | Q_EMIT m_resource->status(AgentBase::Running, i18ncp("@info:status", "Moving %1 contacts from group '%2' to '%3'", | ||||
384 | "Moving %1 contact from group '%2' to '%3'", | ||||
385 | items.count(), collectionSource.remoteId(), collectionDestination.remoteId())); | ||||
386 | ContactsList contacts; | ||||
387 | contacts.reserve(items.count()); | ||||
388 | std::transform(items.cbegin(), items.cend(), std::back_inserter(contacts), | ||||
389 | [this, &collectionSource, &collectionDestination](const Item &item){ | ||||
390 | KContacts::Addressee addressee = item.payload<KContacts::Addressee>(); | ||||
391 | ContactPtr contact(new Contact(addressee)); | ||||
392 | // MyContacts -> OtherContacts | ||||
393 | if (collectionSource.remoteId() == myContactsRemoteId() | ||||
394 | && collectionDestination.remoteId() == OTHERCONTACTS_REMOTEID) { | ||||
395 | contact->clearGroups(); | ||||
396 | // OtherContacts -> MyContacts | ||||
397 | } else if (collectionSource.remoteId() == OTHERCONTACTS_REMOTEID | ||||
398 | && collectionDestination.remoteId() == myContactsRemoteId()) { | ||||
399 | contact->addGroup(myContactsRemoteId()); | ||||
400 | } | ||||
401 | | ||||
402 | return contact; | ||||
403 | }); | ||||
404 | qCDebug(GOOGLE_CONTACTS_LOG) << "Moving contacts from" << collectionSource.remoteId() << "to" << collectionDestination.remoteId(); | ||||
405 | auto job = new ContactModifyJob(contacts, m_settings->accountPtr(), this); | ||||
406 | job->setProperty(ITEMS_PROPERTY, QVariant::fromValue(items)); | ||||
407 | connect(job, &ContactModifyJob::finished, m_resource, &GoogleResource::slotGenericJobFinished); | ||||
408 | } | ||||
409 | | ||||
410 | void ContactHandler::itemsLinked(const Item::List &items, const Collection &collection) | ||||
411 | { | ||||
412 | Q_EMIT m_resource->status(AgentBase::Running, i18ncp("@info:status", "Linking %1 contact", "Linking %1 contacts", items.count())); | ||||
413 | qCDebug(GOOGLE_CONTACTS_LOG) << "Linking" << items.count() << "contacts to group" << collection.remoteId(); | ||||
414 | | ||||
415 | ContactsList contacts; | ||||
416 | contacts.reserve(items.count()); | ||||
417 | std::transform(items.cbegin(), items.cend(), std::back_inserter(contacts), | ||||
418 | [this, &collection](const Item &item){ | ||||
419 | KContacts::Addressee addressee = item.payload<KContacts::Addressee>(); | ||||
420 | ContactPtr contact(new Contact(addressee)); | ||||
421 | contact->addGroup(collection.remoteId()); | ||||
422 | return contact; | ||||
423 | }); | ||||
424 | auto job = new ContactModifyJob(contacts, m_settings->accountPtr(), this); | ||||
425 | job->setProperty(ITEMS_PROPERTY, QVariant::fromValue(items)); | ||||
426 | connect(job, &ContactModifyJob::finished, m_resource, &GoogleResource::slotGenericJobFinished); | ||||
427 | } | ||||
428 | | ||||
429 | void ContactHandler::itemsUnlinked(const Item::List &items, const Collection &collection) | ||||
430 | { | ||||
431 | Q_EMIT m_resource->status(AgentBase::Running, i18ncp("@info:status", "Unlinking %1 contact", "Unlinking %1 contacts", items.count())); | ||||
432 | qCDebug(GOOGLE_CONTACTS_LOG) << "Unlinking" << items.count() << "contacts from group" << collection.remoteId(); | ||||
433 | | ||||
434 | ContactsList contacts; | ||||
435 | contacts.reserve(items.count()); | ||||
436 | std::transform(items.cbegin(), items.cend(), std::back_inserter(contacts), | ||||
437 | [this, &collection](const Item &item){ | ||||
438 | KContacts::Addressee addressee = item.payload<KContacts::Addressee>(); | ||||
439 | ContactPtr contact(new Contact(addressee)); | ||||
440 | contact->removeGroup(collection.remoteId()); | ||||
441 | return contact; | ||||
442 | }); | ||||
443 | auto job = new ContactModifyJob(contacts, m_settings->accountPtr(), this); | ||||
444 | job->setProperty(ITEMS_PROPERTY, QVariant::fromValue(items)); | ||||
445 | connect(job, &ContactModifyJob::finished, m_resource, &GoogleResource::slotGenericJobFinished); | ||||
446 | } | ||||
447 | | ||||
448 | | ||||
449 | void ContactHandler::collectionAdded(const Collection &collection, const Collection & /*parent*/) | ||||
450 | { | ||||
451 | Q_EMIT m_resource->status(AgentBase::Running, i18nc("@info:status", "Creating new contact group '%1'", collection.displayName())); | ||||
452 | qCDebug(GOOGLE_CONTACTS_LOG) << "Adding contact group" << collection.displayName(); | ||||
453 | ContactsGroupPtr group(new ContactsGroup); | ||||
454 | group->setTitle(collection.name()); | ||||
455 | group->setIsSystemGroup(false); | ||||
456 | | ||||
457 | auto job = new ContactsGroupCreateJob(group, m_settings->accountPtr(), this); | ||||
458 | connect(job, &ContactsGroupCreateJob::finished, this, [this, collection](KGAPI2::Job *job){ | ||||
459 | if (!m_resource->handleError(job)) { | ||||
460 | return; | ||||
461 | } | ||||
462 | | ||||
463 | ContactsGroupPtr group = qobject_cast<ContactsGroupCreateJob *>(job)->items().first().dynamicCast<ContactsGroup>(); | ||||
464 | qCDebug(GOOGLE_CONTACTS_LOG) << "Contact group created:" << group->id(); | ||||
465 | Collection newCollection(collection); | ||||
466 | setupCollection(newCollection, group); | ||||
467 | m_collections[ newCollection.remoteId() ] = newCollection; | ||||
468 | m_resource->changeCommitted(newCollection); | ||||
469 | m_resource->emitReadyStatus(); | ||||
470 | }); | ||||
471 | } | ||||
472 | | ||||
473 | void ContactHandler::collectionChanged(const Collection &collection) | ||||
474 | { | ||||
475 | Q_EMIT m_resource->status(AgentBase::Running, i18nc("@info:status", "Changing contact group '%1'", collection.displayName())); | ||||
476 | qCDebug(GOOGLE_CONTACTS_LOG) << "Changing contact group" << collection.remoteId(); | ||||
477 | | ||||
478 | ContactsGroupPtr group(new ContactsGroup()); | ||||
479 | group->setId(collection.remoteId()); | ||||
480 | group->setTitle(collection.displayName()); | ||||
481 | | ||||
482 | auto job = new ContactsGroupModifyJob(group, m_settings->accountPtr(), this); | ||||
483 | job->setProperty(COLLECTION_PROPERTY, QVariant::fromValue(collection)); | ||||
484 | connect(job, &ContactsGroupModifyJob::finished, m_resource, &GoogleResource::slotGenericJobFinished); | ||||
485 | } | ||||
486 | | ||||
487 | void ContactHandler::collectionRemoved(const Collection &collection) | ||||
488 | { | ||||
489 | Q_EMIT m_resource->status(AgentBase::Running, i18nc("@info:status", "Removing contact group '%1'", collection.displayName())); | ||||
490 | qCDebug(GOOGLE_CONTACTS_LOG) << "Removing contact group" << collection.remoteId(); | ||||
491 | auto job = new ContactsGroupDeleteJob(collection.remoteId(), m_settings->accountPtr(), this); | ||||
492 | job->setProperty(COLLECTION_PROPERTY, QVariant::fromValue(collection)); | ||||
493 | connect(job, &ContactsGroupDeleteJob::finished, m_resource, &GoogleResource::slotGenericJobFinished); | ||||
494 | } |