File indexing completed on 2024-11-10 04:40:43

0001 /*
0002     SPDX-FileCopyrightText: 2009 Stephen Kelly <steveire@gmail.com>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "partfetcher.h"
0008 
0009 #include "entitytreemodel.h"
0010 #include "itemfetchjob.h"
0011 #include "itemfetchscope.h"
0012 #include "session.h"
0013 #include <KLocalizedString>
0014 
0015 Q_DECLARE_METATYPE(QSet<QByteArray>)
0016 
0017 using namespace Akonadi;
0018 
0019 namespace Akonadi
0020 {
0021 class PartFetcherPrivate
0022 {
0023     PartFetcherPrivate(PartFetcher *partFetcher, const QModelIndex &index, const QByteArray &partName)
0024         : m_persistentIndex(index)
0025         , m_partName(partName)
0026         , q_ptr(partFetcher)
0027     {
0028     }
0029 
0030     void fetchJobDone(KJob *job);
0031 
0032     void modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
0033 
0034     QPersistentModelIndex m_persistentIndex;
0035     QByteArray m_partName;
0036     Item m_item;
0037 
0038     Q_DECLARE_PUBLIC(PartFetcher)
0039     PartFetcher *q_ptr;
0040 };
0041 
0042 } // namespace Akonadi
0043 
0044 void PartFetcherPrivate::fetchJobDone(KJob *job)
0045 {
0046     Q_Q(PartFetcher);
0047     if (job->error()) {
0048         q->setError(KJob::UserDefinedError);
0049         q->setErrorText(i18n("Unable to fetch item for index"));
0050         q->emitResult();
0051         return;
0052     }
0053 
0054     auto fetchJob = qobject_cast<ItemFetchJob *>(job);
0055 
0056     const Item::List list = fetchJob->items();
0057 
0058     Q_ASSERT(list.size() == 1);
0059 
0060     // If m_persistentIndex comes from a selection proxy model, it could become
0061     // invalid if the user clicks around a lot.
0062     if (!m_persistentIndex.isValid()) {
0063         q->setError(KJob::UserDefinedError);
0064         q->setErrorText(i18n("Index is no longer available"));
0065         q->emitResult();
0066         return;
0067     }
0068 
0069     const auto loadedParts = m_persistentIndex.data(EntityTreeModel::LoadedPartsRole).value<QSet<QByteArray>>();
0070 
0071     Q_ASSERT(!loadedParts.contains(m_partName));
0072 
0073     Item item = m_persistentIndex.data(EntityTreeModel::ItemRole).value<Item>();
0074 
0075     item.apply(list.at(0));
0076 
0077     auto model = const_cast<QAbstractItemModel *>(m_persistentIndex.model());
0078 
0079     Q_ASSERT(model);
0080 
0081     QVariant itemVariant = QVariant::fromValue(item);
0082     model->setData(m_persistentIndex, itemVariant, EntityTreeModel::ItemRole);
0083 
0084     m_item = item;
0085 
0086     q->emitResult();
0087 }
0088 
0089 PartFetcher::PartFetcher(const QModelIndex &index, const QByteArray &partName, QObject *parent)
0090     : KJob(parent)
0091     , d_ptr(new PartFetcherPrivate(this, index, partName))
0092 {
0093 }
0094 
0095 PartFetcher::~PartFetcher() = default;
0096 
0097 void PartFetcher::start()
0098 {
0099     Q_D(PartFetcher);
0100 
0101     const QModelIndex index = d->m_persistentIndex;
0102 
0103     const auto loadedParts = index.data(EntityTreeModel::LoadedPartsRole).value<QSet<QByteArray>>();
0104 
0105     if (loadedParts.contains(d->m_partName)) {
0106         d->m_item = d->m_persistentIndex.data(EntityTreeModel::ItemRole).value<Item>();
0107         emitResult();
0108         return;
0109     }
0110 
0111     const auto availableParts = index.data(EntityTreeModel::AvailablePartsRole).value<QSet<QByteArray>>();
0112     if (!availableParts.contains(d->m_partName)) {
0113         setError(UserDefinedError);
0114         setErrorText(i18n("Payload part '%1' is not available for this index", QString::fromLatin1(d->m_partName)));
0115         emitResult();
0116         return;
0117     }
0118 
0119     auto session = qobject_cast<Akonadi::Session *>(qvariant_cast<QObject *>(index.data(EntityTreeModel::SessionRole)));
0120 
0121     if (!session) {
0122         setError(UserDefinedError);
0123         setErrorText(i18n("No session available for this index"));
0124         emitResult();
0125         return;
0126     }
0127 
0128     const auto item = index.data(EntityTreeModel::ItemRole).value<Akonadi::Item>();
0129 
0130     if (!item.isValid()) {
0131         setError(UserDefinedError);
0132         setErrorText(i18n("No item available for this index"));
0133         emitResult();
0134         return;
0135     }
0136 
0137     ItemFetchScope scope;
0138     scope.fetchPayloadPart(d->m_partName);
0139     auto itemFetchJob = new Akonadi::ItemFetchJob(item, session);
0140     itemFetchJob->setFetchScope(scope);
0141     connect(itemFetchJob, &KJob::result, this, [d](KJob *job) {
0142         d->fetchJobDone(job);
0143     });
0144 }
0145 
0146 QModelIndex PartFetcher::index() const
0147 {
0148     Q_D(const PartFetcher);
0149 
0150     return d->m_persistentIndex;
0151 }
0152 
0153 QByteArray PartFetcher::partName() const
0154 {
0155     Q_D(const PartFetcher);
0156 
0157     return d->m_partName;
0158 }
0159 
0160 Item PartFetcher::item() const
0161 {
0162     Q_D(const PartFetcher);
0163 
0164     return d->m_item;
0165 }
0166 
0167 #include "moc_partfetcher.cpp"