File indexing completed on 2022-09-27 16:37:29

0001 // SPDX-FileCopyrightText: 2022 Felipe Kinoshita <kinofhek@gmail.com>
0002 // SPDX-License-Identifier: LGPL-2.1-or-later
0003 
0004 #include "tasksmodel.h"
0005 
0006 #include <QStandardPaths>
0007 #include <QFile>
0008 #include <QDir>
0009 
0010 #include <QJsonArray>
0011 #include <QJsonDocument>
0012 #include <QJsonObject>
0013 
0014 TasksModel::TasksModel(QObject *parent)
0015     : QAbstractListModel(parent)
0016 {
0017     loadTasks();
0018 }
0019 
0020 QHash<int, QByteArray> TasksModel::roleNames() const
0021 {
0022     return {
0023         {Roles::TitleRole, QByteArrayLiteral("title")},
0024         {Roles::CheckedRole, QByteArrayLiteral("checked")}
0025     };
0026 }
0027 
0028 QVariant TasksModel::data(const QModelIndex &index, int role) const
0029 {
0030     if (!index.isValid() || index.row() < 0 || index.row() >= m_tasks.count()) {
0031         return {};
0032     }
0033 
0034     auto task = m_tasks.at(index.row());
0035 
0036     switch (role) {
0037     case Roles::TitleRole:
0038         return task.title();
0039     case Roles::CheckedRole:
0040         return task.checked();
0041     }
0042 
0043     return {};
0044 }
0045 
0046 int TasksModel::rowCount(const QModelIndex &parent) const
0047 {
0048     Q_UNUSED(parent)
0049     return m_tasks.size();
0050 }
0051 
0052 bool TasksModel::setData(const QModelIndex &index, const QVariant &value, int role)
0053 {
0054     if (index.row() < 0 || index.row() >= m_tasks.count()) {
0055         return false;
0056     }
0057 
0058     auto& task = m_tasks[index.row()];
0059 
0060     switch (role) {
0061         case Roles::CheckedRole:
0062             task.setChecked(value.toBool());
0063             break;
0064         case Roles::TitleRole:
0065             task.setTitle(value.toString());
0066             break;
0067     }
0068 
0069     emit dataChanged(index, index, { role });
0070 
0071     saveTasks();
0072 
0073     return true;
0074 }
0075 
0076 void TasksModel::add(const QString &title)
0077 {
0078     Task t(title, false);
0079 
0080     beginInsertRows(QModelIndex(), m_tasks.count(), m_tasks.count());
0081     m_tasks.append(t);
0082     endInsertRows();
0083 
0084     saveTasks();
0085 }
0086 
0087 void TasksModel::remove(const int &index)
0088 {
0089     if (index < 0 || index > m_tasks.count()) {
0090         return;
0091     }
0092 
0093     beginRemoveRows(QModelIndex(), index, index);
0094     m_tasks.removeAt(index);
0095     endRemoveRows();
0096 
0097     saveTasks();
0098 }
0099 
0100 void TasksModel::clear()
0101 {
0102     beginResetModel();
0103     m_tasks.clear();
0104     endResetModel();
0105 
0106     saveTasks();
0107 }
0108 
0109 bool TasksModel::saveTasks() const
0110 {
0111     const QString outputDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
0112 
0113     QFile outputFile(outputDir + QStringLiteral("/tasks.json"));
0114     if (!QDir(outputDir).mkpath(QStringLiteral("."))) {
0115         qDebug() << "Destdir doesn't exist and I can't create it: " << outputDir;
0116         return false;
0117     }
0118     if (!outputFile.open(QIODevice::WriteOnly)) {
0119         qDebug() << "Failed to write tabs to disk";
0120     }
0121 
0122     QJsonArray tasksArray;
0123     std::transform(m_tasks.cbegin(), m_tasks.cend(), std::back_inserter(tasksArray), [](const Task &task) {
0124         return task.toJson();
0125     });
0126 
0127     qDebug() << "Wrote to file" << outputFile.fileName() << "(" << tasksArray.count() << "tasks" << ")";
0128 
0129     const QJsonDocument document({QLatin1String("tasks"), tasksArray});
0130 
0131     outputFile.write(document.toJson());
0132 
0133     return true;
0134 }
0135 
0136 bool TasksModel::loadTasks()
0137 {
0138     beginResetModel();
0139 
0140     const QString input = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QStringLiteral("/tasks.json");
0141 
0142     QFile inputFile(input);
0143     if (!inputFile.exists()) {
0144         return false;
0145     }
0146 
0147     if (!inputFile.open(QIODevice::ReadOnly)) {
0148         qDebug() << "Failed to load tabs from disk";
0149     }
0150 
0151     const auto tasksStorage = QJsonDocument::fromJson(inputFile.readAll()).object();
0152     m_tasks.clear();
0153 
0154     const auto tasks = tasksStorage.value(QLatin1String("tasks")).toArray();
0155 
0156     std::transform(tasks.cbegin(), tasks.cend(), std::back_inserter(m_tasks), [](const QJsonValue &task) {
0157         return Task::fromJson(task.toObject());
0158     });
0159 
0160     qDebug() << "loaded from file:" << m_tasks.count() << input;
0161 
0162     endResetModel();
0163 
0164     return true;
0165 }