File indexing completed on 2024-05-19 16:31:38

0001 /*
0002  * SPDX-FileCopyrightText: 2015 Dominik Haumann <dhaumann@kde.org>
0003  *
0004  * SPDX-License-Identifier: LGPL-2.1-or-later
0005  */
0006 #include "QuotaListModel.h"
0007 
0008 #include <QDebug>
0009 
0010 QuotaListModel::QuotaListModel(QObject *parent)
0011     : QAbstractListModel(parent)
0012 {
0013 }
0014 
0015 namespace
0016 {
0017 /**
0018  * QML data roles.
0019  */
0020 enum {
0021     DetailsRole = Qt::UserRole,
0022     IconRole,
0023     FreeStringRole,
0024     UsedStringRole,
0025     MountPointRole,
0026     UsageRole,
0027 };
0028 }
0029 
0030 QHash<int, QByteArray> QuotaListModel::roleNames() const
0031 {
0032     QHash<int, QByteArray> roles;
0033     roles[DetailsRole] = "details";
0034     roles[IconRole] = "icon";
0035     roles[FreeStringRole] = "free";
0036     roles[UsedStringRole] = "used";
0037     roles[MountPointRole] = "mountPoint";
0038     roles[UsageRole] = "usage";
0039 
0040     return roles;
0041 }
0042 
0043 QVariant QuotaListModel::data(const QModelIndex &index, int role) const
0044 {
0045     if (!index.isValid() || index.row() >= m_items.size()) {
0046         return QVariant();
0047     }
0048 
0049     const auto item = m_items[index.row()];
0050 
0051     switch (role) {
0052     case DetailsRole:
0053         return item.mountString();
0054     case IconRole:
0055         return item.iconName();
0056     case FreeStringRole:
0057         return item.freeString();
0058     case UsedStringRole:
0059         return item.usedString();
0060     case MountPointRole:
0061         return item.mountPoint();
0062     case UsageRole:
0063         return item.usage();
0064     }
0065 
0066     return QVariant();
0067 }
0068 
0069 int QuotaListModel::rowCount(const QModelIndex &index) const
0070 {
0071     if (!index.isValid()) {
0072         return m_items.size();
0073     }
0074 
0075     return 0;
0076 }
0077 
0078 bool QuotaListModel::setData(const QModelIndex &index, const QVariant &variant, int role)
0079 {
0080     Q_UNUSED(role)
0081 
0082     const int row = index.row();
0083     if (index.isValid() && row < m_items.size()) {
0084         const QuotaItem item = variant.value<QuotaItem>();
0085 
0086         // This assert makes sure that changing items modify the correct item:
0087         // therefore, the unique identifier 'mountPoint()' is used. If that
0088         // is not the case, the newly inserted row must have an empty mountPoint().
0089         Q_ASSERT(item.mountPoint() == m_items[row].mountPoint() || m_items[row].mountPoint().isEmpty());
0090 
0091         if (m_items[row] != item) {
0092             m_items[row] = item;
0093             Q_EMIT dataChanged(index, index);
0094             return true;
0095         }
0096     }
0097 
0098     return false;
0099 }
0100 
0101 bool QuotaListModel::insertRows(int row, int count, const QModelIndex &parent)
0102 {
0103     // only top-level items are supported
0104     if (parent.isValid()) {
0105         return false;
0106     }
0107 
0108     beginInsertRows(QModelIndex(), row, row + count - 1);
0109     m_items.insert(row, count, QuotaItem());
0110     endInsertRows();
0111 
0112     return true;
0113 }
0114 
0115 bool QuotaListModel::removeRows(int row, int count, const QModelIndex &parent)
0116 {
0117     // only top-level items are valid
0118     if (parent.isValid() || (row + count) >= m_items.size()) {
0119         return false;
0120     }
0121 
0122     beginRemoveRows(QModelIndex(), row, row + count - 1);
0123     m_items.remove(row, count);
0124     endRemoveRows();
0125 
0126     return true;
0127 }
0128 
0129 void QuotaListModel::clear()
0130 {
0131     beginResetModel();
0132     m_items.clear();
0133     endResetModel();
0134 }
0135 
0136 namespace
0137 {
0138 QStringList mountPoints(const QVector<QuotaItem> &items)
0139 {
0140     QStringList list;
0141     for (auto &item : items) {
0142         list.append(item.mountPoint());
0143     }
0144     return list;
0145 }
0146 
0147 int indexOfMountPoint(const QString &mountPoint, const QVector<QuotaItem> &items)
0148 {
0149     for (int i = 0; i < items.size(); ++i) {
0150         if (mountPoint == items[i].mountPoint()) {
0151             return i;
0152         }
0153     }
0154     return -1;
0155 }
0156 }
0157 
0158 void QuotaListModel::updateItems(const QVector<QuotaItem> &items)
0159 {
0160     QStringList unusedMountPoints = mountPoints(m_items);
0161 
0162     // merge existing and new mount points
0163     for (auto &item : items) {
0164         // remove still used item from unused list
0165         unusedMountPoints.removeOne(item.mountPoint());
0166 
0167         // insert or modify m_items
0168         int row = indexOfMountPoint(item.mountPoint(), m_items);
0169         if (row < 0) {
0170             // new item: append on end
0171             row = m_items.size();
0172             insertRow(row);
0173         }
0174         setData(createIndex(row, 0), QVariant::fromValue(item));
0175     }
0176 
0177     // remove mount points, that do not exist anymore
0178     for (const auto &mountPoint : unusedMountPoints) {
0179         const int row = indexOfMountPoint(mountPoint, m_items);
0180         Q_ASSERT(row >= 0);
0181         removeRow(row);
0182     }
0183 }