File indexing completed on 2024-05-19 04:55:57

0001 /**
0002  * \file starratingmappingsmodel.cpp
0003  * Star rating mappings configuration table model.
0004  *
0005  * \b Project: Kid3
0006  * \author Urs Fleisch
0007  * \date 2 Jan 2018
0008  *
0009  * Copyright (C) 2018-2024  Urs Fleisch
0010  *
0011  * This file is part of Kid3.
0012  *
0013  * Kid3 is free software; you can redistribute it and/or modify
0014  * it under the terms of the GNU General Public License as published by
0015  * the Free Software Foundation; either version 2 of the License, or
0016  * (at your option) any later version.
0017  *
0018  * Kid3 is distributed in the hope that it will be useful,
0019  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0020  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0021  * GNU General Public License for more details.
0022  *
0023  * You should have received a copy of the GNU General Public License
0024  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
0025  */
0026 
0027 #include "starratingmappingsmodel.h"
0028 
0029 /** Column indices. */
0030 enum ColumnIndex {
0031   CI_Name = 0,
0032   CI_NumColumns = 6
0033 };
0034 
0035 /**
0036  * Constructor.
0037  * @param parent parent widget
0038  */
0039 StarRatingMappingsModel::StarRatingMappingsModel(QObject* parent)
0040   : QAbstractTableModel(parent)
0041 {
0042   setObjectName(QLatin1String("StarRatingMappingsModel"));
0043 }
0044 
0045 /**
0046  * Get item flags for index.
0047  * @param index model index
0048  * @return item flags
0049  */
0050 Qt::ItemFlags StarRatingMappingsModel::flags(const QModelIndex& index) const
0051 {
0052   Qt::ItemFlags theFlags = QAbstractTableModel::flags(index);
0053   if (index.isValid()) {
0054     theFlags |= Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable;
0055   }
0056   return theFlags;
0057 }
0058 
0059 /**
0060  * Get data for a given role.
0061  * @param index model index
0062  * @param role item data role
0063  * @return data for role
0064  */
0065 QVariant StarRatingMappingsModel::data(const QModelIndex& index, int role) const
0066 {
0067   if (!index.isValid() ||
0068       index.row() < 0 || index.row() >= m_maps.size() ||
0069       index.column() < 0 || index.column() >= CI_NumColumns)
0070     return QVariant();
0071   const QPair<QString, QVector<int> >& item = m_maps.at(index.row());
0072   if (role == Qt::DisplayRole || role == Qt::EditRole) {
0073     if (index.column() == CI_Name) {
0074       return item.first;
0075     }
0076     if (item.second.size() >= index.column()) {
0077       return item.second.at(index.column() - 1);
0078     }
0079   }
0080   return QVariant();
0081 }
0082 
0083 /**
0084  * Set data for a given role.
0085  * @param index model index
0086  * @param value data value
0087  * @param role item data role
0088  * @return true if successful
0089  */
0090 bool StarRatingMappingsModel::setData(const QModelIndex& index,
0091                                       const QVariant& value, int role)
0092 {
0093   if (!index.isValid() ||
0094       index.row() < 0 || index.row() >= m_maps.size() ||
0095       index.column() < 0 || index.column() >= CI_NumColumns)
0096     return false;
0097   QPair<QString, QVector<int> >& item = m_maps[index.row()]; // clazy:exclude=detaching-member
0098   bool changed = false;
0099   if (role == Qt::EditRole) {
0100     if (index.column() == CI_Name) {
0101       item.first = value.toString();
0102       changed = true;
0103     } else if (item.second.size() >= index.column()) {
0104       item.second[index.column() - 1] = value.toInt();
0105       changed = true;
0106     }
0107     if (changed) {
0108       makeRowValid(index.row());
0109       emit dataChanged(index, index);
0110     }
0111   }
0112   return changed;
0113 }
0114 
0115 /**
0116  * Get data for header section.
0117  * @param section column or row
0118  * @param orientation horizontal or vertical
0119  * @param role item data role
0120  * @return header data for role
0121  */
0122 QVariant StarRatingMappingsModel::headerData(
0123     int section, Qt::Orientation orientation, int role) const
0124 {
0125   if (role != Qt::DisplayRole)
0126     return QVariant();
0127   if (orientation == Qt::Horizontal) {
0128     if (section == CI_Name) {
0129       return tr("Name");
0130     }
0131     if (section < CI_NumColumns) {
0132       return section;
0133     }
0134   }
0135   return section + 1;
0136 }
0137 
0138 /**
0139  * Get number of rows.
0140  * @param parent parent model index, invalid for table models
0141  * @return number of rows,
0142  * if parent is valid number of children (0 for table models)
0143  */
0144 int StarRatingMappingsModel::rowCount(const QModelIndex& parent) const
0145 {
0146   return parent.isValid() ? 0 : m_maps.size();
0147 }
0148 
0149 /**
0150  * Get number of columns.
0151  * @param parent parent model index, invalid for table models
0152  * @return number of columns,
0153  * if parent is valid number of children (0 for table models)
0154  */
0155 int StarRatingMappingsModel::columnCount(const QModelIndex& parent) const
0156 {
0157   return parent.isValid() ? 0 : CI_NumColumns;
0158 }
0159 
0160 /**
0161  * Insert rows.
0162  * @param row rows are inserted before this row, if 0 at the begin,
0163  * if rowCount() at the end
0164  * @param count number of rows to insert
0165  * @return true if successful
0166  */
0167 bool StarRatingMappingsModel::insertRows(int row, int count,
0168                                          const QModelIndex&)
0169 {
0170   if (count > 0) {
0171     beginInsertRows(QModelIndex(), row, row + count - 1);
0172     for (int i = 0; i < count; ++i) {
0173       m_maps.insert(row, qMakePair(QString(), QVector<int>(CI_NumColumns - 1)));
0174       makeRowValid(row);
0175     }
0176     endInsertRows();
0177   }
0178   return true;
0179 }
0180 
0181 /**
0182  * Remove rows.
0183  * @param row rows are removed starting with this row
0184  * @param count number of rows to remove
0185  * @return true if successful
0186  */
0187 bool StarRatingMappingsModel::removeRows(int row, int count,
0188                         const QModelIndex&)
0189 {
0190   if (count > 0) {
0191     beginRemoveRows(QModelIndex(), row, row + count - 1);
0192     for (int i = 0; i < count; ++i)
0193       m_maps.removeAt(row);
0194     endRemoveRows();
0195   }
0196   return true;
0197 }
0198 
0199 /**
0200  * Set the model from the star count mappings.
0201  * @param maps star count mappings
0202  */
0203 void StarRatingMappingsModel::setMappings(
0204     const QList<QPair<QString, QVector<int> > >& maps)
0205 {
0206   beginResetModel();
0207   m_maps = maps;
0208   endResetModel();
0209 }
0210 
0211 /**
0212  * Get the start count mappings from the model.
0213  * @return star count mappings
0214  */
0215 QList<QPair<QString, QVector<int> > > StarRatingMappingsModel::getMappings() const
0216 {
0217   return m_maps;
0218 }
0219 
0220 /**
0221  * Make sure that @a row contains valid values.
0222  */
0223 void StarRatingMappingsModel::makeRowValid(int row)
0224 {
0225   QString& type = m_maps[row].first; // clazy:exclude=detaching-member
0226   type = type.trimmed();
0227   if (type == QLatin1String("POPM.")) {
0228     type.truncate(4);
0229   }
0230   QVector<int>& values = m_maps[row].second; // clazy:exclude=detaching-member
0231   int previousValue = 0;
0232   for (auto it = values.begin(); it != values.end(); ++it) {
0233     if (*it <= previousValue) {
0234       *it = previousValue + 1;
0235     }
0236     previousValue = *it;
0237   }
0238 }