File indexing completed on 2024-12-29 04:46:19

0001 /*
0002   SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
0003     Author: Stephen Kelly <stephen@kdab.com>
0004 
0005   SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #include "incidenceattachmentmodel.h"
0009 
0010 #include <Akonadi/EntityTreeModel>
0011 #include <Akonadi/ItemFetchJob>
0012 #include <Akonadi/ItemFetchScope>
0013 #include <Akonadi/Monitor>
0014 
0015 using namespace CalendarSupport;
0016 using namespace Akonadi;
0017 
0018 namespace CalendarSupport
0019 {
0020 class IncidenceAttachmentModelPrivate
0021 {
0022     IncidenceAttachmentModelPrivate(IncidenceAttachmentModel *qq, const QPersistentModelIndex &modelIndex, const Akonadi::Item &item = Akonadi::Item())
0023         : q_ptr(qq)
0024         , m_modelIndex(modelIndex)
0025         , m_item(item)
0026     {
0027         if (modelIndex.isValid()) {
0028             QObject::connect(modelIndex.model(), SIGNAL(dataChanged(QModelIndex, QModelIndex)), qq, SLOT(resetModel()));
0029         } else if (item.isValid()) {
0030             createMonitor();
0031             resetInternalData();
0032         }
0033     }
0034 
0035     void resetModel()
0036     {
0037         Q_Q(IncidenceAttachmentModel);
0038         q->beginResetModel();
0039         resetInternalData();
0040         q->endResetModel();
0041         Q_EMIT q->rowCountChanged();
0042     }
0043 
0044     void itemFetched(Akonadi::Item::List list)
0045     {
0046         Q_ASSERT(list.size() == 1);
0047         setItem(list.first());
0048     }
0049 
0050     void setItem(const Akonadi::Item &item);
0051 
0052     void createMonitor()
0053     {
0054         if (m_monitor) {
0055             return;
0056         }
0057 
0058         m_monitor = new Akonadi::Monitor(q_ptr);
0059         m_monitor->setObjectName(QLatin1StringView("IncidenceAttachmentModelMonitor"));
0060         m_monitor->setItemMonitored(m_item);
0061         m_monitor->itemFetchScope().fetchFullPayload(true);
0062         QObject::connect(m_monitor, SIGNAL(itemChanged(Akonadi::Item, QSet<QByteArray>)), q_ptr, SLOT(resetModel()));
0063         QObject::connect(m_monitor, SIGNAL(itemRemoved(Akonadi::Item)), q_ptr, SLOT(resetModel()));
0064     }
0065 
0066     void resetInternalData()
0067     {
0068         Item item = m_item;
0069         if (m_modelIndex.isValid()) {
0070             item = m_modelIndex.data(EntityTreeModel::ItemRole).value<Akonadi::Item>();
0071         }
0072 
0073         if (!item.isValid() || !item.hasPayload<KCalendarCore::Incidence::Ptr>()) {
0074             m_incidence = KCalendarCore::Incidence::Ptr();
0075             return;
0076         }
0077         m_incidence = item.payload<KCalendarCore::Incidence::Ptr>();
0078     }
0079 
0080     Q_DECLARE_PUBLIC(IncidenceAttachmentModel)
0081     IncidenceAttachmentModel *const q_ptr;
0082 
0083     QModelIndex m_modelIndex;
0084     Akonadi::Item m_item;
0085     KCalendarCore::Incidence::Ptr m_incidence;
0086     Akonadi::Monitor *m_monitor = nullptr;
0087 };
0088 }
0089 
0090 IncidenceAttachmentModel::IncidenceAttachmentModel(const QPersistentModelIndex &modelIndex, QObject *parent)
0091     : QAbstractListModel(parent)
0092     , d_ptr(new IncidenceAttachmentModelPrivate(this, modelIndex))
0093 {
0094 }
0095 
0096 IncidenceAttachmentModel::IncidenceAttachmentModel(const Akonadi::Item &item, QObject *parent)
0097     : QAbstractListModel(parent)
0098     , d_ptr(new IncidenceAttachmentModelPrivate(this, QModelIndex(), item))
0099 {
0100 }
0101 
0102 IncidenceAttachmentModel::IncidenceAttachmentModel(QObject *parent)
0103     : QAbstractListModel(parent)
0104     , d_ptr(new IncidenceAttachmentModelPrivate(this, QModelIndex()))
0105 {
0106 }
0107 
0108 IncidenceAttachmentModel::~IncidenceAttachmentModel() = default;
0109 
0110 KCalendarCore::Incidence::Ptr IncidenceAttachmentModel::incidence() const
0111 {
0112     Q_D(const IncidenceAttachmentModel);
0113     return d->m_incidence;
0114 }
0115 
0116 void IncidenceAttachmentModel::setIndex(const QPersistentModelIndex &modelIndex)
0117 {
0118     Q_D(IncidenceAttachmentModel);
0119     beginResetModel();
0120     d->m_modelIndex = modelIndex;
0121     d->m_item = Akonadi::Item();
0122     d->resetInternalData();
0123     endResetModel();
0124     Q_EMIT rowCountChanged();
0125 }
0126 
0127 void IncidenceAttachmentModel::setItem(const Akonadi::Item &item)
0128 {
0129     Q_D(IncidenceAttachmentModel);
0130     if (!item.hasPayload<KCalendarCore::Incidence::Ptr>()) {
0131         auto job = new ItemFetchJob(item);
0132         job->fetchScope().fetchFullPayload(true);
0133         connect(job, SIGNAL(itemsReceived(Akonadi::Item::List)), SLOT(itemFetched(Akonadi::Item::List)));
0134         return;
0135     }
0136     d->setItem(item);
0137 }
0138 
0139 void IncidenceAttachmentModelPrivate::setItem(const Akonadi::Item &item)
0140 {
0141     Q_Q(IncidenceAttachmentModel);
0142     q->beginResetModel();
0143     m_modelIndex = QModelIndex();
0144     m_item = item;
0145     createMonitor();
0146     resetInternalData();
0147     q->endResetModel();
0148     Q_EMIT q->rowCountChanged();
0149 }
0150 
0151 int IncidenceAttachmentModel::rowCount(const QModelIndex &) const
0152 {
0153     Q_D(const IncidenceAttachmentModel);
0154     if (!d->m_incidence) {
0155         return 0;
0156     } else {
0157         return d->m_incidence->attachments().size();
0158     }
0159 }
0160 
0161 QVariant IncidenceAttachmentModel::data(const QModelIndex &index, int role) const
0162 {
0163     Q_D(const IncidenceAttachmentModel);
0164     if (!d->m_incidence) {
0165         return {};
0166     }
0167 
0168     const KCalendarCore::Attachment attachment = d->m_incidence->attachments().at(index.row());
0169     switch (role) {
0170     case Qt::DisplayRole:
0171         return attachment.label();
0172     case AttachmentDataRole:
0173         return attachment.decodedData();
0174     case MimeTypeRole:
0175         return attachment.mimeType();
0176     }
0177     return {};
0178 }
0179 
0180 QVariant IncidenceAttachmentModel::headerData(int section, Qt::Orientation orientation, int role) const
0181 {
0182     return QAbstractItemModel::headerData(section, orientation, role);
0183 }
0184 
0185 QHash<int, QByteArray> CalendarSupport::IncidenceAttachmentModel::roleNames() const
0186 {
0187     QHash<int, QByteArray> roleNames = QAbstractListModel::roleNames();
0188     roleNames.insert(IncidenceAttachmentModel::MimeTypeRole, "mimeType");
0189     return roleNames;
0190 }
0191 
0192 #include "moc_incidenceattachmentmodel.cpp"