Akonadi Contacts

addemailaddressjob.cpp
1/*
2 SPDX-FileCopyrightText: 2010 Tobias Koenig <tokoe@kde.org>
3 SPDX-FileCopyrightText: 2010 Nicolas Lécureuil <nicolas.lecureuil@free.fr>
4
5 SPDX-License-Identifier: LGPL-2.0-or-later
6*/
7
8#include "addemailaddressjob.h"
9#include "widgets/selectaddressbookdialog.h"
10#include <Akonadi/AgentFilterProxyModel>
11#include <Akonadi/AgentInstanceCreateJob>
12#include <Akonadi/AgentType>
13#include <Akonadi/AgentTypeDialog>
14#include <Akonadi/Collection>
15#include <Akonadi/CollectionDialog>
16#include <Akonadi/CollectionFetchJob>
17#include <Akonadi/CollectionFetchScope>
18#include <Akonadi/ContactEditorDialog>
19#include <Akonadi/ContactSearchJob>
20#include <Akonadi/ItemCreateJob>
21#include <KContacts/ContactGroup>
22
23#include <KLocalizedString>
24#include <KMessageBox>
25
26#include <QPointer>
27
28using namespace Akonadi;
29
30class Akonadi::AddEmailAddressJobPrivate
31{
32public:
33 AddEmailAddressJobPrivate(AddEmailAddressJob *qq, const QString &emailString, QWidget *parentWidget)
34 : q(qq)
35 , mCompleteAddress(emailString)
36 , mParentWidget(parentWidget)
37 , mInteractive(true)
38 {
39 KContacts::Addressee::parseEmailAddress(emailString, mName, mEmail);
40 }
41
42 void slotResourceCreationDone(KJob *job)
43 {
44 if (job->error()) {
45 q->setError(job->error());
46 q->setErrorText(job->errorText());
47 q->emitResult();
48 return;
49 }
50 createContact();
51 }
52
53 void slotSearchDone(KJob *job)
54 {
55 if (job->error()) {
56 q->setError(job->error());
57 q->setErrorText(job->errorText());
58 q->emitResult();
59 return;
60 }
61
62 const Akonadi::ContactSearchJob *searchJob = qobject_cast<Akonadi::ContactSearchJob *>(job);
63
64 const KContacts::Addressee::List contacts = searchJob->contacts();
65 if (!contacts.isEmpty()) {
66 if (mInteractive) {
67 const QString text = xi18nc("@info",
68 "A contact with the email address <email>%1</email> "
69 "is already in your address book.",
70 mCompleteAddress);
71
72 KMessageBox::information(mParentWidget, text, QString(), QStringLiteral("alreadyInAddressBook"));
73 }
74 q->setError(KJob::UserDefinedError);
75 q->emitResult();
76 return;
77 }
78 createContact();
79 }
80
81 void createContact()
82 {
84
86
87 addressBookJob->fetchScope().setContentMimeTypes(mimeTypes);
88 q->connect(addressBookJob, &Akonadi::CollectionFetchJob::result, q, [this](KJob *job) {
89 slotCollectionsFetched(job);
90 });
91 }
92
93 void slotCollectionsFetched(KJob *job)
94 {
95 if (job->error()) {
96 q->setError(job->error());
97 q->setErrorText(job->errorText());
98 q->emitResult();
99 return;
100 }
101
102 const Akonadi::CollectionFetchJob *addressBookJob = qobject_cast<Akonadi::CollectionFetchJob *>(job);
103
104 Akonadi::Collection::List canCreateItemCollections;
105
106 const Akonadi::Collection::List lstColls = addressBookJob->collections();
107 for (const Akonadi::Collection &collection : lstColls) {
108 if (Akonadi::Collection::CanCreateItem & collection.rights()) {
109 canCreateItemCollections.append(collection);
110 }
111 }
112
113 Akonadi::Collection addressBook;
114
115 const int nbItemCollection(canCreateItemCollections.size());
116 if (nbItemCollection == 0) {
118 mParentWidget,
119 i18nc("@info", "You must create an address book before adding a contact. Do you want to create an address book?"),
120 i18nc("@title:window", "No Address Book Available"),
121 KGuiItem(i18nc("@action:button", "Create Address Book"), QStringLiteral("address-book-new")),
123 == KMessageBox::ButtonCode::PrimaryAction) {
125 dlg->setWindowTitle(i18nc("@title:window", "Add Address Book"));
126 dlg->agentFilterProxyModel()->addMimeTypeFilter(KContacts::Addressee::mimeType());
127 dlg->agentFilterProxyModel()->addMimeTypeFilter(KContacts::ContactGroup::mimeType());
128 dlg->agentFilterProxyModel()->addCapabilityFilter(QStringLiteral("Resource"));
129
130 if (dlg->exec()) {
131 const Akonadi::AgentType agentType = dlg->agentType();
132
133 if (agentType.isValid()) {
134 auto job = new Akonadi::AgentInstanceCreateJob(agentType, q);
135 q->connect(job, &Akonadi::AgentInstanceCreateJob::result, q, [this](KJob *job) {
136 slotResourceCreationDone(job);
137 });
138 job->configure(mParentWidget);
139 job->start();
140 delete dlg;
141 return;
142 } else { // if agent is not valid => return error and finish job
143 q->setError(KJob::UserDefinedError);
144 q->emitResult();
145 delete dlg;
146 return;
147 }
148 } else { // Canceled create agent => return error and finish job
149 q->setError(KJob::UserDefinedError);
150 q->emitResult();
151 delete dlg;
152 return;
153 }
154 } else {
155 q->setError(KJob::UserDefinedError);
156 q->emitResult();
157 return;
158 }
159 } else if (nbItemCollection == 1) {
160 addressBook = canCreateItemCollections[0];
161 } else {
162 // ask user in which address book the new contact shall be stored
164
165 bool gotIt = true;
166 if (dlg->exec()) {
167 addressBook = dlg->selectedCollection();
168 } else {
169 q->setError(KJob::UserDefinedError);
170 q->emitResult();
171 gotIt = false;
172 }
173 delete dlg;
174 if (!gotIt) {
175 return;
176 }
177 }
178
179 if (!addressBook.isValid()) {
180 q->setError(KJob::UserDefinedError);
181 q->emitResult();
182 return;
183 }
184 KContacts::Addressee contact;
185 contact.setNameFromString(mName);
186 KContacts::Email email(mEmail);
187 email.setPreferred(true);
188 contact.addEmail(email);
189 // create the new item
190 Akonadi::Item item;
192 item.setPayload<KContacts::Addressee>(contact);
193
194 // save the new item in akonadi storage
195 auto createJob = new Akonadi::ItemCreateJob(item, addressBook, q);
196 q->connect(createJob, &Akonadi::ItemCreateJob::result, q, [this](KJob *job) {
197 slotAddContactDone(job);
198 });
199 }
200
201 void slotAddContactDone(KJob *job)
202 {
203 if (job->error()) {
204 q->setError(job->error());
205 q->setErrorText(job->errorText());
206 q->emitResult();
207 return;
208 }
209
210 const Akonadi::ItemCreateJob *createJob = qobject_cast<Akonadi::ItemCreateJob *>(job);
211 mItem = createJob->item();
212
213 if (mInteractive) {
214 const QString text = xi18nc("@info",
215 "<para>A contact for \"%1\" was successfully added "
216 "to your address book.</para>"
217 "<para>Do you want to edit this new contact now?</para>",
218 mCompleteAddress);
219
220 if (KMessageBox::questionTwoActions(mParentWidget,
221 text,
222 QString(),
223 KGuiItem(i18nc("@action:button", "Edit"), QStringLiteral("document-edit")),
224 KGuiItem(i18nc("@action:button", "Finish"), QStringLiteral("dialog-ok-apply")),
225 QStringLiteral("addedtokabc"))
226 == KMessageBox::ButtonCode::PrimaryAction) {
228 dlg->setContact(mItem);
230 contactStored(item);
231 });
233 slotContactEditorError(str);
234 });
235 dlg->exec();
236 delete dlg;
237 }
238 }
239 q->emitResult();
240 }
241
242 void slotContactEditorError(const QString &error)
243 {
244 if (mInteractive) {
245 KMessageBox::error(mParentWidget, i18n("Contact cannot be stored: %1", error), i18nc("@title:window", "Failed to store contact"));
246 }
247 }
248
249 void contactStored(const Akonadi::Item &)
250 {
251 if (mInteractive) {
252 Q_EMIT q->successMessage(i18n("Contact created successfully"));
253 }
254 }
255
256 AddEmailAddressJob *const q;
257 const QString mCompleteAddress;
258 QString mEmail;
259 QString mName;
260 QWidget *const mParentWidget;
261 Akonadi::Item mItem;
262 bool mInteractive = false;
263};
264
266 : KJob(parent)
267 , d(new AddEmailAddressJobPrivate(this, email, parentWidget))
268{
269}
270
272
274{
275 // first check whether a contact with the same email exists already
276 auto searchJob = new Akonadi::ContactSearchJob(this);
277 searchJob->setLimit(1);
279 connect(searchJob, &Akonadi::ContactSearchJob::result, this, [this](KJob *job) {
280 d->slotSearchDone(job);
281 });
282}
283
285{
286 return d->mItem;
287}
288
289void AddEmailAddressJob::setInteractive(bool b)
290{
291 d->mInteractive = b;
292}
293
294#include "moc_addemailaddressjob.cpp"
A job to add a new contact with a given email address to Akonadi.
~AddEmailAddressJob() override
Destroys the add email address job.
void start() override
Starts the job.
Akonadi::Item contact() const
Returns the item that represents the new contact.
AddEmailAddressJob(const QString &email, QWidget *parentWidget, QObject *parent=nullptr)
Creates a new add email address job.
bool isValid() const
Collection::List collections() const
bool isValid() const
static Collection root()
A dialog for creating or editing a contact in Akonadi.
@ EditMode
Edits an existing contact.
void error(const QString &errMsg)
This signal is emitted whenever a contact is not updated or stored.
void contactStored(const Akonadi::Item &contact)
This signal is emitted whenever a contact was updated or stored.
Job that searches for contacts in the Akonadi storage.
void setQuery(Criterion criterion, const QString &value, Match match=ExactMatch)
Sets the criterion and value for the search with match.
@ 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.
void setLimit(int limit)
Sets a limit on how many results will be returned by this search job.
void setMimeType(const QString &mimeType)
void setPayload(const T &p)
The SelectAddressBookDialog class This class allows to select addressbook where saving contacts.
AddresseeList List
void setNameFromString(const QString &s)
void addEmail(const Email &email)
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 xi18nc(const char *context, const char *text, const TYPE &arg...)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
A widget for editing the display name of a contact.
void information(QWidget *parent, const QString &text, const QString &title=QString(), const QString &dontShowAgainName=QString(), Options options=Notify)
void error(QWidget *parent, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options=Notify)
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)
qsizetype size() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
T * data() 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.