#include "./syncthingdownloadmodel.h" #include "./syncthingconnection.h" #include "./utils.h" #include using namespace ChronoUtilities; namespace Data { SyncthingDownloadModel::SyncthingDownloadModel(SyncthingConnection &connection, QObject *parent) : QAbstractItemModel(parent), m_connection(connection), m_dirs(connection.dirInfo()), m_unknownIcon(QIcon::fromTheme(QStringLiteral("text-x-generic"), QIcon(QStringLiteral(":/icons/hicolor/scalable/mimetypes/text-x-generic.svg")))), m_pendingDirs(0), m_singleColumnMode(true) { connect(&m_connection, &SyncthingConnection::newConfig, this, &SyncthingDownloadModel::newConfig); connect(&m_connection, &SyncthingConnection::newDirs, this, &SyncthingDownloadModel::newDirs); connect(&m_connection, &SyncthingConnection::downloadProgressChanged, this, &SyncthingDownloadModel::downloadProgressChanged); } /*! * \brief Returns the directory info for the spcified \a index. The returned object is not persistent. */ const SyncthingDir *SyncthingDownloadModel::dirInfo(const QModelIndex &index) const { return (index.parent().isValid() ? dirInfo(index.parent()) : (static_cast(index.row()) < m_pendingDirs.size() ? m_pendingDirs[static_cast(index.row())] : nullptr)); } const SyncthingItemDownloadProgress *SyncthingDownloadModel::progressInfo(const QModelIndex &index) const { if(index.parent().isValid() && static_cast(index.parent().row()) < m_pendingDirs.size() && static_cast(index.row()) < m_pendingDirs[static_cast(index.parent().row())]->downloadingItems.size()) { return &(m_pendingDirs[static_cast(index.parent().row())]->downloadingItems[static_cast(index.row())]); } else { return nullptr; } } QModelIndex SyncthingDownloadModel::index(int row, int column, const QModelIndex &parent) const { if(!parent.isValid()) { // top-level: all pending dir labels/IDs if(row < rowCount(parent)) { return createIndex(row, column, static_cast(-1)); } } else if(!parent.parent().isValid()) { // dir-level: pending downloads if(row < rowCount(parent)) { return createIndex(row, column, static_cast(parent.row())); } } return QModelIndex(); } QModelIndex SyncthingDownloadModel::parent(const QModelIndex &child) const { return child.internalId() != static_cast(-1) ? index(static_cast(child.internalId()), 0, QModelIndex()) : QModelIndex(); } QVariant SyncthingDownloadModel::headerData(int section, Qt::Orientation orientation, int role) const { switch(orientation) { case Qt::Horizontal: switch(role) { case Qt::DisplayRole: switch(section) { case 0: return tr("Dir/item"); case 1: return tr("Progress"); } break; default: ; } break; default: ; } return QVariant(); } QVariant SyncthingDownloadModel::data(const QModelIndex &index, int role) const { if(index.isValid()) { if(index.parent().isValid()) { // dir attributes if(static_cast(index.parent().row()) < m_pendingDirs.size()) { const SyncthingDir &dir = *m_pendingDirs[static_cast(index.parent().row())]; if(static_cast(index.row()) < dir.downloadingItems.size()) { const SyncthingItemDownloadProgress &progress = dir.downloadingItems[static_cast(index.row())]; switch(role) { case Qt::DisplayRole: case Qt::EditRole: switch(index.column()) { case 0: // file names return progress.relativePath; case 1: // progress information return progress.label; } break; case Qt::ToolTipRole: break; case Qt::DecorationRole: switch(index.column()) { case 0: // file icon return progress.fileInfo.exists() ? m_fileIconProvider.icon(progress.fileInfo) : m_unknownIcon; default: ; } break; case ItemPercentage: return progress.downloadPercentage; case ItemProgressLabel: return progress.label; default: ; } } } } else if(static_cast(index.row()) < m_pendingDirs.size()) { // dir IDs and overall dir progress const SyncthingDir &dir = *m_pendingDirs[static_cast(index.row())]; switch(role) { case Qt::DisplayRole: case Qt::EditRole: switch(index.column()) { case 0: return QVariant((dir.label.isEmpty() ? dir.id : dir.label) % QChar(' ') % QChar('(') % QString::number(dir.downloadingItems.size()) % QChar(')')); case 1: return dir.downloadLabel; } break; case Qt::TextAlignmentRole: switch(index.column()) { case 0: break; case 1: return static_cast(Qt::AlignRight | Qt::AlignVCenter); } break; case ItemPercentage: return dir.downloadPercentage; case ItemProgressLabel: return dir.downloadLabel; default: ; } } } return QVariant(); } bool SyncthingDownloadModel::setData(const QModelIndex &index, const QVariant &value, int role) { Q_UNUSED(index) Q_UNUSED(value) Q_UNUSED(role) return false; } int SyncthingDownloadModel::rowCount(const QModelIndex &parent) const { if(!parent.isValid()) { return static_cast(m_pendingDirs.size()); } else if(!parent.parent().isValid() && parent.row() >= 0 && static_cast(parent.row()) < m_pendingDirs.size()) { return static_cast(m_pendingDirs[static_cast(parent.row())]->downloadingItems.size()); } else { return 0; } } int SyncthingDownloadModel::columnCount(const QModelIndex &parent) const { if(!parent.isValid()) { return singleColumnMode() ? 1 : 2; // label/ID, status/progress } else if(!parent.parent().isValid()) { return singleColumnMode() ? 1 : 2; // file, progress } else { return 0; } } void SyncthingDownloadModel::newConfig() { beginResetModel(); m_pendingDirs.clear(); endResetModel(); } void SyncthingDownloadModel::newDirs() { m_pendingDirs.reserve(m_connection.dirInfo().size()); } void SyncthingDownloadModel::downloadProgressChanged() { int row = 0; for(const SyncthingDir &dirInfo : m_connection.dirInfo()) { auto pendingIterator = find(m_pendingDirs.begin(), m_pendingDirs.end(), &dirInfo); if(dirInfo.downloadingItems.empty()) { if(pendingIterator != m_pendingDirs.end()) { beginRemoveRows(QModelIndex(), row, row); m_pendingDirs.erase(pendingIterator); endRemoveRows(); } } else { if(pendingIterator != m_pendingDirs.end()) { emit dataChanged(index(row, 0), index(row, 1), QVector() << Qt::DisplayRole << Qt::EditRole << Qt::DecorationRole << Qt::ForegroundRole << Qt::ToolTipRole); } else { beginInsertRows(QModelIndex(), row, row); beginInsertRows(index(row, row), 0, static_cast(dirInfo.downloadingItems.size())); m_pendingDirs.insert(pendingIterator, &dirInfo); endInsertRows(); endInsertRows(); } ++row; } } } void SyncthingDownloadModel::setSingleColumnMode(bool singleColumnModeEnabled) { if(m_singleColumnMode != singleColumnModeEnabled) { if(m_singleColumnMode) { beginInsertColumns(QModelIndex(), 1, 1); m_singleColumnMode = true; endInsertColumns(); } else { beginRemoveColumns(QModelIndex(), 1, 1); m_singleColumnMode = false; endRemoveColumns(); } } } } // namespace Data