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