File indexing completed on 2024-06-02 05:18:01

0001 /*
0002  * SPDX-FileCopyrightText: 2014 Sandro Knauß <knauss@kolabsys.com>
0003  *
0004  * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005  *
0006  */
0007 
0008 #include "freebusycalendar.h"
0009 #include "calendarsupport_debug.h"
0010 
0011 #include <KCalendarCore/FreeBusyPeriod>
0012 #include <KCalendarCore/MemoryCalendar>
0013 
0014 #include <KLocalizedString>
0015 
0016 #include <QTimeZone>
0017 
0018 using namespace CalendarSupport;
0019 
0020 class CalendarSupport::FreeBusyCalendarPrivate
0021 {
0022 public:
0023     FreeBusyCalendarPrivate() = default;
0024 
0025     FreeBusyItemModel *mModel = nullptr;
0026     KCalendarCore::Calendar::Ptr mCalendar;
0027     QMap<QModelIndex, KCalendarCore::Event::Ptr> mFbEvent;
0028 };
0029 
0030 FreeBusyCalendar::FreeBusyCalendar(QObject *parent)
0031     : QObject(parent)
0032     , d(new CalendarSupport::FreeBusyCalendarPrivate)
0033 {
0034     d->mCalendar = KCalendarCore::Calendar::Ptr(new KCalendarCore::MemoryCalendar(QTimeZone::systemTimeZone()));
0035     qCDebug(CALENDARSUPPORT_LOG) << "creating" << this;
0036 }
0037 
0038 FreeBusyCalendar::~FreeBusyCalendar()
0039 {
0040     qCDebug(CALENDARSUPPORT_LOG) << "deleting" << this;
0041 }
0042 
0043 KCalendarCore::Calendar::Ptr FreeBusyCalendar::calendar() const
0044 {
0045     return d->mCalendar;
0046 }
0047 
0048 FreeBusyItemModel *FreeBusyCalendar::model() const
0049 {
0050     return d->mModel;
0051 }
0052 
0053 void FreeBusyCalendar::setModel(FreeBusyItemModel *model)
0054 {
0055     if (model != d->mModel) {
0056         if (d->mModel) {
0057             disconnect(d->mModel, nullptr, nullptr, nullptr);
0058         }
0059         d->mModel = model;
0060         connect(d->mModel, &QAbstractItemModel::layoutChanged, this, &FreeBusyCalendar::onLayoutChanged);
0061         connect(d->mModel, &QAbstractItemModel::modelReset, this, &FreeBusyCalendar::onLayoutChanged);
0062         connect(d->mModel, &QAbstractItemModel::rowsAboutToBeRemoved, this, &FreeBusyCalendar::onRowsRemoved);
0063         connect(d->mModel, &QAbstractItemModel::rowsInserted, this, &FreeBusyCalendar::onRowsInserted);
0064         connect(d->mModel, &QAbstractItemModel::dataChanged, this, &FreeBusyCalendar::onRowsChanged);
0065     }
0066 }
0067 
0068 void FreeBusyCalendar::deleteAllEvents()
0069 {
0070     const KCalendarCore::Event::List lstEvents = d->mCalendar->events();
0071     for (const KCalendarCore::Event::Ptr &event : lstEvents) {
0072         d->mCalendar->deleteEvent(event);
0073     }
0074 }
0075 
0076 void FreeBusyCalendar::onLayoutChanged()
0077 {
0078     if (!d->mFbEvent.isEmpty()) {
0079         deleteAllEvents();
0080         d->mFbEvent.clear();
0081         for (int i = d->mModel->rowCount() - 1; i >= 0; --i) {
0082             QModelIndex parent = d->mModel->index(i, 0);
0083             onRowsInserted(parent, 0, d->mModel->rowCount(parent) - 1);
0084         }
0085     }
0086 }
0087 
0088 void FreeBusyCalendar::onRowsInserted(const QModelIndex &parent, int first, int last)
0089 {
0090     if (!parent.isValid()) {
0091         return;
0092     }
0093     for (int i = first; i <= last; ++i) {
0094         QModelIndex index = d->mModel->index(i, 0, parent);
0095 
0096         const KCalendarCore::FreeBusyPeriod &period = d->mModel->data(index, FreeBusyItemModel::FreeBusyPeriodRole).value<KCalendarCore::FreeBusyPeriod>();
0097         const KCalendarCore::FreeBusy::Ptr &fb = d->mModel->data(parent, FreeBusyItemModel::FreeBusyRole).value<KCalendarCore::FreeBusy::Ptr>();
0098 
0099         KCalendarCore::Event::Ptr inc = KCalendarCore::Event::Ptr(new KCalendarCore::Event());
0100         inc->setDtStart(period.start());
0101         inc->setDtEnd(period.end());
0102         inc->setUid(QLatin1StringView("fb-") + fb->uid() + QLatin1StringView("-") + QString::number(i));
0103 
0104         inc->setCustomProperty("FREEBUSY", "STATUS", QString::number(period.type()));
0105         QString summary = period.summary();
0106         if (summary.isEmpty()) {
0107             switch (period.type()) {
0108             case KCalendarCore::FreeBusyPeriod::Free:
0109                 summary = i18n("Free");
0110                 break;
0111             case KCalendarCore::FreeBusyPeriod::Busy:
0112                 summary = i18n("Busy");
0113                 break;
0114             case KCalendarCore::FreeBusyPeriod::BusyUnavailable:
0115                 summary = i18n("Unavailable");
0116                 break;
0117             case KCalendarCore::FreeBusyPeriod::BusyTentative:
0118                 summary = i18n("Tentative");
0119                 break;
0120             default:
0121                 summary = i18n("Unknown");
0122             }
0123         }
0124         inc->setSummary(summary);
0125 
0126         d->mFbEvent.insert(index, inc);
0127         d->mCalendar->addEvent(inc);
0128     }
0129 }
0130 
0131 void FreeBusyCalendar::onRowsRemoved(const QModelIndex &parent, int first, int last)
0132 {
0133     if (!parent.isValid()) {
0134         for (int i = first; i <= last; ++i) {
0135             QModelIndex index = d->mModel->index(i, 0);
0136             onRowsRemoved(index, 0, d->mModel->rowCount(index) - 1);
0137         }
0138     } else {
0139         for (int i = first; i <= last; ++i) {
0140             QModelIndex index = d->mModel->index(i, 0, parent);
0141             KCalendarCore::Event::Ptr inc = d->mFbEvent.take(index);
0142             d->mCalendar->deleteEvent(inc);
0143         }
0144     }
0145 }
0146 
0147 void FreeBusyCalendar::onRowsChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
0148 {
0149     if (!topLeft.parent().isValid()) {
0150         return;
0151     }
0152     for (int i = topLeft.row(); i <= bottomRight.row(); ++i) {
0153         QModelIndex index = d->mModel->index(i, 0, topLeft.parent());
0154         KCalendarCore::Event::Ptr inc = d->mFbEvent.value(index);
0155         d->mCalendar->beginChange(inc);
0156         d->mCalendar->endChange(inc);
0157     }
0158 }
0159 
0160 #include "moc_freebusycalendar.cpp"