Akonadi Contacts

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