File indexing completed on 2025-01-05 04:49:30
0001 /* 0002 SPDX-FileCopyrightText: 2016-2024 Laurent Montel <montel@kde.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "automaticaddcontactsjob.h" 0008 #include "automaticaddcontactsplugin_debug.h" 0009 #include <Akonadi/AgentFilterProxyModel> 0010 #include <Akonadi/AgentInstanceCreateJob> 0011 #include <Akonadi/AgentTypeDialog> 0012 #include <Akonadi/CollectionFetchJob> 0013 #include <Akonadi/CollectionFetchScope> 0014 #include <Akonadi/ContactSearchJob> 0015 #include <Akonadi/ItemCreateJob> 0016 #include <Akonadi/SelectAddressBookDialog> 0017 #include <KContacts/Addressee> 0018 #include <KContacts/ContactGroup> 0019 #include <KEmailAddress> 0020 #include <KLocalizedString> 0021 #include <KMessageBox> 0022 #include <PimCommon/PimUtil> 0023 #include <QPointer> 0024 0025 AutomaticAddContactsJob::AutomaticAddContactsJob(QObject *parent) 0026 : QObject(parent) 0027 { 0028 } 0029 0030 AutomaticAddContactsJob::~AutomaticAddContactsJob() = default; 0031 0032 void AutomaticAddContactsJob::start() 0033 { 0034 if (mEmails.isEmpty()) { 0035 deleteLaterAndEmitSignal(); 0036 return; 0037 } else { 0038 if (!mCollection.isValid()) { 0039 qCDebug(KMAIL_EDITOR_AUTOMATICADDCONTACTS_PLUGIN_LOG) << "Invalid collection"; 0040 deleteLaterAndEmitSignal(); 0041 return; 0042 } 0043 } 0044 mCurrentIndex = -1; 0045 fetchCollection(); 0046 } 0047 0048 void AutomaticAddContactsJob::fetchCollection() 0049 { 0050 auto const addressBookJob = new Akonadi::CollectionFetchJob(mCollection, Akonadi::CollectionFetchJob::Base); 0051 0052 const QStringList mimeTypes(KContacts::Addressee::mimeType()); 0053 addressBookJob->fetchScope().setContentMimeTypes(mimeTypes); 0054 connect(addressBookJob, &KJob::result, this, &AutomaticAddContactsJob::slotSelectedCollectionFetched); 0055 } 0056 0057 void AutomaticAddContactsJob::slotSelectedCollectionFetched(KJob *job) 0058 { 0059 if (job->error()) { 0060 // Collection not found. 0061 // fetch all collection 0062 const QStringList mimeTypes(KContacts::Addressee::mimeType()); 0063 0064 auto const addressBookJob = new Akonadi::CollectionFetchJob(Akonadi::Collection::root(), Akonadi::CollectionFetchJob::Recursive); 0065 0066 addressBookJob->fetchScope().setContentMimeTypes(mimeTypes); 0067 connect(addressBookJob, &KJob::result, this, &AutomaticAddContactsJob::slotFetchAllCollections); 0068 return; 0069 } 0070 const Akonadi::CollectionFetchJob *addressBookJob = qobject_cast<Akonadi::CollectionFetchJob *>(job); 0071 mCollection = addressBookJob->collections().at(0); 0072 addNextContact(); 0073 } 0074 0075 void AutomaticAddContactsJob::slotFetchAllCollections(KJob *job) 0076 { 0077 if (job->error()) { 0078 qCWarning(KMAIL_EDITOR_AUTOMATICADDCONTACTS_PLUGIN_LOG) << "Error during AutomaticAddContactsJob::slotFetchAllCollections : " << job->errorString(); 0079 deleteLaterAndEmitSignal(); 0080 return; 0081 } 0082 0083 const Akonadi::CollectionFetchJob *addressBookJob = qobject_cast<Akonadi::CollectionFetchJob *>(job); 0084 0085 Akonadi::Collection::List canCreateItemCollections; 0086 const Akonadi::Collection::List addressBookCollections = addressBookJob->collections(); 0087 for (const Akonadi::Collection &collection : addressBookCollections) { 0088 if (Akonadi::Collection::CanCreateItem & collection.rights()) { 0089 canCreateItemCollections.append(collection); 0090 } 0091 } 0092 Akonadi::Collection addressBook; 0093 0094 const int nbItemCollection(canCreateItemCollections.size()); 0095 if (nbItemCollection == 0) { 0096 if (KMessageBox::questionTwoActions(nullptr, 0097 i18nc("@info", "You must create an address book before adding a contact. Do you want to create an address book?"), 0098 i18nc("@title:window", "No Address Book Available"), 0099 KGuiItem(i18nc("@action:button", "Create Address Book"), QStringLiteral("address-book-new")), 0100 KStandardGuiItem::cancel()) 0101 == KMessageBox::ButtonCode::PrimaryAction) { 0102 QPointer<Akonadi::AgentTypeDialog> dlg = new Akonadi::AgentTypeDialog(nullptr); 0103 dlg->setWindowTitle(i18nc("@title:window", "Add Address Book")); 0104 dlg->agentFilterProxyModel()->addMimeTypeFilter(KContacts::Addressee::mimeType()); 0105 dlg->agentFilterProxyModel()->addMimeTypeFilter(KContacts::ContactGroup::mimeType()); 0106 dlg->agentFilterProxyModel()->addCapabilityFilter(QStringLiteral("Resource")); 0107 0108 if (dlg->exec()) { 0109 const Akonadi::AgentType agentType = dlg->agentType(); 0110 0111 if (agentType.isValid()) { 0112 auto createJob = new Akonadi::AgentInstanceCreateJob(agentType, this); 0113 connect(createJob, &KJob::result, this, &AutomaticAddContactsJob::slotResourceCreationDone); 0114 createJob->configure(); 0115 createJob->start(); 0116 delete dlg; 0117 return; 0118 } else { // if agent is not valid => return error and finish job 0119 deleteLaterAndEmitSignal(); 0120 delete dlg; 0121 return; 0122 } 0123 } else { // Canceled create agent => return error and finish job 0124 deleteLaterAndEmitSignal(); 0125 delete dlg; 0126 return; 0127 } 0128 } else { 0129 deleteLaterAndEmitSignal(); 0130 return; 0131 } 0132 } else if (nbItemCollection == 1) { 0133 addressBook = canCreateItemCollections[0]; 0134 } else { 0135 // ask user in which address book the new contact shall be stored 0136 QPointer<Akonadi::SelectAddressBookDialog> dlg = new Akonadi::SelectAddressBookDialog(nullptr); 0137 0138 bool gotIt = true; 0139 if (dlg->exec()) { 0140 addressBook = dlg->selectedCollection(); 0141 } else { 0142 gotIt = false; 0143 } 0144 delete dlg; 0145 if (!gotIt) { 0146 qCWarning(KMAIL_EDITOR_AUTOMATICADDCONTACTS_PLUGIN_LOG) << "Unable to selected Addressbook selected not valid"; 0147 deleteLaterAndEmitSignal(); 0148 return; 0149 } 0150 } 0151 0152 if (!addressBook.isValid()) { 0153 qCWarning(KMAIL_EDITOR_AUTOMATICADDCONTACTS_PLUGIN_LOG) << "Addressbook selected not valid"; 0154 deleteLaterAndEmitSignal(); 0155 return; 0156 } 0157 addNextContact(); 0158 } 0159 0160 void AutomaticAddContactsJob::slotResourceCreationDone(KJob *job) 0161 { 0162 if (job->error()) { 0163 qCWarning(KMAIL_EDITOR_AUTOMATICADDCONTACTS_PLUGIN_LOG) << "Unable to create resource:" << job->errorText(); 0164 deleteLaterAndEmitSignal(); 0165 return; 0166 } 0167 addNextContact(); 0168 } 0169 0170 void AutomaticAddContactsJob::verifyContactExist() 0171 { 0172 const QString email = mEmails.at(mCurrentIndex); 0173 QString tname; 0174 QString temail; 0175 KEmailAddress::extractEmailAddressAndName(email, temail, tname); 0176 if (temail.isEmpty()) { 0177 addNextContact(); 0178 } else { 0179 if (mProcessedEmails.contains(email)) { 0180 addNextContact(); 0181 } else { 0182 mProcessEmail = email; 0183 mName = tname; 0184 mProcessedEmails.append(email); 0185 auto searchJob = new Akonadi::ContactSearchJob(this); 0186 searchJob->setLimit(1); 0187 searchJob->setQuery(Akonadi::ContactSearchJob::Email, mProcessEmail.toLower(), Akonadi::ContactSearchJob::ExactMatch); 0188 connect(searchJob, &KJob::result, this, &AutomaticAddContactsJob::slotSearchDone); 0189 } 0190 } 0191 } 0192 0193 void AutomaticAddContactsJob::slotSearchDone(KJob *job) 0194 { 0195 auto searchJob = static_cast<Akonadi::ContactSearchJob *>(job); 0196 if (searchJob->error()) { 0197 qCWarning(KMAIL_EDITOR_AUTOMATICADDCONTACTS_PLUGIN_LOG) << "Unable to fetch contact:" << searchJob->errorText(); 0198 } else if (searchJob->contacts().isEmpty()) { 0199 KContacts::Addressee contact; 0200 contact.setNameFromString(mName); 0201 KContacts::Email email(mProcessEmail); 0202 email.setPreferred(true); 0203 contact.addEmail(email); 0204 0205 // create the new item 0206 Akonadi::Item item; 0207 item.setMimeType(KContacts::Addressee::mimeType()); 0208 item.setPayload<KContacts::Addressee>(contact); 0209 0210 // save the new item in akonadi storage 0211 auto createJob = new Akonadi::ItemCreateJob(item, mCollection, this); 0212 connect(createJob, &KJob::result, this, &AutomaticAddContactsJob::slotAddContactDone); 0213 return; 0214 } 0215 addNextContact(); 0216 } 0217 0218 void AutomaticAddContactsJob::slotAddContactDone(KJob *job) 0219 { 0220 if (job->error()) { 0221 qCWarning(KMAIL_EDITOR_AUTOMATICADDCONTACTS_PLUGIN_LOG) << "Error when add contact to addressbook:" << job->errorText(); 0222 } 0223 addNextContact(); 0224 } 0225 0226 void AutomaticAddContactsJob::addNextContact() 0227 { 0228 mCurrentIndex++; 0229 if (mCurrentIndex < mEmails.count()) { 0230 verifyContactExist(); 0231 } else { 0232 deleteLaterAndEmitSignal(); 0233 } 0234 } 0235 0236 void AutomaticAddContactsJob::setEmails(const QStringList &list) 0237 { 0238 mEmails = PimCommon::Util::generateEmailList(list); 0239 } 0240 0241 void AutomaticAddContactsJob::setCollection(const Akonadi::Collection &collection) 0242 { 0243 mCollection = collection; 0244 } 0245 0246 void AutomaticAddContactsJob::deleteLaterAndEmitSignal() 0247 { 0248 Q_EMIT finished(); 0249 deleteLater(); 0250 } 0251 0252 #include "moc_automaticaddcontactsjob.cpp"