File indexing completed on 2024-11-24 04:39:33
0001 /* 0002 SPDX-FileCopyrightText: 2010 Tobias Koenig <tokoe@kde.org> 0003 SPDX-FileCopyrightText: 2010 Nicolas Lécureuil <nicolas.lecureuil@free.fr> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include "addemailaddressjob.h" 0009 #include "widgets/selectaddressbookdialog.h" 0010 #include <Akonadi/AgentFilterProxyModel> 0011 #include <Akonadi/AgentInstanceCreateJob> 0012 #include <Akonadi/AgentType> 0013 #include <Akonadi/AgentTypeDialog> 0014 #include <Akonadi/Collection> 0015 #include <Akonadi/CollectionDialog> 0016 #include <Akonadi/CollectionFetchJob> 0017 #include <Akonadi/CollectionFetchScope> 0018 #include <Akonadi/ContactEditorDialog> 0019 #include <Akonadi/ContactSearchJob> 0020 #include <Akonadi/ItemCreateJob> 0021 #include <KContacts/ContactGroup> 0022 0023 #include <KLocalizedString> 0024 #include <KMessageBox> 0025 0026 #include <QPointer> 0027 0028 using namespace Akonadi; 0029 0030 class Akonadi::AddEmailAddressJobPrivate 0031 { 0032 public: 0033 AddEmailAddressJobPrivate(AddEmailAddressJob *qq, const QString &emailString, QWidget *parentWidget) 0034 : q(qq) 0035 , mCompleteAddress(emailString) 0036 , mParentWidget(parentWidget) 0037 , mInteractive(true) 0038 { 0039 KContacts::Addressee::parseEmailAddress(emailString, mName, mEmail); 0040 } 0041 0042 void slotResourceCreationDone(KJob *job) 0043 { 0044 if (job->error()) { 0045 q->setError(job->error()); 0046 q->setErrorText(job->errorText()); 0047 q->emitResult(); 0048 return; 0049 } 0050 createContact(); 0051 } 0052 0053 void slotSearchDone(KJob *job) 0054 { 0055 if (job->error()) { 0056 q->setError(job->error()); 0057 q->setErrorText(job->errorText()); 0058 q->emitResult(); 0059 return; 0060 } 0061 0062 const Akonadi::ContactSearchJob *searchJob = qobject_cast<Akonadi::ContactSearchJob *>(job); 0063 0064 const KContacts::Addressee::List contacts = searchJob->contacts(); 0065 if (!contacts.isEmpty()) { 0066 if (mInteractive) { 0067 const QString text = xi18nc("@info", 0068 "A contact with the email address <email>%1</email> " 0069 "is already in your address book.", 0070 mCompleteAddress); 0071 0072 KMessageBox::information(mParentWidget, text, QString(), QStringLiteral("alreadyInAddressBook")); 0073 } 0074 q->setError(KJob::UserDefinedError); 0075 q->emitResult(); 0076 return; 0077 } 0078 createContact(); 0079 } 0080 0081 void createContact() 0082 { 0083 const QStringList mimeTypes(KContacts::Addressee::mimeType()); 0084 0085 auto const addressBookJob = new Akonadi::CollectionFetchJob(Akonadi::Collection::root(), Akonadi::CollectionFetchJob::Recursive); 0086 0087 addressBookJob->fetchScope().setContentMimeTypes(mimeTypes); 0088 q->connect(addressBookJob, &Akonadi::CollectionFetchJob::result, q, [this](KJob *job) { 0089 slotCollectionsFetched(job); 0090 }); 0091 } 0092 0093 void slotCollectionsFetched(KJob *job) 0094 { 0095 if (job->error()) { 0096 q->setError(job->error()); 0097 q->setErrorText(job->errorText()); 0098 q->emitResult(); 0099 return; 0100 } 0101 0102 const Akonadi::CollectionFetchJob *addressBookJob = qobject_cast<Akonadi::CollectionFetchJob *>(job); 0103 0104 Akonadi::Collection::List canCreateItemCollections; 0105 0106 const Akonadi::Collection::List lstColls = addressBookJob->collections(); 0107 for (const Akonadi::Collection &collection : lstColls) { 0108 if (Akonadi::Collection::CanCreateItem & collection.rights()) { 0109 canCreateItemCollections.append(collection); 0110 } 0111 } 0112 0113 Akonadi::Collection addressBook; 0114 0115 const int nbItemCollection(canCreateItemCollections.size()); 0116 if (nbItemCollection == 0) { 0117 if (KMessageBox::questionTwoActions( 0118 mParentWidget, 0119 i18nc("@info", "You must create an address book before adding a contact. Do you want to create an address book?"), 0120 i18nc("@title:window", "No Address Book Available"), 0121 KGuiItem(i18nc("@action:button", "Create Address Book"), QStringLiteral("address-book-new")), 0122 KStandardGuiItem::cancel()) 0123 == KMessageBox::ButtonCode::PrimaryAction) { 0124 QPointer<Akonadi::AgentTypeDialog> dlg = new Akonadi::AgentTypeDialog(mParentWidget); 0125 dlg->setWindowTitle(i18nc("@title:window", "Add Address Book")); 0126 dlg->agentFilterProxyModel()->addMimeTypeFilter(KContacts::Addressee::mimeType()); 0127 dlg->agentFilterProxyModel()->addMimeTypeFilter(KContacts::ContactGroup::mimeType()); 0128 dlg->agentFilterProxyModel()->addCapabilityFilter(QStringLiteral("Resource")); 0129 0130 if (dlg->exec()) { 0131 const Akonadi::AgentType agentType = dlg->agentType(); 0132 0133 if (agentType.isValid()) { 0134 auto job = new Akonadi::AgentInstanceCreateJob(agentType, q); 0135 q->connect(job, &Akonadi::AgentInstanceCreateJob::result, q, [this](KJob *job) { 0136 slotResourceCreationDone(job); 0137 }); 0138 job->configure(mParentWidget); 0139 job->start(); 0140 delete dlg; 0141 return; 0142 } else { // if agent is not valid => return error and finish job 0143 q->setError(KJob::UserDefinedError); 0144 q->emitResult(); 0145 delete dlg; 0146 return; 0147 } 0148 } else { // Canceled create agent => return error and finish job 0149 q->setError(KJob::UserDefinedError); 0150 q->emitResult(); 0151 delete dlg; 0152 return; 0153 } 0154 } else { 0155 q->setError(KJob::UserDefinedError); 0156 q->emitResult(); 0157 return; 0158 } 0159 } else if (nbItemCollection == 1) { 0160 addressBook = canCreateItemCollections[0]; 0161 } else { 0162 // ask user in which address book the new contact shall be stored 0163 QPointer<Akonadi::SelectAddressBookDialog> dlg = new Akonadi::SelectAddressBookDialog(mParentWidget); 0164 0165 bool gotIt = true; 0166 if (dlg->exec()) { 0167 addressBook = dlg->selectedCollection(); 0168 } else { 0169 q->setError(KJob::UserDefinedError); 0170 q->emitResult(); 0171 gotIt = false; 0172 } 0173 delete dlg; 0174 if (!gotIt) { 0175 return; 0176 } 0177 } 0178 0179 if (!addressBook.isValid()) { 0180 q->setError(KJob::UserDefinedError); 0181 q->emitResult(); 0182 return; 0183 } 0184 KContacts::Addressee contact; 0185 contact.setNameFromString(mName); 0186 KContacts::Email email(mEmail); 0187 email.setPreferred(true); 0188 contact.addEmail(email); 0189 // create the new item 0190 Akonadi::Item item; 0191 item.setMimeType(KContacts::Addressee::mimeType()); 0192 item.setPayload<KContacts::Addressee>(contact); 0193 0194 // save the new item in akonadi storage 0195 auto createJob = new Akonadi::ItemCreateJob(item, addressBook, q); 0196 q->connect(createJob, &Akonadi::ItemCreateJob::result, q, [this](KJob *job) { 0197 slotAddContactDone(job); 0198 }); 0199 } 0200 0201 void slotAddContactDone(KJob *job) 0202 { 0203 if (job->error()) { 0204 q->setError(job->error()); 0205 q->setErrorText(job->errorText()); 0206 q->emitResult(); 0207 return; 0208 } 0209 0210 const Akonadi::ItemCreateJob *createJob = qobject_cast<Akonadi::ItemCreateJob *>(job); 0211 mItem = createJob->item(); 0212 0213 if (mInteractive) { 0214 const QString text = xi18nc("@info", 0215 "<para>A contact for \"%1\" was successfully added " 0216 "to your address book.</para>" 0217 "<para>Do you want to edit this new contact now?</para>", 0218 mCompleteAddress); 0219 0220 if (KMessageBox::questionTwoActions(mParentWidget, 0221 text, 0222 QString(), 0223 KGuiItem(i18nc("@action:button", "Edit"), QStringLiteral("document-edit")), 0224 KGuiItem(i18nc("@action:button", "Finish"), QStringLiteral("dialog-ok-apply")), 0225 QStringLiteral("addedtokabc")) 0226 == KMessageBox::ButtonCode::PrimaryAction) { 0227 QPointer<Akonadi::ContactEditorDialog> dlg = new Akonadi::ContactEditorDialog(Akonadi::ContactEditorDialog::EditMode, mParentWidget); 0228 dlg->setContact(mItem); 0229 QObject::connect(dlg.data(), &Akonadi::ContactEditorDialog::contactStored, q, [this](const Akonadi::Item &item) { 0230 contactStored(item); 0231 }); 0232 QObject::connect(dlg.data(), &Akonadi::ContactEditorDialog::error, q, [this](const QString &str) { 0233 slotContactEditorError(str); 0234 }); 0235 dlg->exec(); 0236 delete dlg; 0237 } 0238 } 0239 q->emitResult(); 0240 } 0241 0242 void slotContactEditorError(const QString &error) 0243 { 0244 if (mInteractive) { 0245 KMessageBox::error(mParentWidget, i18n("Contact cannot be stored: %1", error), i18nc("@title:window", "Failed to store contact")); 0246 } 0247 } 0248 0249 void contactStored(const Akonadi::Item &) 0250 { 0251 if (mInteractive) { 0252 Q_EMIT q->successMessage(i18n("Contact created successfully")); 0253 } 0254 } 0255 0256 AddEmailAddressJob *const q; 0257 const QString mCompleteAddress; 0258 QString mEmail; 0259 QString mName; 0260 QWidget *const mParentWidget; 0261 Akonadi::Item mItem; 0262 bool mInteractive = false; 0263 }; 0264 0265 AddEmailAddressJob::AddEmailAddressJob(const QString &email, QWidget *parentWidget, QObject *parent) 0266 : KJob(parent) 0267 , d(new AddEmailAddressJobPrivate(this, email, parentWidget)) 0268 { 0269 } 0270 0271 AddEmailAddressJob::~AddEmailAddressJob() = default; 0272 0273 void AddEmailAddressJob::start() 0274 { 0275 // first check whether a contact with the same email exists already 0276 auto searchJob = new Akonadi::ContactSearchJob(this); 0277 searchJob->setLimit(1); 0278 searchJob->setQuery(Akonadi::ContactSearchJob::Email, d->mEmail.toLower(), Akonadi::ContactSearchJob::ExactMatch); 0279 connect(searchJob, &Akonadi::ContactSearchJob::result, this, [this](KJob *job) { 0280 d->slotSearchDone(job); 0281 }); 0282 } 0283 0284 Akonadi::Item AddEmailAddressJob::contact() const 0285 { 0286 return d->mItem; 0287 } 0288 0289 void AddEmailAddressJob::setInteractive(bool b) 0290 { 0291 d->mInteractive = b; 0292 } 0293 0294 #include "moc_addemailaddressjob.cpp"