File indexing completed on 2024-11-17 04:42:38

0001 /*
0002  * SPDX-FileCopyrightText: 2014 Sandro Knauß <knauss@kolabsys.com>
0003  *
0004  * SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0
0005  */
0006 
0007 #include "viewcalendar.h"
0008 #include "agendaview.h"
0009 #include "calendarview_debug.h"
0010 #include "helper.h"
0011 
0012 #include <Akonadi/CalendarUtils>
0013 #include <Akonadi/EntityTreeModel>
0014 
0015 #include <QAbstractProxyModel>
0016 #include <QSharedPointer>
0017 
0018 #include <ranges>
0019 
0020 using namespace EventViews;
0021 
0022 ViewCalendar::~ViewCalendar() = default;
0023 
0024 MultiViewCalendar::~MultiViewCalendar() = default;
0025 
0026 KCalendarCore::Calendar::Ptr MultiViewCalendar::getCalendar() const
0027 {
0028     return {};
0029 }
0030 
0031 KCalendarCore::Incidence::List MultiViewCalendar::incidences() const
0032 {
0033     KCalendarCore::Incidence::List list;
0034     for (const ViewCalendar::Ptr &cal : std::as_const(mSubCalendars)) {
0035         if (cal->getCalendar()) {
0036             list += cal->getCalendar()->incidences();
0037         }
0038     }
0039     return list;
0040 }
0041 
0042 int MultiViewCalendar::calendarCount() const
0043 {
0044     return mSubCalendars.size();
0045 }
0046 
0047 Akonadi::CollectionCalendar::Ptr MultiViewCalendar::calendarForCollection(const Akonadi::Collection &collection) const
0048 {
0049     return calendarForCollection(collection.id());
0050 }
0051 
0052 Akonadi::CollectionCalendar::Ptr MultiViewCalendar::calendarForCollection(Akonadi::Collection::Id collectionId) const
0053 {
0054     const auto cal = std::find_if(mSubCalendars.begin(), mSubCalendars.end(), [collectionId](const auto &calendar) {
0055         if (const auto &akonadiCal = qSharedPointerDynamicCast<AkonadiViewCalendar>(calendar); akonadiCal) {
0056             return akonadiCal->mCalendar->collection().id() == collectionId;
0057         }
0058         return false;
0059     });
0060     if (cal == mSubCalendars.end()) {
0061         return {};
0062     }
0063 
0064     return qSharedPointerCast<AkonadiViewCalendar>(*cal)->mCalendar;
0065 }
0066 
0067 ViewCalendar::Ptr MultiViewCalendar::findCalendar(const KCalendarCore::Incidence::Ptr &incidence) const
0068 {
0069     for (const ViewCalendar::Ptr &cal : std::as_const(mSubCalendars)) {
0070         if (cal->isValid(incidence)) {
0071             return cal;
0072         }
0073     }
0074     return {};
0075 }
0076 
0077 ViewCalendar::Ptr MultiViewCalendar::findCalendar(const QString &incidenceIdentifier) const
0078 {
0079     for (const ViewCalendar::Ptr &cal : std::as_const(mSubCalendars)) {
0080         if (cal->isValid(incidenceIdentifier)) {
0081             return cal;
0082         }
0083     }
0084     return {};
0085 }
0086 
0087 void MultiViewCalendar::addCalendar(const ViewCalendar::Ptr &calendar)
0088 {
0089     if (!mSubCalendars.contains(calendar)) {
0090         mSubCalendars.append(calendar);
0091     }
0092 }
0093 
0094 void MultiViewCalendar::removeCalendar(const ViewCalendar::Ptr &calendar)
0095 {
0096     mSubCalendars.removeOne(calendar);
0097 }
0098 
0099 QString MultiViewCalendar::displayName(const KCalendarCore::Incidence::Ptr &incidence) const
0100 {
0101     ViewCalendar::Ptr cal = findCalendar(incidence);
0102     if (cal) {
0103         return cal->displayName(incidence);
0104     }
0105     return {};
0106 }
0107 
0108 QString MultiViewCalendar::iconForIncidence(const KCalendarCore::Incidence::Ptr &incidence) const
0109 {
0110     ViewCalendar::Ptr cal = findCalendar(incidence);
0111     if (cal) {
0112         return cal->iconForIncidence(incidence);
0113     }
0114     return {};
0115 }
0116 
0117 bool MultiViewCalendar::isValid(const KCalendarCore::Incidence::Ptr &incidence) const
0118 {
0119     ViewCalendar::Ptr cal = findCalendar(incidence);
0120     return !cal.isNull();
0121 }
0122 
0123 bool MultiViewCalendar::isValid(const QString &incidenceIdentifier) const
0124 {
0125     ViewCalendar::Ptr cal = findCalendar(incidenceIdentifier);
0126     return !cal.isNull();
0127 }
0128 
0129 QColor MultiViewCalendar::resourceColor(const KCalendarCore::Incidence::Ptr &incidence) const
0130 {
0131     ViewCalendar::Ptr cal = findCalendar(incidence);
0132     if (cal) {
0133         return cal->resourceColor(incidence);
0134     }
0135     return {};
0136 }
0137 
0138 Akonadi::Item MultiViewCalendar::item(const KCalendarCore::Incidence::Ptr &incidence) const
0139 {
0140     for (auto &cal : mSubCalendars) {
0141         const auto &akonadiCal = qSharedPointerDynamicCast<AkonadiViewCalendar>(cal);
0142         if (!akonadiCal) {
0143             continue;
0144         }
0145         if (const auto &item = akonadiCal->item(incidence); item.isValid()) {
0146             return item;
0147         }
0148     }
0149     return {};
0150 }
0151 
0152 AkonadiViewCalendar::~AkonadiViewCalendar() = default;
0153 
0154 bool AkonadiViewCalendar::isValid(const KCalendarCore::Incidence::Ptr &incidence) const
0155 {
0156     if (!mCalendar) {
0157         return false;
0158     }
0159 
0160     if (item(incidence).isValid()) {
0161         return true;
0162     }
0163     return false;
0164 }
0165 
0166 bool AkonadiViewCalendar::isValid(const QString &incidenceIdentifier) const
0167 {
0168     if (!mCalendar) {
0169         return false;
0170     }
0171 
0172     return !mCalendar->incidence(incidenceIdentifier).isNull();
0173 }
0174 
0175 Akonadi::Item AkonadiViewCalendar::item(const KCalendarCore::Incidence::Ptr &incidence) const
0176 {
0177     if (!mCalendar || !incidence) {
0178         return {};
0179     }
0180     bool ok = false;
0181     Akonadi::Item::Id id = incidence->customProperty("VOLATILE", "AKONADI-ID").toLongLong(&ok);
0182 
0183     if (id == -1 || !ok) {
0184         id = mCalendar->item(incidence).id();
0185 
0186         if (id == -1) {
0187             // Ok, we really don't know the ID, give up.
0188             qCWarning(CALENDARVIEW_LOG) << "Item is invalid. uid = " << incidence->instanceIdentifier();
0189             return {};
0190         }
0191         return mCalendar->item(incidence->instanceIdentifier());
0192     }
0193     return mCalendar->item(id);
0194 }
0195 
0196 QString AkonadiViewCalendar::displayName(const KCalendarCore::Incidence::Ptr &incidence) const
0197 {
0198     auto *model = mAgendaView->model();
0199     Akonadi::EntityTreeModel *etm = nullptr;
0200     while (model) {
0201         if (const auto *proxy = qobject_cast<QAbstractProxyModel *>(model); proxy != nullptr) {
0202             model = proxy->sourceModel();
0203         } else if (etm = qobject_cast<Akonadi::EntityTreeModel *>(model); etm != nullptr) {
0204             break;
0205         } else {
0206             model = nullptr;
0207         }
0208     }
0209     if (etm) {
0210         return Akonadi::CalendarUtils::displayName(etm, item(incidence).parentCollection());
0211     }
0212 
0213     return {};
0214 }
0215 
0216 QColor AkonadiViewCalendar::resourceColor(const KCalendarCore::Incidence::Ptr &incidence) const
0217 {
0218     return EventViews::resourceColor(item(incidence), mAgendaView->preferences());
0219 }
0220 
0221 QString AkonadiViewCalendar::iconForIncidence(const KCalendarCore::Incidence::Ptr &incidence) const
0222 {
0223     return mAgendaView->iconForItem(item(incidence));
0224 }
0225 
0226 KCalendarCore::Calendar::Ptr AkonadiViewCalendar::getCalendar() const
0227 {
0228     return mCalendar;
0229 }