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 "projectmodel.h"
0022 
0023 #include "event.h"
0024 #include "eventsmodel.h"
0025 #include "import/plannerparser.h"
0026 #include "ktt_debug.h"
0027 #include "task.h"
0028 #include "tasksmodel.h"
0029 
0030 ProjectModel::ProjectModel()
0031     : m_tasksModel(new TasksModel())
0032     , m_eventsModel(new EventsModel())
0033 {
0034 }
0035 
0036 TasksModel *ProjectModel::tasksModel()
0037 {
0038     return m_tasksModel;
0039 }
0040 
0041 EventsModel *ProjectModel::eventsModel()
0042 {
0043     return m_eventsModel;
0044 }
0045 
0046 std::unique_ptr<FileCalendar> ProjectModel::asCalendar(const QUrl &url) const
0047 {
0048     std::unique_ptr<FileCalendar> calendar(new FileCalendar(url));
0049     for (auto *item : m_tasksModel->getAllItems()) {
0050         Task *task = dynamic_cast<Task *>(item);
0051 
0052         KCalendarCore::Todo::Ptr todo(new KCalendarCore::Todo());
0053         calendar->addTodo(task->asTodo(todo));
0054     }
0055 
0056 
0057     // TODO: Use libkcalcore comments
0058     // todo->addComment(comment);
0059     // temporary
0060 //     todo->setDescription(task->comment());
0061 
0062 
0063     for (Event *event : m_eventsModel->events()) {
0064         KCalendarCore::Event::Ptr calEvent(new KCalendarCore::Event());
0065         calendar->addEvent(event->asCalendarEvent(calEvent));
0066     }
0067 
0068     return calendar;
0069 }
0070 
0071 void ProjectModel::resetTimeForAllTasks()
0072 {
0073     for (Task *task : tasksModel()->getAllTasks()) {
0074         task->resetTimes();
0075     }
0076 
0077     eventsModel()->clear();
0078 }
0079 
0080 void ProjectModel::importPlanner(const QString &fileName, Task *currentTask)
0081 {
0082     auto *handler = new PlannerParser(this, currentTask);
0083     QFile xmlFile(fileName);
0084     QXmlInputSource source(&xmlFile);
0085     QXmlSimpleReader reader;
0086     reader.setContentHandler(handler);
0087     reader.parse(source);
0088 
0089     refresh();
0090 }
0091 
0092 void ProjectModel::refresh()
0093 {
0094     for (Task *task : tasksModel()->getAllTasks()) {
0095         task->invalidateCompletedState();
0096         task->update(); // maybe there was a change in the times's format
0097     }
0098 }
0099 
0100 void ProjectModel::refreshTimes()
0101 {
0102     // This procedure resets all times (session and overall) for all tasks and subtasks.
0103     // Reset session and total time for all tasks - do not touch the storage.
0104     for (Task *task : tasksModel()->getAllTasks()) {
0105         task->resetTimes();
0106     }
0107 
0108     for (Task *task : tasksModel()->getAllTasks()) {
0109         // get all events for task
0110         for (const auto *event : eventsModel()->eventsForTask(task)) {
0111             QDateTime eventStart = event->dtStart();
0112             QDateTime eventEnd = event->dtEnd();
0113 
0114             const int64_t duration = event->duration() / 60;
0115             task->addTime(duration);
0116             qCDebug(KTT_LOG) << "duration is" << duration;
0117 
0118             if (task->sessionStartTiMe().isValid()) {
0119                 // if there is a session
0120                 if (task->sessionStartTiMe().secsTo(eventStart) > 0 && task->sessionStartTiMe().secsTo(eventEnd) > 0) {
0121                     // if the event is after the session start
0122                     task->addSessionTime(duration);
0123                 }
0124             } else {
0125                 // so there is no session at all
0126                 task->addSessionTime(duration);
0127             }
0128         }
0129     }
0130 
0131     // Recalculate total times after changing hierarchy by drag&drop
0132     for (Task *task : tasksModel()->getAllTasks()) {
0133         // Start recursive method recalculateTotalTimesSubtree() for each top-level task.
0134         if (task->isRoot()) {
0135             task->recalculateTotalTimesSubtree();
0136         }
0137     }
0138 
0139     refresh();
0140 }