File indexing completed on 2024-06-02 05:32:54
0001 /* 0002 * SPDX-FileCopyrightText: 2015 Kevin Ottens <ervin@kde.org> 0003 * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0004 */ 0005 0006 0007 #include "akonadilivequeryhelpers.h" 0008 0009 #include "akonadi/akonadicollectionfetchjobinterface.h" 0010 #include "akonadi/akonadiitemfetchjobinterface.h" 0011 0012 #include "utils/jobhandler.h" 0013 0014 using namespace Akonadi; 0015 0016 LiveQueryHelpers::LiveQueryHelpers(const SerializerInterface::Ptr &serializer, 0017 const StorageInterface::Ptr &storage) 0018 : m_serializer(serializer), 0019 m_storage(storage) 0020 { 0021 } 0022 0023 LiveQueryHelpers::CollectionFetchFunction LiveQueryHelpers::fetchAllCollections(QObject *parent) const 0024 { 0025 auto storage = m_storage; 0026 return [storage, parent] (const Domain::LiveQueryInput<Collection>::AddFunction &add) { 0027 auto job = storage->fetchCollections(Collection::root(), StorageInterface::Recursive, parent); 0028 Utils::JobHandler::install(job->kjob(), [job, add] { 0029 if (job->kjob()->error()) 0030 return; 0031 0032 foreach (const auto &collection, job->collections()) 0033 add(collection); 0034 }); 0035 }; 0036 } 0037 0038 LiveQueryHelpers::CollectionFetchFunction LiveQueryHelpers::fetchCollections(const Collection &root, QObject *parent) const 0039 { 0040 auto storage = m_storage; 0041 return [storage, root, parent] (const Domain::LiveQueryInput<Collection>::AddFunction &add) { 0042 auto job = storage->fetchCollections(root, StorageInterface::Recursive, parent); 0043 Utils::JobHandler::install(job->kjob(), [root, job, add] { 0044 if (job->kjob()->error()) 0045 return; 0046 0047 auto directChildren = QHash<Collection::Id, Collection>(); 0048 foreach (const auto &collection, job->collections()) { 0049 auto directChild = collection; 0050 while (directChild.parentCollection() != root) 0051 directChild = directChild.parentCollection(); 0052 if (!directChildren.contains(directChild.id())) 0053 directChildren[directChild.id()] = directChild; 0054 } 0055 0056 foreach (const auto &directChild, directChildren) 0057 add(directChild); 0058 }); 0059 }; 0060 } 0061 0062 LiveQueryHelpers::ItemFetchFunction LiveQueryHelpers::fetchItems(QObject *parent) const 0063 { 0064 auto serializer = m_serializer; 0065 auto storage = m_storage; 0066 return [serializer, storage, parent] (const Domain::LiveQueryInput<Item>::AddFunction &add) { 0067 auto job = storage->fetchCollections(Akonadi::Collection::root(), 0068 StorageInterface::Recursive, 0069 parent); 0070 Utils::JobHandler::install(job->kjob(), [serializer, storage, job, add, parent] { 0071 if (job->kjob()->error() != KJob::NoError) 0072 return; 0073 0074 foreach (const auto &collection, job->collections()) { 0075 if (!serializer->isSelectedCollection(collection)) 0076 continue; 0077 0078 auto job = storage->fetchItems(collection, parent); 0079 Utils::JobHandler::install(job->kjob(), [job, add] { 0080 if (job->kjob()->error() != KJob::NoError) 0081 return; 0082 0083 foreach (const auto &item, job->items()) 0084 add(item); 0085 }); 0086 } 0087 }); 0088 }; 0089 } 0090 0091 LiveQueryHelpers::ItemFetchFunction LiveQueryHelpers::fetchItems(const Collection &collection, QObject *parent) const 0092 { 0093 auto storage = m_storage; 0094 return [storage, collection, parent] (const Domain::LiveQueryInput<Item>::AddFunction &add) { 0095 auto job = storage->fetchItems(collection, parent); 0096 Utils::JobHandler::install(job->kjob(), [job, add] { 0097 if (job->kjob()->error() != KJob::NoError) 0098 return; 0099 0100 foreach (const auto &item, job->items()) 0101 add(item); 0102 }); 0103 }; 0104 } 0105 0106 LiveQueryHelpers::ItemFetchFunction LiveQueryHelpers::fetchItemsForContext(const Domain::Context::Ptr &context, QObject *parent) const 0107 { 0108 auto fetchFunction = fetchItems(parent); 0109 auto serializer = m_serializer; 0110 0111 return [context, fetchFunction, serializer] (const Domain::LiveQueryInput<Item>::AddFunction &add) { 0112 auto filterAdd = [context, add, serializer] (const Item &item) { 0113 if (serializer->isContextChild(context, item)) 0114 add(item); 0115 }; 0116 fetchFunction(filterAdd); 0117 }; 0118 } 0119 0120 LiveQueryHelpers::ItemFetchFunction LiveQueryHelpers::fetchTaskAndAncestors(Domain::Task::Ptr task, QObject *parent) const 0121 { 0122 Akonadi::Item childItem = m_serializer->createItemFromTask(task); 0123 Q_ASSERT(childItem.parentCollection().isValid()); // do I really need a fetchItem first, like fetchSiblings does? 0124 // Note: if the task moves to another collection, this live query will then be invalid... 0125 0126 const Akonadi::Item::Id childId = childItem.id(); 0127 auto storage = m_storage; 0128 auto serializer = m_serializer; 0129 return [storage, serializer, childItem, childId, parent] (const Domain::LiveQueryInput<Item>::AddFunction &add) { 0130 auto job = storage->fetchItems(childItem.parentCollection(), parent); 0131 Utils::JobHandler::install(job->kjob(), [job, add, serializer, childId] { 0132 if (job->kjob()->error() != KJob::NoError) 0133 return; 0134 0135 const auto items = job->items(); 0136 // The item itself is part of the result, we need that in findProject, to react on changes of the item itself 0137 // To return a correct child item in case it got updated, we can't use childItem, we need to find it in the list. 0138 const auto myself = std::find_if(items.cbegin(), items.cend(), 0139 [childId] (const Akonadi::Item &item) { 0140 return childId == item.id(); 0141 }); 0142 if (myself == items.cend()) { 0143 qWarning() << "Did not find item in the listing for its parent collection. Item ID:" << childId; 0144 return; 0145 } 0146 add(*myself); 0147 auto parentUid = serializer->relatedUidFromItem(*myself); 0148 while (!parentUid.isEmpty()) { 0149 const auto parent = std::find_if(items.cbegin(), items.cend(), 0150 [serializer, parentUid] (const Akonadi::Item &item) { 0151 return serializer->itemUid(item) == parentUid; 0152 }); 0153 if (parent == items.cend()) { 0154 break; 0155 } 0156 add(*parent); 0157 parentUid = serializer->relatedUidFromItem(*parent); 0158 } 0159 }); 0160 }; 0161 } 0162 0163 LiveQueryHelpers::CollectionFetchFunction LiveQueryHelpers::fetchItemCollection(const Item& item, QObject *parent) const 0164 { 0165 auto storage = m_storage; 0166 return [storage, item, parent] (const Domain::LiveQueryInput<Collection>::AddFunction &add) { 0167 auto job = storage->fetchCollections(item.parentCollection(), StorageInterface::Base, parent); 0168 Utils::JobHandler::install(job->kjob(), [storage, job, add] { 0169 if (job->kjob()->error() != KJob::NoError) 0170 return; 0171 auto collection = job->collections().at(0); 0172 add(collection); 0173 }); 0174 }; 0175 } 0176 0177 0178 LiveQueryHelpers::ItemFetchFunction LiveQueryHelpers::fetchSiblings(const Item &item, QObject *parent) const 0179 { 0180 auto storage = m_storage; 0181 return [storage, item, parent] (const Domain::LiveQueryInput<Item>::AddFunction &add) { 0182 auto job = storage->fetchItem(item, parent); 0183 Utils::JobHandler::install(job->kjob(), [storage, job, add, parent] { 0184 if (job->kjob()->error() != KJob::NoError) 0185 return; 0186 0187 Q_ASSERT(job->items().size() == 1); 0188 auto item = job->items().at(0); 0189 Q_ASSERT(item.parentCollection().isValid()); 0190 auto job = storage->fetchItems(item.parentCollection(), parent); 0191 Utils::JobHandler::install(job->kjob(), [job, add] { 0192 if (job->kjob()->error() != KJob::NoError) 0193 return; 0194 0195 foreach (const auto &item, job->items()) 0196 add(item); 0197 }); 0198 }); 0199 }; 0200 }