File indexing completed on 2024-05-12 05:54:14

0001 /*
0002     SPDX-FileCopyrightText: 2015 Elvis Angelaccio <elvis.angelaccio@kde.org>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "sessionmodel.h"
0008 
0009 #include <KLocalizedString>
0010 
0011 #include <QDebug>
0012 #include <QFile>
0013 #include <QJsonArray>
0014 #include <QJsonDocument>
0015 #include <QJsonObject>
0016 #include <QStandardPaths>
0017 
0018 SessionModel::SessionModel(QObject *parent) : QAbstractTableModel(parent)
0019 {
0020     QFile saveFile {QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + QLatin1String("/sessions.json")};
0021     if (saveFile.exists()) {
0022         if (saveFile.open(QIODevice::ReadOnly)) {
0023             auto saveData = saveFile.readAll();
0024             auto saveDoc = QJsonDocument::fromJson(saveData);
0025             read(saveDoc.object());
0026         } else {
0027             qDebug().nospace() << "cannot open " << saveFile.fileName() << ": " << saveFile.errorString();
0028         }
0029     }
0030 
0031     connect(this, &QAbstractTableModel::dataChanged, this, &SessionModel::slotWriteData);
0032     connect(this, &QAbstractTableModel::rowsInserted, this, &SessionModel::slotWriteData);
0033     connect(this, &QAbstractTableModel::rowsRemoved, this, &SessionModel::slotWriteData);
0034 }
0035 
0036 int SessionModel::columnCount(const QModelIndex& parent) const
0037 {
0038     Q_UNUSED(parent)
0039 
0040     return m_roles.count();
0041 }
0042 
0043 int SessionModel::rowCount(const QModelIndex& parent) const
0044 {
0045     Q_UNUSED(parent)
0046 
0047     return m_sessionList.size();
0048 }
0049 
0050 QVariant SessionModel::data(const QModelIndex& index, int role) const
0051 {
0052     if (!index.isValid()) {
0053         return QVariant::Invalid;
0054     }
0055 
0056     if (index.row() >= rowCount() || index.row() < 0) {
0057         return QVariant::Invalid;
0058     }
0059 
0060     if (role == Qt::DisplayRole) {
0061         return data(index, Qt::UserRole + index.column());
0062     }
0063 
0064     switch (static_cast<Roles>(role)) {
0065     case Roles::SessionIdRole:
0066         return QString::number(index.row() + 1);
0067     case Roles::NameRole:
0068         return m_sessionList.at(index.row()).name();
0069     case Roles::DateRole:
0070         return m_sessionList.at(index.row()).date();
0071     case Roles::NoteRole:
0072         return m_sessionList.at(index.row()).note();
0073     case Roles::SessionRole:
0074         return QVariant::fromValue(m_sessionList.at(index.row()));
0075     }
0076 
0077     if (role == Qt::EditRole && index.column() == columnForRole(Roles::NameRole)) {
0078         // prevent the disappear of the old value when double-clicking the item
0079         return m_sessionList.at(index.row()).name();
0080     }
0081 
0082     if (role == Qt::EditRole && index.column() == columnForRole(Roles::NoteRole)) {
0083         return m_sessionList.at(index.row()).note();
0084     }
0085 
0086     return QVariant::Invalid;
0087 }
0088 
0089 
0090 QVariant SessionModel::headerData(int section, Qt::Orientation orientation, int role) const
0091 {
0092     if (role != Qt::DisplayRole || orientation != Qt::Horizontal)
0093         return QVariant::Invalid;
0094 
0095     switch (roleForColumn(section)) {
0096     case Roles::SessionIdRole:
0097         return i18nc("session number", "Session #");
0098     case Roles::NameRole:
0099         return i18n("Name");
0100     case Roles::DateRole:
0101         return i18n("Date");
0102     case Roles::NoteRole:
0103         return i18n("Note");
0104     case Roles::SessionRole:
0105         break;
0106     }
0107 
0108     return QVariant::Invalid;
0109 }
0110 
0111 bool SessionModel::setData(const QModelIndex& index, const QVariant& value, int role)
0112 {
0113     if (!index.isValid() || role != Qt::EditRole)
0114         return false;
0115 
0116     if (index.column() == columnForRole(Roles::NameRole)) {
0117         if (value.toString().isEmpty())
0118             return false;
0119 
0120         m_sessionList[index.row()].setName(value.toString());
0121         Q_EMIT dataChanged(index, index);
0122 
0123         return true;
0124     }
0125 
0126     if (index.column() == columnForRole(Roles::NoteRole)) {
0127         m_sessionList[index.row()].setNote(value.toString());
0128         Q_EMIT dataChanged(index, index);
0129 
0130         return true;
0131     }
0132 
0133     return false;
0134 }
0135 
0136 Qt::ItemFlags SessionModel::flags(const QModelIndex& index) const
0137 {
0138     if (!index.isValid())
0139         return Qt::ItemIsEnabled;
0140 
0141     if (isEditable(index))
0142         return QAbstractTableModel::flags(index) | Qt::ItemIsEditable;
0143 
0144     return QAbstractTableModel::flags(index);
0145 }
0146 
0147 bool SessionModel::removeRows(int row, int count, const QModelIndex& parent)
0148 {
0149     if (row < 0 || row + count - 1 >= rowCount())
0150         return false;
0151 
0152     beginRemoveRows(parent, row, row + count - 1);
0153 
0154     for (int i = 0; i < count; i++) {
0155         m_sessionList.removeAt(row);
0156     }
0157 
0158     endRemoveRows();
0159 
0160     return true;
0161 }
0162 
0163 void SessionModel::append(const Session& session)
0164 {
0165     beginInsertRows(QModelIndex(), rowCount(), rowCount());    // i.e. append the new row at the table end
0166     m_sessionList.append(session);
0167     endInsertRows();
0168 }
0169 
0170 void SessionModel::update(Session& session)
0171 {
0172     int i = m_sessionList.indexOf(session);
0173 
0174     if (i == -1)
0175         return;
0176 
0177     session.setDate(QDateTime::currentDateTime());
0178     m_sessionList[i] = session;
0179 
0180     Q_EMIT dataChanged({}, {});
0181 }
0182 
0183 bool SessionModel::isEmpty() const
0184 {
0185     return m_sessionList.isEmpty();
0186 }
0187 
0188 bool SessionModel::isEditable(const QModelIndex& index) const
0189 {
0190     auto role = roleForColumn(index.column());
0191     return role == Roles::NameRole || role == Roles::NoteRole;
0192 }
0193 
0194 void SessionModel::read(const QJsonObject& json)
0195 {
0196     const auto sessions = json[QStringLiteral("sessions")].toArray();
0197     for (const auto& session : sessions) {
0198         append(Session::fromJson(session.toObject()));
0199     }
0200 }
0201 
0202 void SessionModel::slotWriteData()
0203 {
0204     QFile saveFile {QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + QLatin1String("/sessions.json")};
0205     if (!saveFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
0206         qDebug().nospace() << "cannot open " << saveFile.fileName() << ": " << saveFile.errorString();
0207         return;
0208     }
0209 
0210     auto json = QJsonObject {};
0211     json[QStringLiteral("sessions")] = jsonSessions();
0212 
0213     auto saveDoc = QJsonDocument {json};
0214     saveFile.write(saveDoc.toJson());
0215 }
0216 
0217 int SessionModel::columnForRole(SessionModel::Roles role) const
0218 {
0219     return m_roles.indexOf(role);
0220 }
0221 
0222 SessionModel::Roles SessionModel::roleForColumn(int column) const
0223 {
0224     return m_roles.at(column);
0225 }
0226 
0227 QJsonArray SessionModel::jsonSessions() const
0228 {
0229     auto array = QJsonArray {};
0230     const auto sessions = m_sessionList;
0231     for (const auto& session : sessions) {
0232         auto object = QJsonObject {};
0233         session.write(object);
0234         array.append(object);
0235     }
0236 
0237     return array;
0238 }
0239 
0240 
0241 #include "moc_sessionmodel.cpp"