File indexing completed on 2024-11-24 04:50:41
0001 // SPDX-FileCopyrightText: 2022 Carl Schwan <carl@carlschwan.eu> 0002 // SPDX-License-Identifier: LGPL-2.0-or-later 0003 0004 #include "contacteditorbackend.h" 0005 #include "addresseewrapper.h" 0006 #include "attributes/contactmetadataattribute_p.h" 0007 #include <Akonadi/CollectionDialog> 0008 #include <Akonadi/CollectionFetchJob> 0009 #include <Akonadi/ItemCreateJob> 0010 #include <Akonadi/ItemModifyJob> 0011 #include <Akonadi/Monitor> 0012 #include <Akonadi/Session> 0013 0014 ContactEditorBackend::ContactEditorBackend(QObject *parent) 0015 : QObject(parent) 0016 , m_mode(ContactEditorBackend::CreateMode) 0017 { 0018 } 0019 0020 ContactEditorBackend::~ContactEditorBackend() = default; 0021 0022 void ContactEditorBackend::setDefaultAddressBook(const Akonadi::Collection &addressbook) 0023 { 0024 m_defaultAddressBook = addressbook; 0025 } 0026 0027 void ContactEditorBackend::setCollectionId(const qint64 collectionId) 0028 { 0029 m_defaultAddressBook.setId(collectionId); 0030 } 0031 0032 AddresseeWrapper *ContactEditorBackend::contact() 0033 { 0034 if (m_addressee) { 0035 return m_addressee; 0036 } 0037 0038 m_addressee = new AddresseeWrapper(this); 0039 Q_EMIT contactChanged(); 0040 return m_addressee; 0041 } 0042 0043 ContactEditorBackend::Mode ContactEditorBackend::mode() const 0044 { 0045 return m_mode; 0046 } 0047 0048 void ContactEditorBackend::setMode(ContactEditorBackend::Mode mode) 0049 { 0050 if (m_mode == mode) { 0051 return; 0052 } 0053 m_mode = mode; 0054 Q_EMIT modeChanged(); 0055 } 0056 0057 Akonadi::Item ContactEditorBackend::item() const 0058 { 0059 return m_item; 0060 } 0061 0062 void ContactEditorBackend::setItem(const Akonadi::Item &item) 0063 { 0064 auto job = new Akonadi::ItemFetchJob(item); 0065 job->fetchScope().fetchFullPayload(); 0066 job->fetchScope().fetchAttribute<ContactMetaDataAttribute>(); 0067 job->fetchScope().setAncestorRetrieval(Akonadi::ItemFetchScope::Parent); 0068 0069 connect(job, &Akonadi::ItemFetchJob::result, this, [this](KJob *job) { 0070 itemFetchDone(job); 0071 }); 0072 0073 setupMonitor(); 0074 m_monitor->setItemMonitored(item); 0075 } 0076 0077 void ContactEditorBackend::setupMonitor() 0078 { 0079 delete m_monitor; 0080 m_monitor = new Akonadi::Monitor; 0081 m_monitor->setObjectName(QLatin1StringView("ContactEditorMonitor")); 0082 m_monitor->ignoreSession(Akonadi::Session::defaultSession()); 0083 0084 connect(m_monitor, &Akonadi::Monitor::itemChanged, this, [this](const Akonadi::Item &item, const QSet<QByteArray> &) { 0085 m_item = item; 0086 Q_EMIT itemChangedExternally(); 0087 }); 0088 } 0089 0090 void ContactEditorBackend::fetchItem() 0091 { 0092 auto job = new Akonadi::ItemFetchJob(m_item); 0093 job->fetchScope().fetchFullPayload(); 0094 job->fetchScope().fetchAttribute<ContactMetaDataAttribute>(); 0095 job->fetchScope().setAncestorRetrieval(Akonadi::ItemFetchScope::Parent); 0096 0097 connect(job, &Akonadi::ItemFetchJob::result, this, [this](KJob *job) { 0098 itemFetchDone(job); 0099 }); 0100 } 0101 0102 void ContactEditorBackend::itemFetchDone(KJob *job) 0103 { 0104 if (job->error() != KJob::NoError) { 0105 Q_EMIT errorOccured(job->errorString()); 0106 return; 0107 } 0108 0109 auto fetchJob = qobject_cast<Akonadi::ItemFetchJob *>(job); 0110 if (!fetchJob) { 0111 return; 0112 } 0113 0114 if (fetchJob->items().isEmpty()) { 0115 return; 0116 } 0117 0118 m_item = fetchJob->items().at(0); 0119 Q_EMIT itemChanged(); 0120 0121 setReadOnly(false); 0122 if (m_mode == ContactEditorBackend::EditMode) { 0123 // if in edit mode we have to fetch the parent collection to find out 0124 // about the modify rights of the item 0125 0126 auto collectionFetchJob = new Akonadi::CollectionFetchJob(m_item.parentCollection(), Akonadi::CollectionFetchJob::Base); 0127 this->connect(collectionFetchJob, &Akonadi::CollectionFetchJob::result, this, [this](KJob *job) { 0128 parentCollectionFetchDone(job); 0129 }); 0130 } else { 0131 const auto addr = m_item.payload<KContacts::Addressee>(); 0132 m_contactMetaData.load(m_item); 0133 contact()->setDisplayType((AddresseeWrapper::DisplayType)m_contactMetaData.displayNameMode()); 0134 contact()->setAddressee(m_item.payload<KContacts::Addressee>()); 0135 } 0136 Q_EMIT itemChanged(); 0137 Q_EMIT contactChanged(); 0138 } 0139 0140 void ContactEditorBackend::parentCollectionFetchDone(KJob *job) 0141 { 0142 if (job->error()) { 0143 Q_EMIT errorOccured(job->errorString()); 0144 return; 0145 } 0146 0147 auto fetchJob = qobject_cast<Akonadi::CollectionFetchJob *>(job); 0148 if (!fetchJob) { 0149 return; 0150 } 0151 0152 const Akonadi::Collection parentCollection = fetchJob->collections().at(0); 0153 if (parentCollection.isValid()) { 0154 setReadOnly(!(parentCollection.rights() & Akonadi::Collection::CanChangeItem)); 0155 m_defaultAddressBook = parentCollection; 0156 Q_EMIT collectionChanged(); 0157 } 0158 0159 m_contactMetaData.load(m_item); 0160 contact()->setDisplayType((AddresseeWrapper::DisplayType)m_contactMetaData.displayNameMode()); 0161 contact()->setAddressee(m_item.payload<KContacts::Addressee>()); 0162 } 0163 0164 qint64 ContactEditorBackend::collectionId() const 0165 { 0166 return m_defaultAddressBook.id(); 0167 } 0168 0169 void ContactEditorBackend::saveContactInAddressBook() 0170 { 0171 if (m_mode == EditMode) { 0172 if (!m_item.isValid() || m_readOnly) { 0173 qDebug() << "item not valid anymore"; 0174 return; 0175 } 0176 0177 auto addressee = m_addressee->addressee(); 0178 0179 storeContact(addressee, m_contactMetaData); 0180 0181 m_contactMetaData.store(m_item); 0182 0183 m_item.setPayload<KContacts::Addressee>(addressee); 0184 0185 auto job = new Akonadi::ItemModifyJob(m_item); 0186 connect(job, &Akonadi::ItemModifyJob::result, this, [this](KJob *job) { 0187 storeDone(job); 0188 }); 0189 } else if (m_mode == CreateMode) { 0190 Q_ASSERT(m_defaultAddressBook.isValid()); 0191 0192 KContacts::Addressee addr(m_addressee->addressee()); 0193 storeContact(addr, m_contactMetaData); 0194 0195 Akonadi::Item item; 0196 item.setPayload<KContacts::Addressee>(addr); 0197 item.setMimeType(KContacts::Addressee::mimeType()); 0198 0199 m_contactMetaData.store(item); 0200 0201 auto job = new Akonadi::ItemCreateJob(item, m_defaultAddressBook); 0202 connect(job, &Akonadi::ItemCreateJob::result, this, [this](KJob *job) { 0203 storeDone(job); 0204 }); 0205 } 0206 } 0207 0208 void ContactEditorBackend::storeDone(KJob *job) 0209 { 0210 if (job->error() != KJob::NoError) { 0211 Q_EMIT errorOccured(job->errorString()); 0212 return; 0213 } 0214 0215 if (m_mode == EditMode) { 0216 Q_EMIT contactStored(m_item); 0217 } else if (m_mode == CreateMode) { 0218 Q_EMIT contactStored(static_cast<Akonadi::ItemCreateJob *>(job)->item()); 0219 } 0220 Q_EMIT finished(); 0221 } 0222 0223 void ContactEditorBackend::storeContact(KContacts::Addressee &contact, ContactMetaData &metaData) const 0224 { 0225 // TODO custom fields group description support 0226 // metaData.setCustomFieldDescriptions(d->mCustomFieldsWidget->localCustomFieldDescriptions()); 0227 Q_UNUSED(contact) 0228 0229 metaData.setDisplayNameMode(m_addressee->displayType()); 0230 } 0231 0232 bool ContactEditorBackend::isReadOnly() const 0233 { 0234 return m_readOnly; 0235 } 0236 void ContactEditorBackend::setReadOnly(bool isReadOnly) 0237 { 0238 if (m_readOnly == isReadOnly) { 0239 return; 0240 } 0241 m_readOnly = isReadOnly; 0242 Q_EMIT isReadOnlyChanged(); 0243 } 0244 0245 #include "moc_contacteditorbackend.cpp"