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 }