Akonadi Contacts

addemaildisplayjob.cpp
1 /*
2  SPDX-FileCopyrightText: 2013-2023 Laurent Montel <[email protected]>
3 
4  SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6 
7 #include "addemaildisplayjob.h"
8 #include "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>
27 using namespace Akonadi;
28 
29 class Akonadi::AddEmailDisplayJobPrivate
30 {
31 public:
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);
56  searchJob->setQuery(Akonadi::ContactSearchJob::Email, mEmail.toLower(), Akonadi::ContactSearchJob::ExactMatch);
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>()) {
66  auto address = item.payload<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 
272 AddEmailDisplayJob::AddEmailDisplayJob(const QString &email, QWidget *parentWidget, QObject *parent)
273  : KJob(parent)
274  , d(new AddEmailDisplayJobPrivate(this, email, parentWidget))
275 {
276 }
277 
278 AddEmailDisplayJob::~AddEmailDisplayJob() = default;
279 
280 void AddEmailDisplayJob::setShowAsHTML(bool html)
281 {
282  d->mShowAsHTML = html;
283 }
284 
285 void AddEmailDisplayJob::setRemoteContent(bool b)
286 {
287  d->mRemoteContent = b;
288 }
289 
290 void AddEmailDisplayJob::setContact(const Akonadi::Item &contact)
291 {
292  d->contact = contact;
293 }
294 
295 void AddEmailDisplayJob::setMessageId(Akonadi::Item::Id id)
296 {
297  d->messageId = id;
298 }
299 
300 void AddEmailDisplayJob::start()
301 {
302  if (d->contact.isValid()) {
303  d->modifyContact();
304  } else {
305  d->searchContact();
306  }
307 }
308 
309 #include "moc_addemaildisplayjob.cpp"
bool isValid() const
bool isEmpty() const const
Item::List items() const
virtual Q_SCRIPTABLE void start()=0
void result(KJob *job)
void append(const T &value)
void setMimeType(const QString &mimeType)
bool hasPayload() const
KGuiItem cancel()
Collection::List collections() const
static void parseEmailAddress(const QString &rawEmail, QString &fullName, QString &email)
The SelectAddressBookDialog class This class allows to select addressbook where saving contacts.
@ Email
The email address of the contact.
const T & at(int i) const const
QString errorText() const
PostalAddress address(const QVariant &location)
static QString mimeType()
KContacts::Addressee::List contacts() const
Returns the contacts that matched the search criteria.
ButtonCode questionTwoActions(QWidget *parent, const QString &text, const QString &title, const KGuiItem &primaryAction, const KGuiItem &secondaryAction, const QString &dontAskAgainName=QString(), Options options=Notify)
static Collection root()
Job that searches for contacts in the Akonadi storage.
void insertCustom(const QString &app, const QString &name, const QString &value)
void setNameFromString(const QString &s)
QStringList mimeTypes(Mode mode=Writing)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
void addEmail(const Email &email)
The AddEmailDisplayJob class.
int size() const const
bool isValid() const
void setPayload(const T &p)
int error() const
T payload() const
static QString mimeType()
@ ExactMatch
The result must match exactly the pattern (case sensitive).
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Sat Apr 1 2023 04:09:04 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.