1 /*
2     This file is part of Akonadi Contact.
3 
4     SPDX-FileCopyrightText: 2009 Tobias Koenig <tokoe@kde.org>
5 
6     SPDX-License-Identifier: LGPL-2.0-or-later
7 */
8 
9 #include "contactgroupexpandjob.h"
10 #include "akonadi_contact_debug.h"
11 #include "job/contactgroupsearchjob.h"
12 #include <Akonadi/ItemFetchJob>
13 #include <Akonadi/ItemFetchScope>
14 #include <Akonadi/ItemSearchJob>
15 #include <kcontacts_version.h>
16 using namespace Akonadi;
17 
18 class Akonadi::ContactGroupExpandJobPrivate
19 {
20 public:
ContactGroupExpandJobPrivate(const KContacts::ContactGroup & group,ContactGroupExpandJob * parent)21     ContactGroupExpandJobPrivate(const KContacts::ContactGroup &group, ContactGroupExpandJob *parent)
22         : mParent(parent)
23         , mGroup(group)
24     {
25     }
26 
ContactGroupExpandJobPrivate(const QString & name,ContactGroupExpandJob * parent)27     ContactGroupExpandJobPrivate(const QString &name, ContactGroupExpandJob *parent)
28         : mParent(parent)
29         , mName(name)
30     {
31     }
32 
resolveGroup()33     void resolveGroup()
34     {
35         for (int i = 0, total = mGroup.dataCount(); i < total; ++i) {
36             const KContacts::ContactGroup::Data data = mGroup.data(i);
37 
38             KContacts::Addressee contact;
39             contact.setNameFromString(data.name());
40 #if KContacts_VERSION < QT_VERSION_CHECK(5, 88, 0)
41             contact.insertEmail(data.email(), true);
42 #else
43             KContacts::Email email(data.email());
44             email.setPreferred(true);
45             contact.addEmail(email);
46 #endif
47             mContacts.append(contact);
48         }
49 
50         for (int i = 0, total = mGroup.contactReferenceCount(); i < total; ++i) {
51             const KContacts::ContactGroup::ContactReference reference = mGroup.contactReference(i);
52 
53             Item item;
54             if (!reference.gid().isEmpty()) {
55                 item.setGid(reference.gid());
56             } else {
57                 item.setId(reference.uid().toLongLong());
58             }
59             auto job = new ItemFetchJob(item, mParent);
60             job->fetchScope().fetchFullPayload();
61             job->setProperty("preferredEmail", reference.preferredEmail());
62 
63             mParent->connect(job, &ItemFetchJob::result, mParent, [this](KJob *job) {
64                 fetchResult(job);
65             });
66 
67             mFetchCount++;
68         }
69 
70         if (mFetchCount == 0) { // nothing to fetch, so we can return immediately
71             mParent->emitResult();
72         }
73     }
74 
searchResult(KJob * job)75     void searchResult(KJob *job)
76     {
77         if (job->error()) {
78             mParent->setError(job->error());
79             mParent->setErrorText(job->errorText());
80             mParent->emitResult();
81             return;
82         }
83 
84         auto searchJob = qobject_cast<ContactGroupSearchJob *>(job);
85 
86         if (searchJob->contactGroups().isEmpty()) {
87             mParent->emitResult();
88             return;
89         }
90 
91         mGroup = searchJob->contactGroups().at(0);
92         resolveGroup();
93     }
94 
fetchResult(KJob * job)95     void fetchResult(KJob *job)
96     {
97         const ItemFetchJob *fetchJob = qobject_cast<ItemFetchJob *>(job);
98 
99         const Item::List items = fetchJob->items();
100         if (!items.isEmpty()) {
101             const QString preferredEmail = fetchJob->property("preferredEmail").toString();
102 
103             const Item item = items.first();
104             if (item.hasPayload<KContacts::Addressee>()) {
105                 auto contact = item.payload<KContacts::Addressee>();
106 #if KContacts_VERSION < QT_VERSION_CHECK(5, 88, 0)
107                 if (!preferredEmail.isEmpty()) {
108                     contact.insertEmail(preferredEmail, true);
109                 }
110 #else
111                 if (!preferredEmail.isEmpty()) {
112                     KContacts::Email email(preferredEmail);
113                     email.setPreferred(true);
114                     contact.addEmail(email);
115                 }
116 #endif
117                 mContacts.append(contact);
118             } else {
119                 qCWarning(AKONADICONTACT_LOG) << "Contact for Akonadi item" << item.id() << "does not exist anymore!";
120             }
121         }
122 
123         mFetchCount--;
124 
125         if (mFetchCount == 0) {
126             mParent->emitResult();
127         }
128     }
129 
130     ContactGroupExpandJob *const mParent;
131     KContacts::ContactGroup mGroup;
132     QString mName;
133     KContacts::Addressee::List mContacts;
134 
135     int mFetchCount = 0;
136 };
137 
ContactGroupExpandJob(const KContacts::ContactGroup & group,QObject * parent)138 ContactGroupExpandJob::ContactGroupExpandJob(const KContacts::ContactGroup &group, QObject *parent)
139     : KJob(parent)
140     , d(new ContactGroupExpandJobPrivate(group, this))
141 {
142 }
143 
ContactGroupExpandJob(const QString & name,QObject * parent)144 ContactGroupExpandJob::ContactGroupExpandJob(const QString &name, QObject *parent)
145     : KJob(parent)
146     , d(new ContactGroupExpandJobPrivate(name, this))
147 {
148 }
149 
150 ContactGroupExpandJob::~ContactGroupExpandJob() = default;
151 
start()152 void ContactGroupExpandJob::start()
153 {
154     if (!d->mName.isEmpty() && !d->mName.contains(QLatin1Char('@'))) {
155         // we have to search the contact group first
156         auto searchJob = new ContactGroupSearchJob(this);
157         searchJob->setQuery(ContactGroupSearchJob::Name, d->mName);
158         searchJob->setLimit(1);
159         connect(searchJob, &ContactGroupSearchJob::result, this, [this](KJob *job) {
160             d->searchResult(job);
161         });
162     } else {
163         QMetaObject::invokeMethod(
164             this,
165             [this]() {
166                 d->resolveGroup();
167             },
168             Qt::QueuedConnection);
169     }
170 }
171 
contacts() const172 KContacts::Addressee::List ContactGroupExpandJob::contacts() const
173 {
174     return d->mContacts;
175 }
176 
177 #include "moc_contactgroupexpandjob.cpp"
178