LCOV - code coverage report
Current view: top level - src/models - ListModel.cpp (source / functions) Coverage Total Hit
Test: coverage.info.cleaned Lines: 28.8 % 146 42
Test Date: 2026-01-27 22:31:25 Functions: 36.0 % 25 9

            Line data    Source code
       1              : /*
       2              :  * Author: Christophe Dumez <dchris@gmail.com>
       3              :  * License: Public domain (No attribution required)
       4              :  * Website: http://cdumez.blogspot.com/
       5              :  * Version: 1.0
       6              :  */
       7              :  
       8              : #include "ListModel.h"
       9              : 
      10              : #include <QDebug>
      11              :  
      12           16 : ListModel::ListModel(ListItem* prototype, QObject *parent) :
      13           16 :     QAbstractListModel(parent), m_prototype(prototype), _selected(nullptr)
      14              : {
      15              :     // Populate our _roleNames reverse lookup map.
      16           16 :     QHash<int, QByteArray> roleNames = m_prototype->roleNames();
      17          320 :     for (int roleIndex : roleNames.keys()) {
      18          304 :         _roleNames[ roleNames[roleIndex] ] = roleIndex;
      19           16 :     }
      20           16 : }
      21              :  
      22          267 : int ListModel::rowCount(const QModelIndex &parent) const
      23              : {
      24              :     Q_UNUSED(parent);
      25          267 :     return m_list.size();
      26              : }
      27              : 
      28            0 : QVariant ListModel::data(const QModelIndex &index, int role) const
      29              : {
      30            0 :     if(index.row() < 0 || index.row() >= m_list.size()) {
      31            0 :         return QVariant();
      32              :     }
      33              : 
      34            0 :     int indexRow = index.row();
      35            0 :     int maxRows = rowCount();
      36            0 :     return m_list.at(indexRow)->data(role);
      37              : }
      38              : 
      39            0 : QVariant ListModel::dataByField(int row, const QString &field_name) const
      40              : {
      41            0 :     if(row < 0 || row >= m_list.size()) {
      42            0 :       return QVariant();
      43              :     }
      44              : 
      45            0 :     int roleIndex = roleNameToRole(field_name);
      46            0 :     if (roleIndex < 0) {
      47            0 :         qCritical() << "ListModel::dataByField: Invalid field name" << field_name;
      48            0 :         return QVariant();
      49              :     }
      50              : 
      51            0 :     return m_list.at(row)->data(roleIndex);
      52              : }
      53              : 
      54            0 : bool ListModel::setData(const QModelIndex &index, const QVariant &value, int role)
      55              : {
      56            0 :     if(index.row() < 0 || index.row() >= m_list.size()) {
      57            0 :       return false;
      58              :     }
      59              :     
      60            0 :     return m_list.at(index.row())->setData(value, role);
      61              : }
      62              : 
      63            0 : void ListModel::setData(int row, const QString &field_name, QVariant new_value)
      64              : {
      65            0 :     if (row < 0 || row >= m_list.size()) {
      66            0 :       return;
      67              :     }
      68              :     
      69            0 :     QHash<int, QByteArray> roleNames = m_list.at(row)->roleNames();
      70            0 :     for (int roleIndex : roleNames.keys()) {
      71            0 :         if (field_name == roleNames[roleIndex]) {
      72            0 :              m_list.at(row)->setData(new_value, roleIndex);
      73              : 
      74            0 :             return;
      75              :         }
      76            0 :     }
      77              : 
      78            0 :     int roleIndex = roleNameToRole(field_name);
      79            0 :     if (roleIndex < 0) {
      80            0 :         qCritical() << "ListModel::setData: Invalid field name" << field_name;
      81            0 :         return;
      82              :     }
      83            0 :     m_list.at(row)->setData(new_value, roleIndex);
      84            0 : }
      85              : 
      86            0 : Qt::ItemFlags ListModel::flags(const QModelIndex &index) const
      87              : {
      88            0 :     if(index.row() < 0 || index.row() >= m_list.size()) {
      89            0 :       return Qt::NoItemFlags;
      90              :     }
      91              :     
      92            0 :     return m_list.at(index.row())->flags();
      93              : }
      94              : 
      95            0 : void ListModel::move(int from, int to)
      96              : {
      97              :     // From: https://qt.gitorious.org/qt-labs/qml-object-model/source/7c2207640a65dc59a420ebf71a45e38350840313:qobjectlistmodel.cpp
      98            0 :     if (!beginMoveRows(QModelIndex(), from, from, QModelIndex(), to > from ? to+1 : to)) {
      99            0 :         return;
     100              :     }
     101              :     
     102            0 :     m_list.move(from, to);
     103            0 :     endMoveRows();
     104              : }
     105              :  
     106           24 : ListModel::~ListModel() {
     107           16 :   delete m_prototype;
     108           16 :   clear();
     109           24 : }
     110              :  
     111           30 : void ListModel::appendRow(ListItem *item)
     112              : {
     113           30 :   appendRows(QList<ListItem*>() << item);
     114           30 : }
     115              :  
     116           30 : void ListModel::appendRows(const QList<ListItem *> &items)
     117              : {
     118           30 :   beginInsertRows(QModelIndex(), rowCount(), rowCount()+items.size()-1);
     119           60 :   for (ListItem *item : items) {
     120           30 :     connect(item, &ListItem::dataChanged, this, &ListModel::handleItemChange);
     121           30 :     m_list.append(item);
     122              :   }
     123           30 :   endInsertRows();
     124              :   
     125           60 :   for (ListItem* item : items) {
     126           30 :       emit added(item);
     127              :   }
     128              :   
     129           30 :   emit countChanged(count());
     130           30 : }
     131              :  
     132            0 : void ListModel::insertRow(int row, ListItem *item)
     133              : {
     134            0 :   beginInsertRows(QModelIndex(), row, row);
     135            0 :   connect(item, &ListItem::dataChanged, this, &ListModel::handleItemChange);
     136            0 :   m_list.insert(row, item);
     137            0 :   endInsertRows();
     138              :   
     139            0 :   emit added(item);
     140              :   
     141            0 :   emit countChanged(count());
     142            0 : }
     143              :  
     144           73 : void ListModel::handleItemChange()
     145              : {
     146           73 :   ListItem* item = static_cast<ListItem*>(sender());
     147           73 :   QModelIndex index = indexFromItem(item);
     148           73 :   if(index.isValid()) {
     149           73 :     emit dataChanged(index, index);
     150              :   }
     151           73 : }
     152              :  
     153            0 : ListItem * ListModel::find(const QString &id) const
     154              : {
     155            0 :   for (ListItem* item : m_list) {
     156            0 :     if(item->id() == id) return item;
     157              :   }
     158            0 :   return 0;
     159              : }
     160              :  
     161           73 : QModelIndex ListModel::indexFromItem(const ListItem *item) const
     162              : {
     163           73 :   if (!item) {
     164            0 :       qCritical() << "ListModel::indexFromItem: item is null";
     165            0 :       return QModelIndex();
     166              :   }
     167          185 :   for(int row=0; row<m_list.size(); ++row) {
     168          185 :       if(m_list.at(row) == item) return index(row);
     169              :   }
     170            0 :   return QModelIndex();
     171              : }
     172              :  
     173           16 : void ListModel::clear()
     174              : {
     175           46 :     for (ListItem* item : m_list) {
     176           30 :         emit removed(item);
     177              :     }
     178              :     
     179           16 :     m_list.clear();
     180              :     
     181           16 :     emit countChanged(count());
     182           16 : }
     183              : 
     184            0 : void ListModel::setSelected(ListItem *selected)
     185              : {
     186            0 :     _selected = selected;
     187            0 :     emit selectedChanged(_selected);
     188            0 :     emit selectedIndexChanged(selectedIndex());
     189            0 : }
     190              : 
     191            0 : int ListModel::selectedIndex()
     192              : {
     193            0 :     return m_list.indexOf(_selected);
     194              : }
     195              : 
     196            0 : void ListModel::setSelectedIndex(int selectedIndex)
     197              : {
     198            0 :     setSelected(m_list.at(selectedIndex));
     199            0 : }
     200              : 
     201            0 : int ListModel::roleNameToRole(const QString &field_name) const
     202              : {
     203            0 :     return _roleNames.contains(field_name) ? _roleNames[field_name] : -1;
     204              : }
     205              :  
     206            0 : bool ListModel::removeRow(int row, const QModelIndex &parent)
     207              : {
     208              :   Q_UNUSED(parent);
     209            0 :   ListItem* toRemove = nullptr;
     210            0 :   if(row < 0 || row >= m_list.size()) return false;
     211            0 :   beginRemoveRows(QModelIndex(), row, row);
     212            0 :   toRemove = m_list.takeAt(row);
     213            0 :   endRemoveRows();
     214              :   
     215            0 :   emit removed(toRemove);
     216            0 :   emit countChanged(count());
     217              :   
     218            0 :   return true;
     219              : }
     220              :  
     221            0 : bool ListModel::removeRows(int row, int count, const QModelIndex &parent)
     222              : {
     223              :   Q_UNUSED(parent);
     224            0 :   QList<ListItem*> toRemove;
     225              :   
     226            0 :   if(row < 0 || (row+count) >= m_list.size()) return false;
     227            0 :   beginRemoveRows(QModelIndex(), row, row+count-1);
     228            0 :   for(int i=0; i<count; ++i) {
     229            0 :       toRemove.append(m_list.takeAt(row));
     230              :   }
     231            0 :   endRemoveRows();
     232              :   
     233            0 :   for (ListItem* item : toRemove) {
     234            0 :       emit removed(item);
     235              :   }
     236              :   
     237            0 :   emit countChanged(this->count());
     238              :   
     239            0 :   return true;
     240            0 : }
     241              : 
     242            0 : bool ListModel::removeItem(const ListItem *item)
     243              : {
     244            0 :     QModelIndex index = indexFromItem(item);
     245            0 :     int row = index.row();
     246              :     
     247            0 :     qDebug() << "Remove item at: " << row;
     248              :     
     249            0 :     if (row == -1) {
     250            0 :         return false; // Not found.
     251              :     }
     252              :     
     253            0 :     return removeRow(row);
     254              : }
     255              :  
     256            0 : ListItem * ListModel::takeRow(int row)
     257              : {
     258            0 :   beginRemoveRows(QModelIndex(), row, row);
     259            0 :   ListItem* item = m_list.takeAt(row);
     260            0 :   endRemoveRows();
     261              :   
     262            0 :   emit removed(item);
     263            0 :   emit countChanged(count());
     264              :   
     265            0 :   return item;
     266              : }
        

Generated by: LCOV version 2.0-1