Akonadi Contacts

addemaildisplayjob.cpp
1 /*
2  SPDX-FileCopyrightText: 2013-2021 Laurent Montel <[email protected]>
3 
4  SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6 
7 #include "addemaildisplayjob.h"
8 #include "akonadi/contact/selectaddressbookdialog.h"
9 
10 #include <AgentFilterProxyModel>
11 #include <AgentInstanceCreateJob>
12 #include <AgentType>
13 #include <AgentTypeDialog>
14 #include <Akonadi/Contact/ContactEditorDialog>
15 #include <Akonadi/Contact/ContactSearchJob>
16 #include <Collection>
17 #include <CollectionDialog>
18 #include <CollectionFetchJob>
19 #include <CollectionFetchScope>
20 #include <Item>
21 #include <ItemCreateJob>
22 #include <ItemModifyJob>
23 
24 #include <KContacts/ContactGroup>
25 #include <KLocalizedString>
26 #include <KMessageBox>
27 
28 #include <QPointer>
29 
30 using namespace Akonadi;
31 
32 class Q_DECL_HIDDEN AddEmailDisplayJob::Private
33 {
34 public:
35  Private(AddEmailDisplayJob *qq, const QString &emailString, QWidget *parentWidget)
36  : q(qq)
37  , mCompleteAddress(emailString)
38  , mParentWidget(parentWidget)
39  {
40  KContacts::Addressee::parseEmailAddress(emailString, mName, mEmail);
41  }
42 
43  void slotResourceCreationDone(KJob *job)
44  {
45  if (job->error()) {
46  q->setError(job->error());
47  q->setErrorText(job->errorText());
48  q->emitResult();
49  return;
50  }
51  createContact();
52  }
53 
54  void searchContact()
55  {
56  // first check whether a contact with the same email exists already
57  auto searchJob = new Akonadi::ContactSearchJob(q);
58  searchJob->setLimit(1);
59  searchJob->setQuery(Akonadi::ContactSearchJob::Email, mEmail.toLower(), Akonadi::ContactSearchJob::ExactMatch);
60  q->connect(searchJob, &Akonadi::ContactSearchJob::result, q, [this](KJob *job) {
61  slotSearchDone(job);
62  });
63  }
64 
65  void modifyContact()
66  {
67  Akonadi::Item item = contact;
68  if (item.hasPayload<KContacts::Addressee>()) {
69  auto address = item.payload<KContacts::Addressee>();
70  address.insertCustom(QStringLiteral("KADDRESSBOOK"),
71  QStringLiteral("MailPreferedFormatting"),
72  mShowAsHTML ? QStringLiteral("HTML") : QStringLiteral("TEXT"));
73  address.insertCustom(QStringLiteral("KADDRESSBOOK"),
74  QStringLiteral("MailAllowToRemoteContent"),
75  mRemoteContent ? QStringLiteral("TRUE") : QStringLiteral("FALSE"));
77  auto itemModifyJob = new Akonadi::ItemModifyJob(item);
78  q->connect(itemModifyJob, &Akonadi::ItemModifyJob::result, q, [this](KJob *itemModifyJob) {
79  auto modifiedJob = static_cast<Akonadi::ItemModifyJob *>(itemModifyJob);
80  if (!modifiedJob->error()) {
81  Q_EMIT q->contactUpdated(modifiedJob->item(), messageId, mShowAsHTML, mRemoteContent);
82  }
83  slotAddModifyContactDone(itemModifyJob);
84  });
85  } else {
86  searchContact();
87  }
88  }
89 
90  void slotSearchDone(KJob *job)
91  {
92  if (job->error()) {
93  q->setError(job->error());
94  q->setErrorText(job->errorText());
95  q->emitResult();
96  return;
97  }
98 
99  const Akonadi::ContactSearchJob *searchJob = qobject_cast<Akonadi::ContactSearchJob *>(job);
100 
101  const Akonadi::Item::List items = searchJob->items();
102  if (items.isEmpty()) {
103  createContact();
104  } else {
105  Akonadi::Item item = items.at(0);
106  KContacts::Addressee contact = searchJob->contacts().at(0);
107  contact.insertCustom(QStringLiteral("KADDRESSBOOK"),
108  QStringLiteral("MailPreferedFormatting"),
109  mShowAsHTML ? QStringLiteral("HTML") : QStringLiteral("TEXT"));
110  contact.insertCustom(QStringLiteral("KADDRESSBOOK"),
111  QStringLiteral("MailAllowToRemoteContent"),
112  mRemoteContent ? QStringLiteral("TRUE") : QStringLiteral("FALSE"));
113  item.setPayload<KContacts::Addressee>(contact);
114  auto itemModifyJob = new Akonadi::ItemModifyJob(item);
115  q->connect(itemModifyJob, &Akonadi::ItemModifyJob::result, q, [this](KJob *itemModifyJob) {
116  auto modifiedJob = static_cast<Akonadi::ItemModifyJob *>(itemModifyJob);
117  if (!modifiedJob->error()) {
118  Q_EMIT q->contactUpdated(modifiedJob->item(), messageId, mShowAsHTML, mRemoteContent);
119  }
120  slotAddModifyContactDone(itemModifyJob);
121  });
122  }
123  }
124 
125  void createContact()
126  {
128 
130 
131  addressBookJob->fetchScope().setContentMimeTypes(mimeTypes);
132  q->connect(addressBookJob, &Akonadi::CollectionFetchJob::result, q, [this](KJob *job) {
133  slotCollectionsFetched(job);
134  });
135  }
136 
137  void slotCollectionsFetched(KJob *job)
138  {
139  if (job->error()) {
140  q->setError(job->error());
141  q->setErrorText(job->errorText());
142  q->emitResult();
143  return;
144  }
145 
146  const Akonadi::CollectionFetchJob *addressBookJob = qobject_cast<Akonadi::CollectionFetchJob *>(job);
147 
148  Akonadi::Collection::List canCreateItemCollections;
149  const Akonadi::Collection::List colsList = addressBookJob->collections();
150  for (const Akonadi::Collection &collection : colsList) {
151  if (Akonadi::Collection::CanCreateItem & collection.rights()) {
152  canCreateItemCollections.append(collection);
153  }
154  }
155 
156  Akonadi::Collection addressBook;
157 
158  const int nbItemCollection(canCreateItemCollections.size());
159  if (nbItemCollection == 0) {
160  if (KMessageBox::questionYesNo(mParentWidget,
161  i18nc("@info", "You must create an address book before adding a contact. Do you want to create an address book?"),
162  i18nc("@title:window", "No Address Book Available"))
163  == KMessageBox::Yes) {
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(UserDefinedError);
184  q->emitResult();
185  delete dlg;
186  return;
187  }
188  } else { // Canceled create agent => return error and finish job
189  q->setError(UserDefinedError);
190  q->emitResult();
191  delete dlg;
192  return;
193  }
194  } else {
195  q->setError(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(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(UserDefinedError);
221  q->emitResult();
222  return;
223  }
224  KContacts::Addressee contact;
225  contact.setNameFromString(mName);
226  contact.insertEmail(mEmail, true);
227  contact.insertCustom(QStringLiteral("KADDRESSBOOK"),
228  QStringLiteral("MailPreferedFormatting"),
229  mShowAsHTML ? QStringLiteral("HTML") : QStringLiteral("TEXT"));
230  contact.insertCustom(QStringLiteral("KADDRESSBOOK"),
231  QStringLiteral("MailAllowToRemoteContent"),
232  mRemoteContent ? QStringLiteral("TRUE") : QStringLiteral("FALSE"));
233 
234  // create the new item
235  Akonadi::Item item;
237  item.setPayload<KContacts::Addressee>(contact);
238 
239  // save the new item in akonadi storage
240  auto createJob = new Akonadi::ItemCreateJob(item, addressBook, q);
241  q->connect(createJob, &Akonadi::ItemCreateJob::result, q, [this](KJob *createJob) {
242  auto modifiedJob = static_cast<Akonadi::ItemCreateJob *>(createJob);
243  if (!modifiedJob->error()) {
244  Q_EMIT q->contactUpdated(modifiedJob->item(), messageId, mShowAsHTML, mRemoteContent);
245  }
246  slotAddModifyContactDone(createJob);
247  });
248  }
249 
250  void slotAddModifyContactDone(KJob *job)
251  {
252  if (job->error()) {
253  q->setError(job->error());
254  q->setErrorText(job->errorText());
255  }
256  q->emitResult();
257  }
258 
259  AddEmailDisplayJob *const q;
260  Akonadi::Item contact;
261  Akonadi::Item::Id messageId;
262  QString mCompleteAddress;
263  QString mEmail;
264  QString mName;
265  QWidget *const mParentWidget;
266  bool mShowAsHTML = false;
267  bool mRemoteContent = false;
268 };
269 
270 AddEmailDisplayJob::AddEmailDisplayJob(const QString &email, QWidget *parentWidget, QObject *parent)
271  : KJob(parent)
272  , d(new Private(this, email, parentWidget))
273 {
274 }
275 
276 AddEmailDisplayJob::~AddEmailDisplayJob()
277 {
278  delete d;
279 }
280 
281 void AddEmailDisplayJob::setShowAsHTML(bool html)
282 {
283  d->mShowAsHTML = html;
284 }
285 
286 void AddEmailDisplayJob::setRemoteContent(bool b)
287 {
288  d->mRemoteContent = b;
289 }
290 
291 void AddEmailDisplayJob::setContact(const Akonadi::Item &contact)
292 {
293  d->contact = contact;
294 }
295 
296 void AddEmailDisplayJob::setMessageId(Akonadi::Item::Id id)
297 {
298  d->messageId = id;
299 }
300 
301 void AddEmailDisplayJob::start()
302 {
303  if (d->contact.isValid()) {
304  d->modifyContact();
305  } else {
306  d->searchContact();
307  }
308 }
309 
310 #include "moc_addemaildisplayjob.cpp"
static QString mimeType()
Collection::List collections() const
bool isValid() const
void append(const T &value)
Item::List items() const
static void parseEmailAddress(const QString &rawEmail, QString &fullName, QString &email)
The SelectAddressBookDialog class This class allows to select addressbook where saving contacts...
bool isValid() const
void setPayload(const T &p)
T payload() const
void insertEmail(const QString &email, bool preferred=false, const QMap< QString, QStringList > &param=QMap< QString, QStringList >())
void setMimeType(const QString &mimeType)
PostalAddress address(const QVariant &location)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
static QString mimeType()
void setNameFromString(const QString &s)
Job that searches for contacts in the Akonadi storage.
static Collection root()
Akonadi::Item contact() const
Returns the item that represents the new contact.
QStringList mimeTypes(Types)
The email address of the contact.
ButtonCode questionYesNo(QWidget *parent, const QString &text, const QString &caption=QString(), const KGuiItem &buttonYes=KStandardGuiItem::yes(), const KGuiItem &buttonNo=KStandardGuiItem::no(), const QString &dontAskAgainName=QString(), Options options=Notify)
void insertCustom(const QString &app, const QString &name, const QString &value)
KContacts::Addressee::List contacts() const
Returns the contacts that matched the search criteria.
virtual Q_SCRIPTABLE void start()=0
void result(KJob *job)
bool hasPayload() const
The AddEmailDisplayJob class.
QString errorText() const
int error() const
The result must match exactly the pattern (case sensitive).
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Wed Jun 23 2021 23:09:24 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.