File indexing completed on 2024-11-24 04:43:42
0001 /* 0002 * SPDX-FileCopyrightText: 2020 Shashwat Jolly <shashwat.jolly@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "journalsfetchjob.h" 0008 0009 #include <Akonadi/CollectionColorAttribute> 0010 #include <Akonadi/EntityDisplayAttribute> 0011 #include <KCalendarCore/Event> 0012 #include <KCalendarCore/Todo> 0013 #include <KContacts/Addressee> 0014 #include <KContacts/ContactGroup> 0015 #include <QtConcurrent> 0016 0017 #include "etesync_debug.h" 0018 0019 #define COLLECTIONS_FETCH_BATCH_SIZE 50 0020 0021 using namespace EteSyncAPI; 0022 using namespace Akonadi; 0023 0024 JournalsFetchJob::JournalsFetchJob(const EteSyncClientState *clientState, const Akonadi::Collection &resourceCollection, QObject *parent) 0025 : KJob(parent) 0026 , mClientState(clientState) 0027 , mResourceCollection(resourceCollection) 0028 { 0029 } 0030 0031 void JournalsFetchJob::start() 0032 { 0033 qCDebug(ETESYNC_LOG) << "Journals fetch start"; 0034 QFutureWatcher<void> *watcher = new QFutureWatcher<void>(this); 0035 connect(watcher, &QFutureWatcher<void>::finished, this, [this] { 0036 qCDebug(ETESYNC_LOG) << "emitResult from JournalsFetchJob"; 0037 emitResult(); 0038 }); 0039 QFuture<void> fetchJournalsFuture = QtConcurrent::run(this, &JournalsFetchJob::fetchJournals); 0040 watcher->setFuture(fetchJournalsFuture); 0041 } 0042 0043 void JournalsFetchJob::fetchJournals() 0044 { 0045 if (!mClientState) { 0046 setError(UserDefinedError); 0047 setErrorText(QStringLiteral("EntriesFetchJob: EteSync client state is null")); 0048 return; 0049 } 0050 0051 EtebaseAccount *account = mClientState->account(); 0052 0053 if (!account) { 0054 setError(UserDefinedError); 0055 setErrorText(QStringLiteral("EntriesFetchJob: Etebase account is null")); 0056 return; 0057 } 0058 0059 mSyncToken = mResourceCollection.remoteRevision(); 0060 bool done = false; 0061 EtebaseCollectionManagerPtr collectionManager(etebase_account_get_collection_manager(account)); 0062 0063 while (!done) { 0064 EtebaseFetchOptionsPtr fetchOptions(etebase_fetch_options_new()); 0065 etebase_fetch_options_set_stoken(fetchOptions.get(), mSyncToken); 0066 etebase_fetch_options_set_limit(fetchOptions.get(), COLLECTIONS_FETCH_BATCH_SIZE); 0067 etebase_fetch_options_set_prefetch(fetchOptions.get(), ETEBASE_PREFETCH_OPTION_MEDIUM); 0068 0069 EtebaseCollectionListResponsePtr collectionList(etebase_collection_manager_list_multi(collectionManager.get(), 0070 ETESYNC_COLLECTION_TYPES, 0071 ETEBASE_UTILS_C_ARRAY_LEN(ETESYNC_COLLECTION_TYPES), 0072 fetchOptions.get())); 0073 if (!collectionList) { 0074 setError(int(etebase_error_get_code())); 0075 const char *err = etebase_error_get_message(); 0076 setErrorText(QString::fromUtf8(err)); 0077 return; 0078 } 0079 0080 mSyncToken = QString::fromUtf8(etebase_collection_list_response_get_stoken(collectionList.get())); 0081 done = etebase_collection_list_response_is_done(collectionList.get()); 0082 0083 uintptr_t dataLength = etebase_collection_list_response_get_data_length(collectionList.get()); 0084 0085 qCDebug(ETESYNC_LOG) << "Retrieved collection list length" << dataLength; 0086 0087 std::vector<const EtebaseCollection *> etesyncCollections(dataLength, nullptr); 0088 if (etebase_collection_list_response_get_data(collectionList.get(), etesyncCollections.data())) { 0089 setError(int(etebase_error_get_code())); 0090 const char *err = etebase_error_get_message(); 0091 setErrorText(QString::fromUtf8(err)); 0092 } 0093 0094 for (uintptr_t i = 0; i < dataLength; i++) { 0095 mClientState->saveEtebaseCollectionCache(etesyncCollections[i]); 0096 setupCollection(etesyncCollections[i]); 0097 } 0098 0099 uintptr_t removedCollectionsLength = etebase_collection_list_response_get_removed_memberships_length(collectionList.get()); 0100 qCDebug(ETESYNC_LOG) << "Removed collection membership list length" << removedCollectionsLength; 0101 if (removedCollectionsLength) { 0102 std::vector<const EtebaseRemovedCollection *> removedEtesyncCollections(removedCollectionsLength, nullptr); 0103 if (etebase_collection_list_response_get_removed_memberships(collectionList.get(), removedEtesyncCollections.data())) { 0104 setError(int(etebase_error_get_code())); 0105 const char *err = etebase_error_get_message(); 0106 setErrorText(QString::fromUtf8(err)); 0107 } 0108 for (uintptr_t i = 0; i < removedCollectionsLength; i++) { 0109 Collection collection; 0110 const QString journalUid = QString::fromUtf8(etebase_removed_collection_get_uid(removedEtesyncCollections[i])); 0111 collection.setRemoteId(journalUid); 0112 collection.setParentCollection(mResourceCollection); 0113 qCDebug(ETESYNC_LOG) << "Removed collection membership" << journalUid; 0114 mRemovedCollections.push_back(collection); 0115 } 0116 } 0117 } 0118 } 0119 0120 void JournalsFetchJob::setupCollection(const EtebaseCollection *etesyncCollection) 0121 { 0122 if (!etesyncCollection) { 0123 qCDebug(ETESYNC_LOG) << "Unable to setup collection - etesyncCollection is null"; 0124 return; 0125 } 0126 0127 qCDebug(ETESYNC_LOG) << "Setting up collection" << etebase_collection_get_uid(etesyncCollection); 0128 0129 EtebaseItemMetadataPtr metaData(etebase_collection_get_meta(etesyncCollection)); 0130 0131 const QString type = QString::fromUtf8(etebase_collection_get_collection_type(etesyncCollection)); 0132 qCDebug(ETESYNC_LOG) << ETEBASE_COLLECTION_TYPE_CALENDAR; 0133 0134 qCDebug(ETESYNC_LOG) << "Type" << type; 0135 0136 QStringList mimeTypes; 0137 0138 Collection collection; 0139 0140 auto attr = collection.attribute<EntityDisplayAttribute>(Collection::AddIfMissing); 0141 0142 const QString displayName = QString::fromUtf8(etebase_item_metadata_get_name(metaData.get())); 0143 0144 qCDebug(ETESYNC_LOG) << "Name:" << displayName; 0145 0146 if (type == ETEBASE_COLLECTION_TYPE_ADDRESS_BOOK) { 0147 mimeTypes.push_back(KContacts::Addressee::mimeType()); 0148 mimeTypes.push_back(KContacts::ContactGroup::mimeType()); 0149 attr->setDisplayName(displayName); 0150 attr->setIconName(QStringLiteral("view-pim-contacts")); 0151 } else if (type == ETEBASE_COLLECTION_TYPE_CALENDAR) { 0152 mimeTypes.push_back(KCalendarCore::Event::eventMimeType()); 0153 attr->setDisplayName(displayName); 0154 attr->setIconName(QStringLiteral("view-calendar")); 0155 } else if (type == ETEBASE_COLLECTION_TYPE_TASKS) { 0156 mimeTypes.push_back(KCalendarCore::Todo::todoMimeType()); 0157 attr->setDisplayName(displayName); 0158 attr->setIconName(QStringLiteral("view-pim-tasks")); 0159 } else { 0160 qCInfo(ETESYNC_LOG) << "Unknown collection type. Cannot set collection mime type."; 0161 return; 0162 } 0163 0164 const QString journalUid = QString::fromUtf8(etebase_collection_get_uid(etesyncCollection)); 0165 auto collectionColor = QString::fromUtf8(etebase_item_metadata_get_color(metaData.get())); 0166 auto colorAttr = collection.attribute<Akonadi::CollectionColorAttribute>(Collection::AddIfMissing); 0167 if (collectionColor.isEmpty()) { 0168 collectionColor = ETESYNC_DEFAULT_COLLECTION_COLOR; 0169 } 0170 // Convert #RRGGBBAA strings to #AARRGGBB, which is required by Qt 0171 if (collectionColor.length() == 9) { 0172 collectionColor = collectionColor.left(1) + collectionColor.right(2) + collectionColor.mid(1, 6); 0173 } 0174 colorAttr->setColor(collectionColor); 0175 0176 if (etebase_collection_get_access_level(etesyncCollection) == ETEBASE_COLLECTION_ACCESS_LEVEL_READ_ONLY) { 0177 collection.setRights(Collection::ReadOnly); 0178 } 0179 0180 collection.setRemoteId(journalUid); 0181 collection.setName(journalUid); 0182 collection.setContentMimeTypes(mimeTypes); 0183 collection.setParentCollection(mResourceCollection); 0184 0185 if (etebase_collection_is_deleted(etesyncCollection)) { 0186 mRemovedCollections.push_back(collection); 0187 return; 0188 } 0189 0190 mCollections.push_back(collection); 0191 } 0192 0193 #include "moc_journalsfetchjob.cpp"