File indexing completed on 2024-11-24 04:50:41
0001 // SPDX-FileCopyrightText: 2007-2009 Tobias Koenig <tokoe@kde.org> 0002 // SPDX-FileCopyrightText: 2022 Carl Schwan <carl@carlschwan.eu> 0003 // SPDX-License-Identifier: LGPL-2.0-or-later 0004 0005 #include "contactgroupeditor.h" 0006 #include <qobjectdefs.h> 0007 0008 #include "contactgroupmodel.h" 0009 0010 #include <Akonadi/CollectionDialog> 0011 #include <Akonadi/CollectionFetchJob> 0012 #include <Akonadi/ItemCreateJob> 0013 #include <Akonadi/ItemFetchJob> 0014 #include <Akonadi/ItemFetchScope> 0015 #include <Akonadi/ItemModifyJob> 0016 #include <Akonadi/Monitor> 0017 #include <Akonadi/Session> 0018 #include <KColorScheme> 0019 #include <KContacts/ContactGroup> 0020 #include <KLocalizedString> 0021 0022 using namespace Akonadi; 0023 0024 class ContactGroupEditorPrivate 0025 { 0026 public: 0027 ContactGroupEditorPrivate(ContactGroupEditor *parent); 0028 ~ContactGroupEditorPrivate(); 0029 0030 void itemFetchDone(KJob *job); 0031 void parentCollectionFetchDone(KJob *job); 0032 void storeDone(KJob *job); 0033 void itemChanged(const Akonadi::Item &item, const QSet<QByteArray> ¬Used); 0034 void memberChanged(); 0035 0036 void loadContactGroup(const KContacts::ContactGroup &group); 0037 [[nodiscard]] bool storeContactGroup(KContacts::ContactGroup &group); 0038 void setupMonitor(); 0039 0040 ContactGroupEditor::Mode mMode = ContactGroupEditor::Mode::CreateMode; 0041 Item mItem; 0042 Collection mCollection; 0043 Collection mDefaultCollection; 0044 ContactGroupEditor *mParent = nullptr; 0045 ContactGroupModel *mGroupModel = nullptr; 0046 Monitor *mMonitor = nullptr; 0047 QString mName; 0048 bool mReadOnly = false; 0049 }; 0050 0051 ContactGroupEditorPrivate::ContactGroupEditorPrivate(ContactGroupEditor *parent) 0052 : mParent(parent) 0053 { 0054 } 0055 0056 ContactGroupEditorPrivate::~ContactGroupEditorPrivate() 0057 { 0058 delete mMonitor; 0059 } 0060 0061 void ContactGroupEditorPrivate::itemFetchDone(KJob *job) 0062 { 0063 if (job->error()) { 0064 return; 0065 } 0066 0067 auto fetchJob = qobject_cast<ItemFetchJob *>(job); 0068 if (!fetchJob) { 0069 return; 0070 } 0071 0072 if (fetchJob->items().isEmpty()) { 0073 return; 0074 } 0075 0076 mItem = fetchJob->items().at(0); 0077 0078 mParent->setReadOnly(false); 0079 if (mMode == ContactGroupEditor::EditMode) { 0080 // if in edit mode we have to fetch the parent collection to find out 0081 // about the modify rights of the item 0082 0083 auto collectionFetchJob = new Akonadi::CollectionFetchJob(mItem.parentCollection(), Akonadi::CollectionFetchJob::Base); 0084 mParent->connect(collectionFetchJob, &CollectionFetchJob::result, mParent, [this](KJob *job) { 0085 parentCollectionFetchDone(job); 0086 }); 0087 } else { 0088 const auto group = mItem.payload<KContacts::ContactGroup>(); 0089 loadContactGroup(group); 0090 } 0091 } 0092 0093 void ContactGroupEditorPrivate::parentCollectionFetchDone(KJob *job) 0094 { 0095 if (job->error()) { 0096 return; 0097 } 0098 0099 auto fetchJob = qobject_cast<Akonadi::CollectionFetchJob *>(job); 0100 if (!fetchJob) { 0101 return; 0102 } 0103 0104 const Akonadi::Collection parentCollection = fetchJob->collections().at(0); 0105 if (parentCollection.isValid()) { 0106 mReadOnly = !(parentCollection.rights() & Collection::CanChangeItem); 0107 } 0108 mCollection = parentCollection; 0109 Q_EMIT mParent->collectionChanged(); 0110 0111 const auto group = mItem.payload<KContacts::ContactGroup>(); 0112 loadContactGroup(group); 0113 0114 mParent->setReadOnly(mReadOnly); 0115 } 0116 0117 void ContactGroupEditorPrivate::storeDone(KJob *job) 0118 { 0119 if (job->error()) { 0120 Q_EMIT mParent->errorOccured(job->errorString()); 0121 return; 0122 } 0123 0124 if (mMode == ContactGroupEditor::EditMode) { 0125 Q_EMIT mParent->contactGroupStored(mItem); 0126 } else if (mMode == ContactGroupEditor::CreateMode) { 0127 Q_EMIT mParent->contactGroupStored(static_cast<ItemCreateJob *>(job)->item()); 0128 } 0129 Q_EMIT mParent->finished(); 0130 } 0131 0132 void ContactGroupEditor::fetchItem() 0133 { 0134 auto job = new ItemFetchJob(d->mItem); 0135 job->fetchScope().fetchFullPayload(); 0136 job->fetchScope().setAncestorRetrieval(Akonadi::ItemFetchScope::Parent); 0137 0138 connect(job, &ItemFetchJob::result, this, [this](KJob *job) { 0139 d->itemFetchDone(job); 0140 }); 0141 } 0142 0143 void ContactGroupEditorPrivate::loadContactGroup(const KContacts::ContactGroup &group) 0144 { 0145 mName = group.name(); 0146 Q_EMIT mParent->nameChanged(); 0147 0148 mGroupModel->loadContactGroup(group); 0149 } 0150 0151 bool ContactGroupEditorPrivate::storeContactGroup(KContacts::ContactGroup &group) 0152 { 0153 group.setName(mName); 0154 0155 if (!mGroupModel->storeContactGroup(group)) { 0156 Q_EMIT mParent->errorOccured(mGroupModel->lastErrorMessage()); 0157 return false; 0158 } 0159 0160 return true; 0161 } 0162 0163 void ContactGroupEditorPrivate::setupMonitor() 0164 { 0165 delete mMonitor; 0166 mMonitor = new Monitor; 0167 mMonitor->setObjectName(QLatin1StringView("ContactGroupEditorMonitor")); 0168 mMonitor->ignoreSession(Session::defaultSession()); 0169 0170 QObject::connect(mMonitor, &Monitor::itemChanged, mParent, [this](const Akonadi::Item &, const QSet<QByteArray> &) { 0171 Q_EMIT mParent->itemChanged(); 0172 }); 0173 } 0174 0175 ContactGroupEditor::ContactGroupEditor(QObject *parent) 0176 : QObject(parent) 0177 , d(new ContactGroupEditorPrivate(this)) 0178 { 0179 d->mMode = ContactGroupEditor::CreateMode; 0180 d->mGroupModel = new ContactGroupModel(true, this); 0181 KContacts::ContactGroup dummyGroup; 0182 d->mGroupModel->loadContactGroup(dummyGroup); 0183 } 0184 0185 ContactGroupEditor::~ContactGroupEditor() = default; 0186 0187 void ContactGroupEditor::loadContactGroup(const Akonadi::Item &item) 0188 { 0189 if (d->mMode == CreateMode) { 0190 Q_ASSERT_X(false, "ContactGroupEditor::loadContactGroup", "You are calling loadContactGroup in CreateMode!"); 0191 } 0192 0193 auto job = new ItemFetchJob(item); 0194 job->fetchScope().fetchFullPayload(); 0195 job->fetchScope().setAncestorRetrieval(Akonadi::ItemFetchScope::Parent); 0196 0197 connect(job, &ItemModifyJob::result, this, [this](KJob *job) { 0198 d->itemFetchDone(job); 0199 }); 0200 0201 d->setupMonitor(); 0202 d->mMonitor->setItemMonitored(item); 0203 } 0204 0205 bool ContactGroupEditor::saveContactGroup() 0206 { 0207 if (d->mMode == EditMode) { 0208 if (!d->mItem.isValid()) { 0209 return false; 0210 } 0211 0212 if (d->mReadOnly) { 0213 return true; 0214 } 0215 0216 auto group = d->mItem.payload<KContacts::ContactGroup>(); 0217 0218 if (!d->storeContactGroup(group)) { 0219 return false; 0220 } 0221 0222 d->mItem.setPayload<KContacts::ContactGroup>(group); 0223 0224 auto job = new ItemModifyJob(d->mItem); 0225 connect(job, &ItemModifyJob::result, this, [this](KJob *job) { 0226 d->storeDone(job); 0227 }); 0228 } else if (d->mMode == CreateMode) { 0229 if (!d->mDefaultCollection.isValid()) { 0230 const QStringList mimeTypeFilter(KContacts::ContactGroup::mimeType()); 0231 Q_EMIT errorOccured(i18n("No address book selected")); 0232 return false; 0233 0234 // TODO check if this can happen 0235 // QPointer<CollectionDialog> dlg = new CollectionDialog(this); 0236 // dlg->setMimeTypeFilter(mimeTypeFilter); 0237 // dlg->setAccessRightsFilter(Collection::CanCreateItem); 0238 // dlg->setWindowTitle(i18nc("@title:window", "Select Address Book")); 0239 // dlg->setDescription(i18n("Select the address book the new contact group shall be saved in:")); 0240 0241 // if (dlg->exec() == QDialog::Accepted) { 0242 // setDefaultAddressBook(dlg->selectedCollection()); 0243 // delete dlg; 0244 // } else { 0245 // delete dlg; 0246 // return false; 0247 // } 0248 } 0249 0250 KContacts::ContactGroup group; 0251 if (!d->storeContactGroup(group)) { 0252 return false; 0253 } 0254 0255 Item item; 0256 item.setPayload<KContacts::ContactGroup>(group); 0257 item.setMimeType(KContacts::ContactGroup::mimeType()); 0258 0259 auto job = new ItemCreateJob(item, d->mDefaultCollection); 0260 connect(job, &ItemCreateJob::result, this, [this](KJob *job) { 0261 d->storeDone(job); 0262 }); 0263 } 0264 0265 return true; 0266 } 0267 0268 void ContactGroupEditor::setDefaultAddressBook(const Akonadi::Collection &collection) 0269 { 0270 d->mDefaultCollection = collection; 0271 } 0272 0273 QString ContactGroupEditor::name() const 0274 { 0275 return d->mName; 0276 } 0277 0278 void ContactGroupEditor::setName(const QString &name) 0279 { 0280 if (d->mName == name) { 0281 return; 0282 } 0283 0284 d->mName = name; 0285 Q_EMIT nameChanged(); 0286 } 0287 0288 qint64 ContactGroupEditor::collectionId() const 0289 { 0290 return d->mCollection.isValid() ? d->mCollection.id() : d->mDefaultCollection.id(); 0291 } 0292 0293 ContactGroupEditor::Mode ContactGroupEditor::mode() const 0294 { 0295 return d->mMode; 0296 } 0297 0298 void ContactGroupEditor::setMode(Mode mode) 0299 { 0300 if (d->mMode == mode) { 0301 return; 0302 } 0303 d->mMode = mode; 0304 Q_EMIT modeChanged(); 0305 } 0306 0307 bool ContactGroupEditor::isReadOnly() const 0308 { 0309 return d->mReadOnly; 0310 } 0311 0312 void ContactGroupEditor::setReadOnly(bool isReadOnly) 0313 { 0314 if (d->mReadOnly == isReadOnly) { 0315 return; 0316 } 0317 d->mReadOnly = isReadOnly; 0318 Q_EMIT isReadOnlyChanged(); 0319 } 0320 0321 QAbstractItemModel *ContactGroupEditor::groupModel() const 0322 { 0323 return d->mGroupModel; 0324 } 0325 0326 #include "moc_contactgroupeditor.cpp"