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