File indexing completed on 2024-11-17 04:49:33

0001 /*
0002  * Copyright (c) 2019 Alexander Potashev <aspotashev@gmail.com>
0003  *
0004  * This program is free software; you can redistribute it and/or
0005  * modify it under the terms of the GNU General Public License as
0006  * published by the Free Software Foundation; either version 2 of
0007  * the License or (at your option) version 3 or any later version
0008  * accepted by the membership of KDE e.V. (or its successor approved
0009  * by the membership of KDE e.V.), which shall act as a proxy
0010  * defined in Section 14 of version 3 of the license.
0011  *
0012  * This program is distributed in the hope that it will be useful,
0013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0015  * GNU General Public License for more details.
0016  *
0017  * You should have received a copy of the GNU General Public License
0018  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
0019  */
0020 
0021 #include "eventsmodel.h"
0022 
0023 #include <KLocalizedString>
0024 
0025 #include "ktt_debug.h"
0026 #include "task.h"
0027 
0028 void EventsModel::load(const KCalendarCore::Event::List &events)
0029 {
0030     clear();
0031 
0032     for (const auto &event : events) {
0033         m_events.append(new Event(event));
0034     }
0035 }
0036 
0037 EventsModel::~EventsModel()
0038 {
0039     clear();
0040 }
0041 
0042 QList<Event *> EventsModel::events() const
0043 {
0044     return m_events;
0045 }
0046 
0047 QList<Event *> EventsModel::eventsForTask(const Task *task) const
0048 {
0049     QList<Event *> res;
0050     for (auto *event : events()) {
0051         if (event->relatedTo() == task->uid()) {
0052             res.append(event);
0053         }
0054     }
0055 
0056     return res;
0057 }
0058 
0059 Event *EventsModel::eventByUID(const QString &uid) const
0060 {
0061     for (auto *event : events()) {
0062         if (event->uid() == uid) {
0063             return event;
0064         }
0065     }
0066 
0067     return nullptr;
0068 }
0069 
0070 void EventsModel::clear()
0071 {
0072     for (auto *event : m_events) {
0073         delete event;
0074     }
0075     m_events.clear();
0076 }
0077 
0078 void EventsModel::removeAllForTask(const Task *task)
0079 {
0080     for (auto it = m_events.begin(); it != m_events.end();) {
0081         Event *event = *it;
0082         if (event->relatedTo() == task->uid()) {
0083             delete event;
0084             it = m_events.erase(it);
0085         } else {
0086             ++it;
0087         }
0088     }
0089 }
0090 
0091 void EventsModel::removeByUID(const QString &uid)
0092 {
0093     for (auto it = m_events.begin(); it != m_events.end(); ++it) {
0094         Event *event = *it;
0095         if (event->uid() == uid) {
0096             delete event;
0097             m_events.erase(it);
0098             return;
0099         }
0100     }
0101 }
0102 
0103 void EventsModel::addEvent(Event *event)
0104 {
0105     m_events.append(event);
0106 }
0107 
0108 static KCalendarCore::Event::Ptr baseEvent(const Task *task)
0109 {
0110     qCDebug(KTT_LOG) << "Entering function";
0111     KCalendarCore::Event::Ptr e(new KCalendarCore::Event());
0112     QStringList categories;
0113     e->setSummary(task->name());
0114 
0115     // Can't use setRelatedToUid()--no error, but no RelatedTo written to disk
0116     e->setRelatedTo(task->uid());
0117 
0118     // Debugging: some events where not getting a related-to field written.
0119     Q_ASSERT(e->relatedTo() == task->uid());
0120 
0121     // Have to turn this off to get datetimes in date fields.
0122     e->setAllDay(false);
0123     e->setDtStart(task->startTime());
0124 
0125     // So someone can filter this mess out of their calendar display
0126     categories.append(i18n("KTimeTracker"));
0127     e->setCategories(categories);
0128 
0129     return e;
0130 }
0131 
0132 void EventsModel::changeTime(const Task *task, int64_t deltaSeconds)
0133 {
0134     qCDebug(KTT_LOG) << "Entering function; deltaSeconds=" << deltaSeconds;
0135     QDateTime end;
0136     auto kcalEvent = baseEvent(task);
0137     auto *e = new Event(kcalEvent);
0138 
0139     // Don't use duration, as ICalFormatImpl::writeIncidence never writes a
0140     // duration, even though it looks like it's used in event.cpp.
0141     end = task->startTime();
0142     if (deltaSeconds > 0) {
0143         end = task->startTime().addSecs(deltaSeconds);
0144     }
0145     e->setDtEnd(end);
0146 
0147     // Use a custom property to keep a record of negative durations
0148     e->setDuration(deltaSeconds);
0149 
0150     addEvent(e);
0151 }
0152 
0153 bool EventsModel::bookTime(const Task *task, const QDateTime &startDateTime, int64_t durationInSeconds)
0154 {
0155     qCDebug(KTT_LOG) << "Entering function";
0156 
0157     auto kcalEvent = baseEvent(task);
0158     auto *e = new Event(kcalEvent);
0159 
0160     e->setDtStart(startDateTime);
0161     e->setDtEnd(startDateTime.addSecs(durationInSeconds));
0162 
0163     // Use a custom property to keep a record of negative durations
0164     e->setDuration(durationInSeconds);
0165 
0166     addEvent(e);
0167     return true;
0168 }
0169 
0170 void EventsModel::startTask(const Task *task)
0171 {
0172     auto *e = new Event(baseEvent(task));
0173 
0174     // TODO support passing of a different start time from TimeTrackerStorage::buildTaskView?
0175     e->setDtStart(QDateTime::currentDateTime());
0176     addEvent(e);
0177 }
0178 
0179 void EventsModel::stopTask(const Task *task, const QDateTime &when)
0180 {
0181     QList<Event *> openEvents;
0182     for (auto *event : eventsForTask(task)) {
0183         if (!event->hasEndDate()) {
0184             openEvents.append(event);
0185         }
0186     }
0187 
0188     if (openEvents.isEmpty()) {
0189         qCWarning(KTT_LOG) << "Task to stop has no open events, uid=" << task->uid() << ", name=" << task->name();
0190     } else if (openEvents.size() > 1) {
0191         qCWarning(KTT_LOG) << "Task to stop has multiple open events (" << openEvents.size() << "), uid=" << task->uid() << ", name=" << task->name();
0192     }
0193 
0194     for (auto *event : openEvents) {
0195         qCDebug(KTT_LOG) << "found an event for task, event=" << event->uid();
0196         event->setDtEnd(when);
0197     }
0198 }
0199 
0200 #include "moc_eventsmodel.cpp"