Akonadi Contacts

addemaildisplayjob.cpp
1/*
2 SPDX-FileCopyrightText: 2013-2024 Laurent Montel <montel@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "addemaildisplayjob.h"
8#include "widgets/selectaddressbookdialog.h"
9#include <Akonadi/AgentFilterProxyModel>
10#include <Akonadi/AgentInstanceCreateJob>
11#include <Akonadi/AgentType>
12#include <Akonadi/AgentTypeDialog>
13#include <Akonadi/Collection>
14#include <Akonadi/CollectionDialog>
15#include <Akonadi/CollectionFetchJob>
16#include <Akonadi/CollectionFetchScope>
17#include <Akonadi/ContactEditorDialog>
18#include <Akonadi/ContactSearchJob>
19#include <Akonadi/ItemCreateJob>
20#include <Akonadi/ItemModifyJob>
21
22#include <KContacts/ContactGroup>
23#include <KLocalizedString>
24#include <KMessageBox>
25
26#include <QPointer>
27using namespace Akonadi;
28
29class Akonadi::AddEmailDisplayJobPrivate
30{
31public:
32 AddEmailDisplayJobPrivate(AddEmailDisplayJob *qq, const QString &emailString, QWidget *parentWidget)
33 : q(qq)
34 , mCompleteAddress(emailString)
35 , mParentWidget(parentWidget)
36 {
37 KContacts::Addressee::parseEmailAddress(emailString, mName, mEmail);
38 }
39
40 void slotResourceCreationDone(KJob *job)
41 {
42 if (job->error()) {
43 q->setError(job->error());
44 q->setErrorText(job->errorText());
45 q->emitResult();
46 return;
47 }
48 createContact();
49 }
50
51 void searchContact()
52 {
53 // first check whether a contact with the same email exists already
54 auto searchJob = new Akonadi::ContactSearchJob(q);
55 searchJob->setLimit(1);
57 q->connect(searchJob, &Akonadi::ContactSearchJob::result, q, [this](KJob *job) {
58 slotSearchDone(job);
59 });
60 }
61
62 void modifyContact()
63 {
64 Akonadi::Item item = contact;
65 if (item.hasPayload<KContacts::Addressee>()) {
67 address.insertCustom(QStringLiteral("KADDRESSBOOK"),
68 QStringLiteral("MailPreferedFormatting"),
69 mShowAsHTML ? QStringLiteral("HTML") : QStringLiteral("TEXT"));
70 address.insertCustom(QStringLiteral("KADDRESSBOOK"),
71 QStringLiteral("MailAllowToRemoteContent"),
72 mRemoteContent ? QStringLiteral("TRUE") : QStringLiteral("FALSE"));
74 auto itemModifyJob = new Akonadi::ItemModifyJob(item);
75 q->connect(itemModifyJob, &Akonadi::ItemModifyJob::result, q, [this](KJob *itemModifyJob) {
76 auto modifiedJob = static_cast<Akonadi::ItemModifyJob *>(itemModifyJob);
77 if (!modifiedJob->error()) {
78 Q_EMIT q->contactUpdated(modifiedJob->item(), messageId, mShowAsHTML, mRemoteContent);
79 }
80 slotAddModifyContactDone(itemModifyJob);
81 });
82 } else {
83 searchContact();
84 }
85 }
86
87 void slotSearchDone(KJob *job)
88 {
89 if (job->error()) {
90 q->setError(job->error());
91 q->setErrorText(job->errorText());
92 q->emitResult();
93 return;
94 }
95
96 const Akonadi::ContactSearchJob *searchJob = qobject_cast<Akonadi::ContactSearchJob *>(job);
97
98 const Akonadi::Item::List items = searchJob->items();
99 if (items.isEmpty()) {
100 createContact();
101 } else {
102 Akonadi::Item item = items.at(0);
103 KContacts::Addressee contact = searchJob->contacts().at(0);
104 contact.insertCustom(QStringLiteral("KADDRESSBOOK"),
105 QStringLiteral("MailPreferedFormatting"),
106 mShowAsHTML ? QStringLiteral("HTML") : QStringLiteral("TEXT"));
107 contact.insertCustom(QStringLiteral("KADDRESSBOOK"),
108 QStringLiteral("MailAllowToRemoteContent"),
109 mRemoteContent ? QStringLiteral("TRUE") : QStringLiteral("FALSE"));
110 item.setPayload<KContacts::Addressee>(contact);
111 auto itemModifyJob = new Akonadi::ItemModifyJob(item);
112 q->connect(itemModifyJob, &Akonadi::ItemModifyJob::result, q, [this](KJob *itemModifyJob) {
113 auto modifiedJob = static_cast<Akonadi::ItemModifyJob *>(itemModifyJob);
114 if (!modifiedJob->error()) {
115 Q_EMIT q->contactUpdated(modifiedJob->item(), messageId, mShowAsHTML, mRemoteContent);
116 }
117 slotAddModifyContactDone(itemModifyJob);
118 });
119 }
120 }
121
122 void createContact()
123 {
125
127
128 addressBookJob->fetchScope().setContentMimeTypes(mimeTypes);
129 q->connect(addressBookJob, &Akonadi::CollectionFetchJob::result, q, [this](KJob *job) {
130 slotCollectionsFetched(job);
131 });
132 }
133
134 void slotCollectionsFetched(KJob *job)
135 {
136 if (job->error()) {
137 q->setError(job->error());
138 q->setErrorText(job->errorText());
139 q->emitResult();
140 return;
141 }
142
143 const Akonadi::CollectionFetchJob *addressBookJob = qobject_cast<Akonadi::CollectionFetchJob *>(job);
144
145 Akonadi::Collection::List canCreateItemCollections;
146 const Akonadi::Collection::List colsList = addressBookJob->collections();
147 for (const Akonadi::Collection &collection : colsList) {
148 if (Akonadi::Collection::CanCreateItem & collection.rights()) {
149 canCreateItemCollections.append(collection);
150 }
151 }
152
153 Akonadi::Collection addressBook;
154
155 const int nbItemCollection(canCreateItemCollections.size());
156 if (nbItemCollection == 0) {
158 mParentWidget,
159 i18nc("@info", "You must create an address book before adding a contact. Do you want to create an address book?"),
160 i18nc("@title:window", "No Address Book Available"),
161 KGuiItem(i18nc("@action:button", "Create Address Book"), QStringLiteral("address-book-new")),
163 == KMessageBox::ButtonCode::PrimaryAction) {
165 dlg->setWindowTitle(i18nc("@title:window", "Add Address Book"));
166 dlg->agentFilterProxyModel()->addMimeTypeFilter(KContacts::Addressee::mimeType());
167 dlg->agentFilterProxyModel()->addMimeTypeFilter(KContacts::ContactGroup::mimeType());
168 dlg->agentFilterProxyModel()->addCapabilityFilter(QStringLiteral("Resource"));
169
170 if (dlg->exec()) {
171 const Akonadi::AgentType agentType = dlg->agentType();
172
173 if (agentType.isValid()) {
174 auto job = new Akonadi::AgentInstanceCreateJob(agentType, q);
175 q->connect(job, &Akonadi::AgentInstanceCreateJob::result, q, [this](KJob *job) {
176 slotResourceCreationDone(job);
177 });
178 job->configure(mParentWidget);
179 job->start();
180 delete dlg;
181 return;
182 } else { // if agent is not valid => return error and finish job
183 q->setError(KJob::UserDefinedError);
184 q->emitResult();
185 delete dlg;
186 return;
187 }
188 } else { // Canceled create agent => return error and finish job
189 q->setError(KJob::UserDefinedError);
190 q->emitResult();
191 delete dlg;
192 return;
193 }
194 } else {
195 q->setError(KJob::UserDefinedError);
196 q->emitResult();
197 return;
198 }
199 } else if (nbItemCollection == 1) {
200 addressBook = canCreateItemCollections[0];
201 } else {
202 // ask user in which address book the new contact shall be stored
204
205 bool gotIt = true;
206 if (dlg->exec()) {
207 addressBook = dlg->selectedCollection();
208 } else {
209 q->setError(KJob::UserDefinedError);
210 q->emitResult();
211 gotIt = false;
212 }
213 delete dlg;
214 if (!gotIt) {
215 return;
216 }
217 }
218
219 if (!addressBook.isValid()) {
220 q->setError(KJob::UserDefinedError);
221 q->emitResult();
222 return;
223 }
224 KContacts::Addressee contact;
225 contact.setNameFromString(mName);
226 KContacts::Email email(mEmail);
227 email.setPreferred(true);
228 contact.addEmail(email);
229 contact.insertCustom(QStringLiteral("KADDRESSBOOK"),
230 QStringLiteral("MailPreferedFormatting"),
231 mShowAsHTML ? QStringLiteral("HTML") : QStringLiteral("TEXT"));
232 contact.insertCustom(QStringLiteral("KADDRESSBOOK"),
233 QStringLiteral("MailAllowToRemoteContent"),
234 mRemoteContent ? QStringLiteral("TRUE") : QStringLiteral("FALSE"));
235
236 // create the new item
237 Akonadi::Item item;
239 item.setPayload<KContacts::Addressee>(contact);
240
241 // save the new item in akonadi storage
242 auto createJob = new Akonadi::ItemCreateJob(item, addressBook, q);
243 q->connect(createJob, &Akonadi::ItemCreateJob::result, q, [this](KJob *createJob) {
244 auto modifiedJob = static_cast<Akonadi::ItemCreateJob *>(createJob);
245 if (!modifiedJob->error()) {
246 Q_EMIT q->contactUpdated(modifiedJob->item(), messageId, mShowAsHTML, mRemoteContent);
247 }
248 slotAddModifyContactDone(createJob);
249 });
250 }
251
252 void slotAddModifyContactDone(KJob *job)
253 {
254 if (job->error()) {
255 q->setError(job->error());
256 q->setErrorText(job->errorText());
257 }
258 q->emitResult();
259 }
260
261 AddEmailDisplayJob *const q;
262 Akonadi::Item contact;
263 Akonadi::Item::Id messageId;
264 const QString mCompleteAddress;
265 QString mEmail;
266 QString mName;
267 QWidget *const mParentWidget;
268 bool mShowAsHTML = false;
269 bool mRemoteContent = false;
270};
271
272AddEmailDisplayJob::AddEmailDisplayJob(const QString &email, QWidget *parentWidget, QObject *parent)
273 : KJob(parent)
274 , d(new AddEmailDisplayJobPrivate(this, email, parentWidget))
275{
276}
277
278AddEmailDisplayJob::~AddEmailDisplayJob() = default;
279
280void AddEmailDisplayJob::setShowAsHTML(bool html)
281{
282 d->mShowAsHTML = html;
283}
284
285void AddEmailDisplayJob::setRemoteContent(bool b)
286{
287 d->mRemoteContent = b;
288}
289
290void AddEmailDisplayJob::setContact(const Akonadi::Item &contact)
291{
292 d->contact = contact;
293}
294
295void AddEmailDisplayJob::setMessageId(Akonadi::Item::Id id)
296{
297 d->messageId = id;
298}
299
300void AddEmailDisplayJob::start()
301{
302 if (d->contact.isValid()) {
303 d->modifyContact();
304 } else {
305 d->searchContact();
306 }
307}
308
309#include "moc_addemaildisplayjob.cpp"
The AddEmailDisplayJob class.
bool isValid() const
Collection::List collections() const
bool isValid() const
static Collection root()
Job that searches for contacts in the Akonadi storage.
@ ExactMatch
The result must match exactly the pattern (case sensitive).
@ Email
The email address of the contact.
KContacts::Addressee::List contacts() const
Returns the contacts that matched the search criteria.
Item::List items() const
T payload() const
void setMimeType(const QString &mimeType)
void setPayload(const T &p)
bool hasPayload() const
The SelectAddressBookDialog class This class allows to select addressbook where saving contacts.
void setNameFromString(const QString &s)
void addEmail(const Email &email)
void insertCustom(const QString &app, const QString &name, const QString &value)
static QString mimeType()
static void parseEmailAddress(const QString &rawEmail, QString &fullName, QString &email)
static QString mimeType()
void setErrorText(const QString &errorText)
void emitResult()
int error() const
void result(KJob *job)
void setError(int errorCode)
virtual Q_SCRIPTABLE void start()=0
QString errorText() const
QString i18nc(const char *context, const char *text, const TYPE &arg...)
A widget for editing the display name of a contact.
PostalAddress address(const QVariant &location)
ButtonCode questionTwoActions(QWidget *parent, const QString &text, const QString &title, const KGuiItem &primaryAction, const KGuiItem &secondaryAction, const QString &dontAskAgainName=QString(), Options options=Notify)
KGuiItem cancel()
void append(QList< T > &&value)
const_reference at(qsizetype i) const const
bool isEmpty() const const
qsizetype size() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QString toLower() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:13:20 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.