#include "particlelistmodel.h" #include #include #include #include #include ParticleListModel::ParticleListModel(Store *store, QObject *parent) : QAbstractListModel(parent), m_store(store), m_currentStreamId() { connect(m_store, &Store::particlesChanged, this, [this](const QString &streamId) { if (streamId == m_currentStreamId) { beginResetModel(); endResetModel(); } }); // Granular update: repaint a single row when a particle property changes connect(m_store, &Store::particleUpdated, this, [this](const QString &streamId, const QString &particleId) { if (streamId != m_currentStreamId) return; const QList &particles = m_store->particlesForStream(m_currentStreamId); for (int i = 0; i < particles.size(); ++i) { if (particles.at(i).id == particleId) { QModelIndex idx = index(i, 0); emit dataChanged(idx, idx, {Qt::DisplayRole, Qt::ForegroundRole}); return; } } }); } int ParticleListModel::rowCount(const QModelIndex &parent) const { if (parent.isValid()) { return 0; } if (m_currentStreamId.isEmpty()) { return 0; } return m_store->particleCount(m_currentStreamId); } QVariant ParticleListModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) { return QVariant(); } if (m_currentStreamId.isEmpty()) { return QVariant(); } const QList &particles = m_store->particlesForStream(m_currentStreamId); if (index.row() < 0 || index.row() >= particles.size()) { return QVariant(); } const Particle &particle = particles.at(index.row()); if (role == Qt::DisplayRole) { QString emailPrefix = particle.createdByEmail.split("@")[0]; QString summary = particle.data.value("content").toString(); if (summary.isEmpty()) { summary = particle.type; } QString display = QString("[%1] - %2").arg(emailPrefix, summary); return display; } else if (role == Qt::ForegroundRole) { // Make seen particles subtle grey, unseen stay default color if (particle.seen) { return QBrush(QColor(128, 128, 128)); // Medium grey for seen items } // Unseen items use default foreground color } return QVariant(); } void ParticleListModel::setStreamId(const QString &streamId) { beginResetModel(); m_currentStreamId = streamId; endResetModel(); } int ParticleListModel::firstUnseenRow() const { if (m_currentStreamId.isEmpty()) { return -1; } const QList &particles = m_store->particlesForStream(m_currentStreamId); for (int i = 0; i < particles.size(); ++i) { if (!particles.at(i).seen) { return i; } } return -1; // All seen or empty } const Particle *ParticleListModel::particleAtRow(int row) const { if (m_currentStreamId.isEmpty()) { return nullptr; } const QList &particles = m_store->particlesForStream(m_currentStreamId); if (row >= 0 && row < particles.size()) { return &particles.at(row); } return nullptr; }