File indexing completed on 2024-11-24 04:44:34
0001 /* This file is part of the KDE project 0002 SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net> 0003 SPDX-FileContributor: Kevin Krammer <krake@kdab.com> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include "abstractlocalstore.h" 0009 0010 #include "akonadifilestore_debug.h" 0011 #include "collectioncreatejob.h" 0012 #include "collectiondeletejob.h" 0013 #include "collectionfetchjob.h" 0014 #include "collectionmodifyjob.h" 0015 #include "collectionmovejob.h" 0016 #include "itemcreatejob.h" 0017 #include "itemdeletejob.h" 0018 #include "itemfetchjob.h" 0019 #include "itemmodifyjob.h" 0020 #include "itemmovejob.h" 0021 #include "sessionimpls_p.h" 0022 #include "storecompactjob.h" 0023 0024 #include <Akonadi/EntityDisplayAttribute> 0025 0026 #include <KLocalizedString> 0027 #include <QFileInfo> 0028 0029 using namespace Akonadi; 0030 0031 class JobProcessingAdaptor : public FileStore::Job::Visitor 0032 { 0033 public: 0034 explicit JobProcessingAdaptor(FileStore::AbstractJobSession *session) 0035 : mSession(session) 0036 { 0037 } 0038 0039 public: // Job::Visitor interface implementation 0040 bool visit(FileStore::Job *job) override 0041 { 0042 Q_UNUSED(job) 0043 return false; 0044 } 0045 0046 bool visit(FileStore::CollectionCreateJob *job) override 0047 { 0048 Q_UNUSED(job) 0049 return false; 0050 } 0051 0052 bool visit(FileStore::CollectionDeleteJob *job) override 0053 { 0054 Q_UNUSED(job) 0055 return false; 0056 } 0057 0058 bool visit(FileStore::CollectionFetchJob *job) override 0059 { 0060 Q_UNUSED(job) 0061 return false; 0062 } 0063 0064 bool visit(FileStore::CollectionModifyJob *job) override 0065 { 0066 Q_UNUSED(job) 0067 return false; 0068 } 0069 0070 bool visit(FileStore::CollectionMoveJob *job) override 0071 { 0072 Q_UNUSED(job) 0073 return false; 0074 } 0075 0076 bool visit(FileStore::ItemCreateJob *job) override 0077 { 0078 Q_UNUSED(job) 0079 return false; 0080 } 0081 0082 bool visit(FileStore::ItemDeleteJob *job) override 0083 { 0084 Q_UNUSED(job) 0085 return false; 0086 } 0087 0088 bool visit(FileStore::ItemFetchJob *job) override 0089 { 0090 Q_UNUSED(job) 0091 return false; 0092 } 0093 0094 bool visit(FileStore::ItemModifyJob *job) override 0095 { 0096 Q_UNUSED(job) 0097 return false; 0098 } 0099 0100 bool visit(FileStore::ItemMoveJob *job) override 0101 { 0102 Q_UNUSED(job) 0103 return false; 0104 } 0105 0106 bool visit(FileStore::StoreCompactJob *job) override 0107 { 0108 Q_UNUSED(job) 0109 return false; 0110 } 0111 0112 protected: 0113 FileStore::AbstractJobSession *mSession = nullptr; 0114 }; 0115 0116 class TopLevelCollectionFetcher : public JobProcessingAdaptor 0117 { 0118 public: 0119 explicit TopLevelCollectionFetcher(FileStore::AbstractJobSession *session) 0120 : JobProcessingAdaptor(session) 0121 { 0122 } 0123 0124 void setTopLevelCollection(const Collection &collection) 0125 { 0126 mTopLevelCollection = collection; 0127 } 0128 0129 public: 0130 using JobProcessingAdaptor::visit; 0131 0132 bool visit(FileStore::CollectionFetchJob *job) override 0133 { 0134 if (job->type() == FileStore::CollectionFetchJob::Base && job->collection().remoteId() == mTopLevelCollection.remoteId()) { 0135 mSession->notifyCollectionsReceived(job, Collection::List() << mTopLevelCollection); 0136 return true; 0137 } 0138 0139 return false; 0140 } 0141 0142 private: 0143 Collection mTopLevelCollection; 0144 }; 0145 0146 class CollectionsProcessedNotifier : public JobProcessingAdaptor 0147 { 0148 public: 0149 explicit CollectionsProcessedNotifier(FileStore::AbstractJobSession *session) 0150 : JobProcessingAdaptor(session) 0151 { 0152 } 0153 0154 void setCollections(const Collection::List &collections) 0155 { 0156 mCollections = collections; 0157 } 0158 0159 public: 0160 using JobProcessingAdaptor::visit; 0161 0162 bool visit(FileStore::CollectionCreateJob *job) override 0163 { 0164 Q_ASSERT(!mCollections.isEmpty()); 0165 if (mCollections.count() > 1) { 0166 qCCritical(AKONADIFILESTORE_LOG) << "Processing collections for CollectionCreateJob " 0167 "encountered more than one collection. Just processing the first one."; 0168 } 0169 0170 mSession->notifyCollectionCreated(job, mCollections[0]); 0171 return true; 0172 } 0173 0174 bool visit(FileStore::CollectionDeleteJob *job) override 0175 { 0176 Q_ASSERT(!mCollections.isEmpty()); 0177 if (mCollections.count() > 1) { 0178 qCCritical(AKONADIFILESTORE_LOG) << "Processing collections for CollectionDeleteJob " 0179 "encountered more than one collection. Just processing the first one."; 0180 } 0181 0182 mSession->notifyCollectionDeleted(job, mCollections[0]); 0183 return true; 0184 } 0185 0186 bool visit(FileStore::CollectionFetchJob *job) override 0187 { 0188 mSession->notifyCollectionsReceived(job, mCollections); 0189 return true; 0190 } 0191 0192 bool visit(FileStore::CollectionModifyJob *job) override 0193 { 0194 Q_ASSERT(!mCollections.isEmpty()); 0195 if (mCollections.count() > 1) { 0196 qCCritical(AKONADIFILESTORE_LOG) << "Processing collections for CollectionModifyJob " 0197 "encountered more than one collection. Just processing the first one."; 0198 } 0199 0200 mSession->notifyCollectionModified(job, mCollections[0]); 0201 return true; 0202 } 0203 0204 bool visit(FileStore::CollectionMoveJob *job) override 0205 { 0206 Q_ASSERT(!mCollections.isEmpty()); 0207 if (mCollections.count() > 1) { 0208 qCCritical(AKONADIFILESTORE_LOG) << "Processing collections for CollectionMoveJob " 0209 "encountered more than one collection. Just processing the first one."; 0210 } 0211 0212 mSession->notifyCollectionMoved(job, mCollections[0]); 0213 return true; 0214 } 0215 0216 bool visit(FileStore::StoreCompactJob *job) override 0217 { 0218 mSession->notifyCollectionsChanged(job, mCollections); 0219 return true; 0220 } 0221 0222 private: 0223 Collection::List mCollections; 0224 }; 0225 0226 class ItemsProcessedNotifier : public JobProcessingAdaptor 0227 { 0228 public: 0229 explicit ItemsProcessedNotifier(FileStore::AbstractJobSession *session) 0230 : JobProcessingAdaptor(session) 0231 { 0232 } 0233 0234 void setItems(const Item::List &items) 0235 { 0236 mItems = items; 0237 } 0238 0239 void clearItems() 0240 { 0241 mItems.clear(); 0242 } 0243 0244 public: 0245 using JobProcessingAdaptor::visit; 0246 0247 bool visit(FileStore::ItemCreateJob *job) override 0248 { 0249 Q_ASSERT(!mItems.isEmpty()); 0250 if (mItems.count() > 1) { 0251 qCCritical(AKONADIFILESTORE_LOG) << "Processing items for ItemCreateJob encountered more than one item. " 0252 "Just processing the first one."; 0253 } 0254 0255 mSession->notifyItemCreated(job, mItems[0]); 0256 return true; 0257 } 0258 0259 bool visit(FileStore::ItemFetchJob *job) override 0260 { 0261 mSession->notifyItemsReceived(job, mItems); 0262 return true; 0263 } 0264 0265 bool visit(FileStore::ItemModifyJob *job) override 0266 { 0267 Q_ASSERT(!mItems.isEmpty()); 0268 if (mItems.count() > 1) { 0269 qCCritical(AKONADIFILESTORE_LOG) << "Processing items for ItemModifyJob encountered more than one item. " 0270 "Just processing the first one."; 0271 } 0272 0273 mSession->notifyItemModified(job, mItems[0]); 0274 return true; 0275 } 0276 0277 bool visit(FileStore::ItemMoveJob *job) override 0278 { 0279 Q_ASSERT(!mItems.isEmpty()); 0280 if (mItems.count() > 1) { 0281 qCCritical(AKONADIFILESTORE_LOG) << "Processing items for ItemMoveJob encountered more than one item. " 0282 "Just processing the first one."; 0283 } 0284 0285 mSession->notifyItemMoved(job, mItems[0]); 0286 return true; 0287 } 0288 0289 bool visit(FileStore::StoreCompactJob *job) override 0290 { 0291 mSession->notifyItemsChanged(job, mItems); 0292 return true; 0293 } 0294 0295 private: 0296 Item::List mItems; 0297 }; 0298 0299 class FileStore::AbstractLocalStorePrivate 0300 { 0301 AbstractLocalStore *const q; 0302 0303 public: 0304 explicit AbstractLocalStorePrivate(FileStore::AbstractLocalStore *parent) 0305 : q(parent) 0306 , mSession(new FileStore::FiFoQueueJobSession(q)) 0307 , mCurrentJob(nullptr) 0308 , mTopLevelCollectionFetcher(mSession) 0309 , mCollectionsProcessedNotifier(mSession) 0310 , mItemsProcessedNotifier(mSession) 0311 { 0312 } 0313 0314 public: 0315 QFileInfo mPathFileInfo; 0316 Collection mTopLevelCollection; 0317 0318 FileStore::AbstractJobSession *mSession = nullptr; 0319 FileStore::Job *mCurrentJob = nullptr; 0320 0321 TopLevelCollectionFetcher mTopLevelCollectionFetcher; 0322 CollectionsProcessedNotifier mCollectionsProcessedNotifier; 0323 ItemsProcessedNotifier mItemsProcessedNotifier; 0324 0325 public: 0326 void processJobs(const QList<FileStore::Job *> &jobs); 0327 }; 0328 0329 void FileStore::AbstractLocalStorePrivate::processJobs(const QList<FileStore::Job *> &jobs) 0330 { 0331 for (FileStore::Job *job : jobs) { 0332 mCurrentJob = job; 0333 0334 if (job->error() == 0) { 0335 if (!job->accept(&mTopLevelCollectionFetcher)) { 0336 q->processJob(job); 0337 } 0338 } 0339 mSession->emitResult(job); 0340 mCurrentJob = nullptr; 0341 } 0342 } 0343 0344 FileStore::AbstractLocalStore::AbstractLocalStore() 0345 : QObject() 0346 , d(new AbstractLocalStorePrivate(this)) 0347 { 0348 connect(d->mSession, &AbstractJobSession::jobsReady, this, [this](const QList<FileStore::Job *> &jobs) { 0349 d->processJobs(jobs); 0350 }); 0351 } 0352 0353 FileStore::AbstractLocalStore::~AbstractLocalStore() = default; 0354 0355 void FileStore::AbstractLocalStore::setPath(const QString &path) 0356 { 0357 QFileInfo pathFileInfo(path); 0358 if (pathFileInfo.fileName().isEmpty()) { 0359 pathFileInfo = QFileInfo(pathFileInfo.path()); 0360 } 0361 pathFileInfo.makeAbsolute(); 0362 0363 if (pathFileInfo.absoluteFilePath() == d->mPathFileInfo.absoluteFilePath()) { 0364 return; 0365 } 0366 0367 d->mPathFileInfo = pathFileInfo; 0368 0369 Collection collection; 0370 collection.setRemoteId(d->mPathFileInfo.absoluteFilePath()); 0371 collection.setName(d->mPathFileInfo.fileName()); 0372 0373 auto attribute = collection.attribute<EntityDisplayAttribute>(); 0374 if (attribute) { 0375 attribute->setDisplayName(d->mPathFileInfo.fileName()); 0376 } 0377 0378 setTopLevelCollection(collection); 0379 } 0380 0381 QString FileStore::AbstractLocalStore::path() const 0382 { 0383 return d->mPathFileInfo.absoluteFilePath(); 0384 } 0385 0386 Collection FileStore::AbstractLocalStore::topLevelCollection() const 0387 { 0388 return d->mTopLevelCollection; 0389 } 0390 0391 FileStore::CollectionCreateJob *FileStore::AbstractLocalStore::createCollection(const Collection &collection, const Collection &targetParent) 0392 { 0393 auto job = new FileStore::CollectionCreateJob(collection, targetParent, d->mSession); 0394 0395 if (d->mTopLevelCollection.remoteId().isEmpty()) { 0396 const QString message = i18nc("@info:status", "Configured storage location is empty"); 0397 qCCritical(AKONADIFILESTORE_LOG) << message; 0398 qCCritical(AKONADIFILESTORE_LOG) << collection << targetParent; 0399 d->mSession->setError(job, FileStore::Job::InvalidStoreState, message); 0400 } else if (targetParent.remoteId().isEmpty()) { 0401 const QString message = i18nc("@info:status", "Given folder name is empty"); 0402 qCCritical(AKONADIFILESTORE_LOG) << message; 0403 qCCritical(AKONADIFILESTORE_LOG) << collection << targetParent; 0404 d->mSession->setError(job, FileStore::Job::InvalidJobContext, message); 0405 } else if ((targetParent.rights() & Collection::CanCreateCollection) == 0) { 0406 const QString message = i18nc("@info:status", "Access control prohibits folder creation in folder %1", targetParent.name()); 0407 qCCritical(AKONADIFILESTORE_LOG) << message; 0408 qCCritical(AKONADIFILESTORE_LOG) << collection << targetParent; 0409 d->mSession->setError(job, FileStore::Job::InvalidJobContext, message); 0410 } 0411 0412 int errorCode = 0; 0413 QString errorText; 0414 checkCollectionCreate(job, errorCode, errorText); 0415 if (errorCode != 0) { 0416 d->mSession->setError(job, errorCode, errorText); 0417 } 0418 0419 return job; 0420 } 0421 0422 FileStore::CollectionDeleteJob *FileStore::AbstractLocalStore::deleteCollection(const Collection &collection) 0423 { 0424 auto job = new FileStore::CollectionDeleteJob(collection, d->mSession); 0425 0426 if (d->mTopLevelCollection.remoteId().isEmpty()) { 0427 const QString message = i18nc("@info:status", "Configured storage location is empty"); 0428 qCCritical(AKONADIFILESTORE_LOG) << message; 0429 qCCritical(AKONADIFILESTORE_LOG) << collection; 0430 d->mSession->setError(job, FileStore::Job::InvalidStoreState, message); 0431 } else if (collection.remoteId().isEmpty() || collection.parentCollection().remoteId().isEmpty()) { 0432 const QString message = i18nc("@info:status", "Given folder name is empty"); 0433 qCCritical(AKONADIFILESTORE_LOG) << message; 0434 qCCritical(AKONADIFILESTORE_LOG) << collection; 0435 d->mSession->setError(job, FileStore::Job::InvalidJobContext, message); 0436 } else if ((collection.rights() & Collection::CanDeleteCollection) == 0) { 0437 const QString message = i18nc("@info:status", "Access control prohibits folder deletion in folder %1", collection.name()); 0438 qCCritical(AKONADIFILESTORE_LOG) << message; 0439 qCCritical(AKONADIFILESTORE_LOG) << collection; 0440 d->mSession->setError(job, FileStore::Job::InvalidJobContext, message); 0441 } 0442 0443 int errorCode = 0; 0444 QString errorText; 0445 checkCollectionDelete(job, errorCode, errorText); 0446 if (errorCode != 0) { 0447 d->mSession->setError(job, errorCode, errorText); 0448 } 0449 0450 return job; 0451 } 0452 0453 FileStore::CollectionFetchJob *FileStore::AbstractLocalStore::fetchCollections(const Collection &collection, FileStore::CollectionFetchJob::Type type) const 0454 { 0455 auto job = new FileStore::CollectionFetchJob(collection, type, d->mSession); 0456 0457 if (d->mTopLevelCollection.remoteId().isEmpty()) { 0458 const QString message = i18nc("@info:status", "Configured storage location is empty"); 0459 qCCritical(AKONADIFILESTORE_LOG) << message; 0460 qCCritical(AKONADIFILESTORE_LOG) << collection << "FetchType=" << type; 0461 d->mSession->setError(job, FileStore::Job::InvalidStoreState, message); 0462 } else if (collection.remoteId().isEmpty()) { 0463 const QString message = i18nc("@info:status", "Given folder name is empty"); 0464 qCCritical(AKONADIFILESTORE_LOG) << message; 0465 qCCritical(AKONADIFILESTORE_LOG) << collection << "FetchType=" << type; 0466 d->mSession->setError(job, FileStore::Job::InvalidJobContext, message); 0467 } 0468 0469 int errorCode = 0; 0470 QString errorText; 0471 checkCollectionFetch(job, errorCode, errorText); 0472 if (errorCode != 0) { 0473 d->mSession->setError(job, errorCode, errorText); 0474 } 0475 0476 return job; 0477 } 0478 0479 FileStore::CollectionModifyJob *FileStore::AbstractLocalStore::modifyCollection(const Collection &collection) 0480 { 0481 auto job = new FileStore::CollectionModifyJob(collection, d->mSession); 0482 0483 if (d->mTopLevelCollection.remoteId().isEmpty()) { 0484 const QString message = i18nc("@info:status", "Configured storage location is empty"); 0485 qCCritical(AKONADIFILESTORE_LOG) << message; 0486 qCCritical(AKONADIFILESTORE_LOG) << collection; 0487 d->mSession->setError(job, FileStore::Job::InvalidStoreState, message); 0488 } else if (collection.remoteId().isEmpty()) { 0489 const QString message = i18nc("@info:status", "Given folder name is empty"); 0490 qCCritical(AKONADIFILESTORE_LOG) << message; 0491 qCCritical(AKONADIFILESTORE_LOG) << collection; 0492 d->mSession->setError(job, FileStore::Job::InvalidJobContext, message); 0493 } else if ((collection.rights() & Collection::CanChangeCollection) == 0) { 0494 const QString message = i18nc("@info:status", "Access control prohibits folder modification in folder %1", collection.name()); 0495 qCCritical(AKONADIFILESTORE_LOG) << message; 0496 qCCritical(AKONADIFILESTORE_LOG) << collection; 0497 d->mSession->setError(job, FileStore::Job::InvalidJobContext, message); 0498 } 0499 0500 int errorCode = 0; 0501 QString errorText; 0502 checkCollectionModify(job, errorCode, errorText); 0503 if (errorCode != 0) { 0504 d->mSession->setError(job, errorCode, errorText); 0505 } 0506 0507 return job; 0508 } 0509 0510 FileStore::CollectionMoveJob *FileStore::AbstractLocalStore::moveCollection(const Collection &collection, const Collection &targetParent) 0511 { 0512 auto job = new FileStore::CollectionMoveJob(collection, targetParent, d->mSession); 0513 0514 if (d->mTopLevelCollection.remoteId().isEmpty()) { 0515 const QString message = i18nc("@info:status", "Configured storage location is empty"); 0516 qCCritical(AKONADIFILESTORE_LOG) << message; 0517 qCCritical(AKONADIFILESTORE_LOG) << collection << targetParent; 0518 d->mSession->setError(job, FileStore::Job::InvalidStoreState, message); 0519 } else if (collection.remoteId().isEmpty() || collection.parentCollection().remoteId().isEmpty() || targetParent.remoteId().isEmpty()) { 0520 const QString message = i18nc("@info:status", "Given folder name is empty"); 0521 qCCritical(AKONADIFILESTORE_LOG) << message; 0522 qCCritical(AKONADIFILESTORE_LOG) << collection << targetParent; 0523 d->mSession->setError(job, FileStore::Job::InvalidJobContext, message); 0524 } else if ((targetParent.rights() & Collection::CanCreateCollection) == 0) { 0525 const QString message = i18nc("@info:status", "Access control prohibits folder creation in folder %1", targetParent.name()); 0526 qCCritical(AKONADIFILESTORE_LOG) << message; 0527 qCCritical(AKONADIFILESTORE_LOG) << collection << targetParent; 0528 d->mSession->setError(job, FileStore::Job::InvalidJobContext, message); 0529 } 0530 0531 int errorCode = 0; 0532 QString errorText; 0533 checkCollectionMove(job, errorCode, errorText); 0534 if (errorCode != 0) { 0535 d->mSession->setError(job, errorCode, errorText); 0536 } 0537 0538 return job; 0539 } 0540 0541 FileStore::ItemFetchJob *FileStore::AbstractLocalStore::fetchItems(const Collection &collection) const 0542 { 0543 auto job = new FileStore::ItemFetchJob(collection, d->mSession); 0544 0545 if (d->mTopLevelCollection.remoteId().isEmpty()) { 0546 const QString message = i18nc("@info:status", "Configured storage location is empty"); 0547 qCCritical(AKONADIFILESTORE_LOG) << message; 0548 qCCritical(AKONADIFILESTORE_LOG) << collection; 0549 d->mSession->setError(job, FileStore::Job::InvalidStoreState, message); 0550 } else if (collection.remoteId().isEmpty()) { 0551 const QString message = i18nc("@info:status", "Given folder name is empty"); 0552 qCCritical(AKONADIFILESTORE_LOG) << message; 0553 qCCritical(AKONADIFILESTORE_LOG) << collection; 0554 d->mSession->setError(job, FileStore::Job::InvalidJobContext, message); 0555 } 0556 0557 int errorCode = 0; 0558 QString errorText; 0559 checkItemFetch(job, errorCode, errorText); 0560 if (errorCode != 0) { 0561 d->mSession->setError(job, errorCode, errorText); 0562 } 0563 0564 return job; 0565 } 0566 0567 FileStore::ItemFetchJob *FileStore::AbstractLocalStore::fetchItems(const Item::List &items) const 0568 { 0569 auto job = new FileStore::ItemFetchJob(items, d->mSession); 0570 0571 if (items.size() == 1) { 0572 const Akonadi::Item &item = items[0]; 0573 if (d->mTopLevelCollection.remoteId().isEmpty()) { 0574 const QString message = i18nc("@info:status", "Configured storage location is empty"); 0575 qCCritical(AKONADIFILESTORE_LOG) << message; 0576 qCCritical(AKONADIFILESTORE_LOG) << "Item(remoteId=" << item.remoteId() << ", mimeType=" << item.mimeType() 0577 << ", parentCollection=" << item.parentCollection().remoteId() << ")"; 0578 d->mSession->setError(job, FileStore::Job::InvalidStoreState, message); 0579 } else if (item.remoteId().isEmpty()) { 0580 const QString message = i18nc("@info:status", "Given item identifier is empty"); 0581 qCCritical(AKONADIFILESTORE_LOG) << message; 0582 qCCritical(AKONADIFILESTORE_LOG) << "Item(remoteId=" << item.remoteId() << ", mimeType=" << item.mimeType() 0583 << ", parentCollection=" << item.parentCollection().remoteId() << ")"; 0584 d->mSession->setError(job, FileStore::Job::InvalidJobContext, message); 0585 } 0586 } 0587 0588 int errorCode = 0; 0589 QString errorText; 0590 checkItemFetch(job, errorCode, errorText); 0591 if (errorCode != 0) { 0592 d->mSession->setError(job, errorCode, errorText); 0593 } 0594 0595 return job; 0596 } 0597 0598 FileStore::ItemFetchJob *FileStore::AbstractLocalStore::fetchItem(const Item &item) const 0599 { 0600 return fetchItems({item}); 0601 } 0602 0603 FileStore::ItemCreateJob *FileStore::AbstractLocalStore::createItem(const Item &item, const Collection &collection) 0604 { 0605 auto job = new FileStore::ItemCreateJob(item, collection, d->mSession); 0606 0607 if (d->mTopLevelCollection.remoteId().isEmpty()) { 0608 const QString message = i18nc("@info:status", "Configured storage location is empty"); 0609 qCCritical(AKONADIFILESTORE_LOG) << message; 0610 qCCritical(AKONADIFILESTORE_LOG) << collection << "Item(remoteId=" << item.remoteId() << ", mimeType=" << item.mimeType() << ")"; 0611 d->mSession->setError(job, FileStore::Job::InvalidStoreState, message); 0612 } else if (collection.remoteId().isEmpty()) { 0613 const QString message = i18nc("@info:status", "Given folder name is empty"); 0614 qCCritical(AKONADIFILESTORE_LOG) << message; 0615 qCCritical(AKONADIFILESTORE_LOG) << collection << "Item(remoteId=" << item.remoteId() << ", mimeType=" << item.mimeType() << ")"; 0616 d->mSession->setError(job, FileStore::Job::InvalidJobContext, message); 0617 } else if ((collection.rights() & Collection::CanCreateItem) == 0) { 0618 const QString message = i18nc("@info:status", "Access control prohibits item creation in folder %1", collection.name()); 0619 qCCritical(AKONADIFILESTORE_LOG) << message; 0620 qCCritical(AKONADIFILESTORE_LOG) << collection << "Item(remoteId=" << item.remoteId() << ", mimeType=" << item.mimeType() << ")"; 0621 d->mSession->setError(job, FileStore::Job::InvalidJobContext, message); 0622 } 0623 0624 int errorCode = 0; 0625 QString errorText; 0626 checkItemCreate(job, errorCode, errorText); 0627 if (errorCode != 0) { 0628 d->mSession->setError(job, errorCode, errorText); 0629 } 0630 0631 return job; 0632 } 0633 0634 FileStore::ItemModifyJob *FileStore::AbstractLocalStore::modifyItem(const Item &item) 0635 { 0636 auto job = new FileStore::ItemModifyJob(item, d->mSession); 0637 0638 if (d->mTopLevelCollection.remoteId().isEmpty()) { 0639 const QString message = i18nc("@info:status", "Configured storage location is empty"); 0640 qCCritical(AKONADIFILESTORE_LOG) << message; 0641 qCCritical(AKONADIFILESTORE_LOG) << "Item(remoteId=" << item.remoteId() << ", mimeType=" << item.mimeType() 0642 << ", parentCollection=" << item.parentCollection().remoteId() << ")"; 0643 d->mSession->setError(job, FileStore::Job::InvalidStoreState, message); 0644 } else if (item.remoteId().isEmpty()) { 0645 const QString message = i18nc("@info:status", "Given item identifier is empty"); 0646 qCCritical(AKONADIFILESTORE_LOG) << message; 0647 qCCritical(AKONADIFILESTORE_LOG) << "Item(remoteId=" << item.remoteId() << ", mimeType=" << item.mimeType() 0648 << ", parentCollection=" << item.parentCollection().remoteId() << ")"; 0649 d->mSession->setError(job, FileStore::Job::InvalidJobContext, message); 0650 } else if ((item.parentCollection().rights() & Collection::CanChangeItem) == 0) { 0651 const QString message = i18nc("@info:status", "Access control prohibits item modification in folder %1", item.parentCollection().name()); 0652 qCCritical(AKONADIFILESTORE_LOG) << message; 0653 qCCritical(AKONADIFILESTORE_LOG) << "Item(remoteId=" << item.remoteId() << ", mimeType=" << item.mimeType() 0654 << ", parentCollection=" << item.parentCollection().remoteId() << ")"; 0655 d->mSession->setError(job, FileStore::Job::InvalidJobContext, message); 0656 } 0657 0658 int errorCode = 0; 0659 QString errorText; 0660 checkItemModify(job, errorCode, errorText); 0661 if (errorCode != 0) { 0662 d->mSession->setError(job, errorCode, errorText); 0663 } 0664 0665 return job; 0666 } 0667 0668 FileStore::ItemDeleteJob *FileStore::AbstractLocalStore::deleteItem(const Item &item) 0669 { 0670 auto job = new FileStore::ItemDeleteJob(item, d->mSession); 0671 0672 if (d->mTopLevelCollection.remoteId().isEmpty()) { 0673 const QString message = i18nc("@info:status", "Configured storage location is empty"); 0674 qCCritical(AKONADIFILESTORE_LOG) << message; 0675 qCCritical(AKONADIFILESTORE_LOG) << "Item(remoteId=" << item.remoteId() << ", mimeType=" << item.mimeType() 0676 << ", parentCollection=" << item.parentCollection().remoteId() << ")"; 0677 d->mSession->setError(job, FileStore::Job::InvalidStoreState, message); 0678 } else if (item.remoteId().isEmpty()) { 0679 const QString message = i18nc("@info:status", "Given item identifier is empty"); 0680 qCCritical(AKONADIFILESTORE_LOG) << message; 0681 qCCritical(AKONADIFILESTORE_LOG) << "Item(remoteId=" << item.remoteId() << ", mimeType=" << item.mimeType() 0682 << ", parentCollection=" << item.parentCollection().remoteId() << ")"; 0683 d->mSession->setError(job, FileStore::Job::InvalidJobContext, message); 0684 } else if ((item.parentCollection().rights() & Collection::CanDeleteItem) == 0) { 0685 const QString message = i18nc("@info:status", "Access control prohibits item deletion in folder %1", item.parentCollection().name()); 0686 qCCritical(AKONADIFILESTORE_LOG) << message; 0687 qCCritical(AKONADIFILESTORE_LOG) << "Item(remoteId=" << item.remoteId() << ", mimeType=" << item.mimeType() 0688 << ", parentCollection=" << item.parentCollection().remoteId() << ")"; 0689 d->mSession->setError(job, FileStore::Job::InvalidJobContext, message); 0690 } 0691 0692 int errorCode = 0; 0693 QString errorText; 0694 checkItemDelete(job, errorCode, errorText); 0695 if (errorCode != 0) { 0696 d->mSession->setError(job, errorCode, errorText); 0697 } 0698 0699 return job; 0700 } 0701 0702 FileStore::ItemMoveJob *FileStore::AbstractLocalStore::moveItem(const Item &item, const Collection &targetParent) 0703 { 0704 auto job = new FileStore::ItemMoveJob(item, targetParent, d->mSession); 0705 0706 if (d->mTopLevelCollection.remoteId().isEmpty()) { 0707 const QString message = i18nc("@info:status", "Configured storage location is empty"); 0708 qCCritical(AKONADIFILESTORE_LOG) << message; 0709 qCCritical(AKONADIFILESTORE_LOG) << "Item(remoteId=" << item.remoteId() << ", mimeType=" << item.mimeType() 0710 << ", parentCollection=" << item.parentCollection().remoteId() << ")" << targetParent; 0711 d->mSession->setError(job, FileStore::Job::InvalidStoreState, message); 0712 } else if (item.parentCollection().remoteId().isEmpty() || targetParent.remoteId().isEmpty()) { 0713 const QString message = i18nc("@info:status", "Given folder name is empty"); 0714 qCCritical(AKONADIFILESTORE_LOG) << message; 0715 qCCritical(AKONADIFILESTORE_LOG) << "Item(remoteId=" << item.remoteId() << ", mimeType=" << item.mimeType() 0716 << ", parentCollection=" << item.parentCollection().remoteId() << ")" << targetParent; 0717 d->mSession->setError(job, FileStore::Job::InvalidJobContext, message); 0718 } else if ((targetParent.rights() & Collection::CanCreateItem) == 0) { 0719 const QString message = i18nc("@info:status", "Access control prohibits item creation in folder %1", targetParent.name()); 0720 qCCritical(AKONADIFILESTORE_LOG) << message; 0721 qCCritical(AKONADIFILESTORE_LOG) << "Item(remoteId=" << item.remoteId() << ", mimeType=" << item.mimeType() 0722 << ", parentCollection=" << item.parentCollection().remoteId() << ")" << targetParent; 0723 d->mSession->setError(job, FileStore::Job::InvalidJobContext, message); 0724 } else if ((item.parentCollection().rights() & Collection::CanDeleteItem) == 0) { 0725 const QString message = i18nc("@info:status", "Access control prohibits item deletion in folder %1", item.parentCollection().name()); 0726 qCCritical(AKONADIFILESTORE_LOG) << message; 0727 qCCritical(AKONADIFILESTORE_LOG) << "Item(remoteId=" << item.remoteId() << ", mimeType=" << item.mimeType() 0728 << ", parentCollection=" << item.parentCollection().remoteId() << ")" << targetParent; 0729 d->mSession->setError(job, FileStore::Job::InvalidJobContext, message); 0730 } else if (item.remoteId().isEmpty()) { 0731 const QString message = i18nc("@info:status", "Given item identifier is empty"); 0732 qCCritical(AKONADIFILESTORE_LOG) << message; 0733 qCCritical(AKONADIFILESTORE_LOG) << "Item(remoteId=" << item.remoteId() << ", mimeType=" << item.mimeType() 0734 << ", parentCollection=" << item.parentCollection().remoteId() << ")" << targetParent; 0735 d->mSession->setError(job, FileStore::Job::InvalidJobContext, message); 0736 } 0737 0738 int errorCode = 0; 0739 QString errorText; 0740 checkItemMove(job, errorCode, errorText); 0741 if (errorCode != 0) { 0742 d->mSession->setError(job, errorCode, errorText); 0743 } 0744 0745 return job; 0746 } 0747 0748 FileStore::StoreCompactJob *FileStore::AbstractLocalStore::compactStore() 0749 { 0750 auto job = new FileStore::StoreCompactJob(d->mSession); 0751 0752 if (d->mTopLevelCollection.remoteId().isEmpty()) { 0753 const QString message = i18nc("@info:status", "Configured storage location is empty"); 0754 qCCritical(AKONADIFILESTORE_LOG) << message; 0755 d->mSession->setError(job, FileStore::Job::InvalidStoreState, message); 0756 } 0757 0758 int errorCode = 0; 0759 QString errorText; 0760 checkStoreCompact(job, errorCode, errorText); 0761 if (errorCode != 0) { 0762 d->mSession->setError(job, errorCode, errorText); 0763 } 0764 0765 return job; 0766 } 0767 0768 FileStore::Job *FileStore::AbstractLocalStore::currentJob() const 0769 { 0770 return d->mCurrentJob; 0771 } 0772 0773 void FileStore::AbstractLocalStore::notifyError(int errorCode, const QString &errorText) const 0774 { 0775 Q_ASSERT(d->mCurrentJob != nullptr); 0776 0777 d->mSession->setError(d->mCurrentJob, errorCode, errorText); 0778 } 0779 0780 void FileStore::AbstractLocalStore::notifyCollectionsProcessed(const Collection::List &collections) const 0781 { 0782 Q_ASSERT(d->mCurrentJob != nullptr); 0783 0784 d->mCollectionsProcessedNotifier.setCollections(collections); 0785 d->mCurrentJob->accept(&(d->mCollectionsProcessedNotifier)); 0786 } 0787 0788 void FileStore::AbstractLocalStore::notifyItemsProcessed(const Item::List &items) const 0789 { 0790 Q_ASSERT(d->mCurrentJob != nullptr); 0791 0792 d->mItemsProcessedNotifier.setItems(items); 0793 d->mCurrentJob->accept(&(d->mItemsProcessedNotifier)); 0794 d->mItemsProcessedNotifier.clearItems(); // save memory 0795 } 0796 0797 void FileStore::AbstractLocalStore::setTopLevelCollection(const Collection &collection) 0798 { 0799 d->mTopLevelCollection = collection; 0800 d->mTopLevelCollectionFetcher.setTopLevelCollection(collection); 0801 } 0802 0803 void FileStore::AbstractLocalStore::checkCollectionCreate(FileStore::CollectionCreateJob *job, int &errorCode, QString &errorText) const 0804 { 0805 Q_UNUSED(job) 0806 Q_UNUSED(errorCode) 0807 Q_UNUSED(errorText) 0808 } 0809 0810 void FileStore::AbstractLocalStore::checkCollectionDelete(FileStore::CollectionDeleteJob *job, int &errorCode, QString &errorText) const 0811 { 0812 Q_UNUSED(job) 0813 Q_UNUSED(errorCode) 0814 Q_UNUSED(errorText) 0815 } 0816 0817 void FileStore::AbstractLocalStore::checkCollectionFetch(FileStore::CollectionFetchJob *job, int &errorCode, QString &errorText) const 0818 { 0819 Q_UNUSED(job) 0820 Q_UNUSED(errorCode) 0821 Q_UNUSED(errorText) 0822 } 0823 0824 void FileStore::AbstractLocalStore::checkCollectionModify(FileStore::CollectionModifyJob *job, int &errorCode, QString &errorText) const 0825 { 0826 Q_UNUSED(job) 0827 Q_UNUSED(errorCode) 0828 Q_UNUSED(errorText) 0829 } 0830 0831 void FileStore::AbstractLocalStore::checkCollectionMove(FileStore::CollectionMoveJob *job, int &errorCode, QString &errorText) const 0832 { 0833 Q_UNUSED(job) 0834 Q_UNUSED(errorCode) 0835 Q_UNUSED(errorText) 0836 } 0837 0838 void FileStore::AbstractLocalStore::checkItemCreate(FileStore::ItemCreateJob *job, int &errorCode, QString &errorText) const 0839 { 0840 Q_UNUSED(job) 0841 Q_UNUSED(errorCode) 0842 Q_UNUSED(errorText) 0843 } 0844 0845 void FileStore::AbstractLocalStore::checkItemDelete(FileStore::ItemDeleteJob *job, int &errorCode, QString &errorText) const 0846 { 0847 Q_UNUSED(job) 0848 Q_UNUSED(errorCode) 0849 Q_UNUSED(errorText) 0850 } 0851 0852 void FileStore::AbstractLocalStore::checkItemFetch(FileStore::ItemFetchJob *job, int &errorCode, QString &errorText) const 0853 { 0854 Q_UNUSED(job) 0855 Q_UNUSED(errorCode) 0856 Q_UNUSED(errorText) 0857 } 0858 0859 void FileStore::AbstractLocalStore::checkItemModify(FileStore::ItemModifyJob *job, int &errorCode, QString &errorText) const 0860 { 0861 Q_UNUSED(job) 0862 Q_UNUSED(errorCode) 0863 Q_UNUSED(errorText) 0864 } 0865 0866 void FileStore::AbstractLocalStore::checkItemMove(FileStore::ItemMoveJob *job, int &errorCode, QString &errorText) const 0867 { 0868 Q_UNUSED(job) 0869 Q_UNUSED(errorCode) 0870 Q_UNUSED(errorText) 0871 } 0872 0873 void FileStore::AbstractLocalStore::checkStoreCompact(FileStore::StoreCompactJob *job, int &errorCode, QString &errorText) const 0874 { 0875 Q_UNUSED(job) 0876 Q_UNUSED(errorCode) 0877 Q_UNUSED(errorText) 0878 } 0879 0880 #include "moc_abstractlocalstore.cpp"