File indexing completed on 2024-05-19 16:51:56

0001 /*
0002     Copyright (C) 2014 by Elvis Angelaccio <elvis.angelaccio@kde.org>
0003 
0004     This file is part of Kronometer.
0005 
0006     Kronometer is free software: you can redistribute it and/or modify
0007     it under the terms of the GNU General Public License as published by
0008     the Free Software Foundation, either version 2 of the License, or
0009     (at your option) any later version.
0010 
0011     Kronometer is distributed in the hope that it will be useful,
0012     but WITHOUT ANY WARRANTY; without even the implied warranty of
0013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0014     GNU General Public License for more details.
0015 
0016     You should have received a copy of the GNU General Public License
0017     along with Kronometer.  If not, see <http://www.gnu.org/licenses/>.
0018 */
0019 
0020 #include "lapmodel.h"
0021 
0022 #include <KLocalizedString>
0023 
0024 #include <QTime>
0025 
0026 LapModel::LapModel(QObject* parent) : QAbstractTableModel(parent)
0027 {}
0028 
0029 int LapModel::columnCount(const QModelIndex& parent) const
0030 {
0031     Q_UNUSED(parent)
0032 
0033     return m_roles.count();
0034 }
0035 
0036 int LapModel::rowCount(const QModelIndex& parent) const
0037 {
0038     Q_UNUSED(parent)
0039 
0040     return m_laps.size();
0041 }
0042 
0043 QVariant LapModel::data(const QModelIndex& index, int role) const
0044 {
0045     if (not index.isValid()) {
0046         return QVariant::Invalid;
0047     }
0048 
0049     if (index.row() >= rowCount() or index.row() < 0) {
0050         return QVariant::Invalid;
0051     }
0052 
0053     if (role == Qt::DisplayRole) {
0054         return data(index, Qt::UserRole + index.column());
0055     }
0056 
0057     switch (static_cast<Roles>(role)) {
0058     case Roles::LapIdRole:
0059         return index.row() + 1;
0060     case Roles::RelativeTimeRole:
0061         return m_laps.at(index.row()).relativeTime();
0062     case Roles::AbsoluteTimeRole:
0063         return m_laps.at(index.row()).absoluteTime();
0064     case Roles::NoteRole:
0065         return m_laps.at(index.row()).note();
0066     case Roles::LapRole:
0067         return QVariant::fromValue(m_laps.at(index.row()));
0068     }
0069 
0070     if (role == Qt::EditRole && index.column() == columnForRole(Roles::NoteRole)) {
0071         // prevent the disappear of the old value when double-clicking the item
0072         return m_laps.at(index.row()).note();
0073     }
0074 
0075     return QVariant::Invalid;
0076 }
0077 
0078 QVariant LapModel::headerData(int section, Qt::Orientation orientation, int role) const
0079 {
0080     if (role != Qt::DisplayRole or orientation != Qt::Horizontal)
0081         return QVariant::Invalid;
0082 
0083     switch (roleForColumn(section)) {
0084     case Roles::LapIdRole:
0085         return i18nc("lap number", "Lap #");
0086     case Roles::RelativeTimeRole:
0087         return i18nc("@title:column", "Lap Time");
0088     case Roles::AbsoluteTimeRole:
0089         return i18nc("@title:column", "Global Time");
0090     case Roles::NoteRole:
0091         return i18nc("@title:column", "Note");
0092     case Roles::LapRole:
0093         break;
0094     }
0095 
0096     return QVariant::Invalid;
0097 }
0098 
0099 bool LapModel::setData(const QModelIndex& index, const QVariant& value, int role)
0100 {
0101     if (not index.isValid() or role != Qt::EditRole)
0102         return false;
0103 
0104     if (index.column() != columnForRole(Roles::NoteRole))
0105         return false;
0106 
0107     m_laps[index.row()].setNote(value.toString());
0108     emit dataChanged(index, index);
0109 
0110     return true;
0111 }
0112 
0113 Qt::ItemFlags LapModel::flags(const QModelIndex& index) const
0114 {
0115     if (not index.isValid())
0116         return Qt::ItemIsEnabled;
0117 
0118     if (index.column() != columnForRole(Roles::NoteRole))
0119         return QAbstractTableModel::flags(index);
0120 
0121     return QAbstractTableModel::flags(index) | Qt::ItemIsEditable;
0122 }
0123 
0124 void LapModel::setTimeFormat(const TimeFormat& format)
0125 {
0126     m_timeFormat = format;
0127 
0128     if (not isEmpty()) {
0129         reload();
0130     }
0131 }
0132 
0133 void LapModel::append(const Lap& lap)
0134 {
0135     // Append the new row at the end.
0136     beginInsertRows(QModelIndex(), rowCount(), rowCount());
0137 
0138     // Either the time of the first lap or the time relative to the last lap.
0139     const auto relativeTime = m_laps.isEmpty() ? lap.time() : m_laps.last().timeTo(lap);
0140 
0141     auto newLap = Lap {lap};
0142     newLap.setRelativeTime(m_timeFormat.format(relativeTime));
0143     newLap.setAbsoluteTime(m_timeFormat.format(newLap.time()));
0144 
0145     m_laps.append(newLap);
0146     endInsertRows();
0147 }
0148 
0149 bool LapModel::isEmpty() const
0150 {
0151     return m_laps.isEmpty();
0152 }
0153 
0154 int LapModel::columnForRole(LapModel::Roles role) const
0155 {
0156     return m_roles.indexOf(role);
0157 }
0158 
0159 void LapModel::addLap(const QTime& lapTime)
0160 {
0161     append(Lap {lapTime});
0162 }
0163 
0164 void LapModel::clear()
0165 {
0166     beginResetModel();
0167     m_laps.clear();
0168     endResetModel();
0169 }
0170 
0171 void LapModel::reload()
0172 {
0173     const auto laps = m_laps;
0174     clear();
0175 
0176     for (const auto& lap : laps) {
0177         append(lap);
0178     }
0179 }
0180 
0181 LapModel::Roles LapModel::roleForColumn(int column) const
0182 {
0183     return m_roles.at(column);
0184 }