syncthingtray/model/syncthingdownloadmodel.cpp

263 lines
9.5 KiB
C++
Raw Normal View History

2016-09-21 21:09:12 +02:00
#include "./syncthingdownloadmodel.h"
#include "../connector/syncthingconnection.h"
#include "../connector/utils.h"
2016-09-21 21:09:12 +02:00
#include <QStringBuilder>
using namespace std;
2016-09-21 21:09:12 +02:00
using namespace ChronoUtilities;
namespace Data {
2017-05-01 03:34:43 +02:00
SyncthingDownloadModel::SyncthingDownloadModel(SyncthingConnection &connection, QObject *parent)
: SyncthingModel(connection, parent)
, 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)
2016-09-21 21:09:12 +02:00
{
connect(&m_connection, &SyncthingConnection::newConfig, this, &SyncthingDownloadModel::newConfig);
connect(&m_connection, &SyncthingConnection::newDirs, this, &SyncthingDownloadModel::newDirs);
connect(&m_connection, &SyncthingConnection::downloadProgressChanged, this, &SyncthingDownloadModel::downloadProgressChanged);
}
QHash<int, QByteArray> SyncthingDownloadModel::initRoleNames()
{
QHash<int, QByteArray> roles;
roles[Qt::DisplayRole] = "name";
roles[Qt::DecorationRole] = "fileIcon";
2017-09-05 00:25:55 +02:00
roles[ItemPercentage] = "percentage";
roles[ItemProgressLabel] = "progressLabel";
roles[ItemPath] = "path";
return roles;
}
QHash<int, QByteArray> SyncthingDownloadModel::roleNames() const
{
const static QHash<int, QByteArray> roles(initRoleNames());
return roles;
}
2016-09-21 21:09:12 +02:00
/*!
* \brief Returns the directory info for the spcified \a index. The returned object is not persistent.
*/
const SyncthingDir *SyncthingDownloadModel::dirInfo(const QModelIndex &index) const
{
2017-05-01 03:34:43 +02:00
return (index.parent().isValid()
? dirInfo(index.parent())
: (static_cast<size_t>(index.row()) < m_pendingDirs.size() ? m_pendingDirs[static_cast<size_t>(index.row())] : nullptr));
2016-09-21 21:09:12 +02:00
}
const SyncthingItemDownloadProgress *SyncthingDownloadModel::progressInfo(const QModelIndex &index) const
{
2017-05-01 03:34:43 +02:00
if (index.parent().isValid() && static_cast<size_t>(index.parent().row()) < m_pendingDirs.size()
&& static_cast<size_t>(index.row()) < m_pendingDirs[static_cast<size_t>(index.parent().row())]->downloadingItems.size()) {
2016-09-21 21:09:12 +02:00
return &(m_pendingDirs[static_cast<size_t>(index.parent().row())]->downloadingItems[static_cast<size_t>(index.row())]);
} else {
return nullptr;
}
}
QModelIndex SyncthingDownloadModel::index(int row, int column, const QModelIndex &parent) const
{
2017-05-01 03:34:43 +02:00
if (!parent.isValid()) {
2016-09-21 21:09:12 +02:00
// top-level: all pending dir labels/IDs
2017-05-01 03:34:43 +02:00
if (row < rowCount(parent)) {
2016-09-21 21:09:12 +02:00
return createIndex(row, column, static_cast<quintptr>(-1));
}
2017-05-01 03:34:43 +02:00
} else if (!parent.parent().isValid()) {
2016-09-21 21:09:12 +02:00
// dir-level: pending downloads
2017-05-01 03:34:43 +02:00
if (row < rowCount(parent)) {
2016-09-21 21:09:12 +02:00
return createIndex(row, column, static_cast<quintptr>(parent.row()));
}
}
return QModelIndex();
}
QModelIndex SyncthingDownloadModel::parent(const QModelIndex &child) const
{
return child.internalId() != static_cast<quintptr>(-1) ? index(static_cast<int>(child.internalId()), 0, QModelIndex()) : QModelIndex();
}
QVariant SyncthingDownloadModel::headerData(int section, Qt::Orientation orientation, int role) const
{
2017-05-01 03:34:43 +02:00
switch (orientation) {
2016-09-21 21:09:12 +02:00
case Qt::Horizontal:
2017-05-01 03:34:43 +02:00
switch (role) {
2016-09-21 21:09:12 +02:00
case Qt::DisplayRole:
2017-05-01 03:34:43 +02:00
switch (section) {
case 0:
return tr("Dir/item");
case 1:
return tr("Progress");
2016-09-21 21:09:12 +02:00
}
break;
2017-05-01 03:34:43 +02:00
default:;
2016-09-21 21:09:12 +02:00
}
break;
2017-05-01 03:34:43 +02:00
default:;
2016-09-21 21:09:12 +02:00
}
return QVariant();
}
QVariant SyncthingDownloadModel::data(const QModelIndex &index, int role) const
{
2017-05-01 03:34:43 +02:00
if (index.isValid()) {
if (index.parent().isValid()) {
2017-09-05 00:25:55 +02:00
// downloading items (of dir)
2017-05-01 03:34:43 +02:00
if (static_cast<size_t>(index.parent().row()) < m_pendingDirs.size()) {
2016-09-21 21:09:12 +02:00
const SyncthingDir &dir = *m_pendingDirs[static_cast<size_t>(index.parent().row())];
2017-05-01 03:34:43 +02:00
if (static_cast<size_t>(index.row()) < dir.downloadingItems.size()) {
2016-09-21 21:09:12 +02:00
const SyncthingItemDownloadProgress &progress = dir.downloadingItems[static_cast<size_t>(index.row())];
2017-05-01 03:34:43 +02:00
switch (role) {
2016-09-21 21:09:12 +02:00
case Qt::DisplayRole:
case Qt::EditRole:
2017-05-01 03:34:43 +02:00
switch (index.column()) {
2016-09-21 21:09:12 +02:00
case 0: // file names
return progress.relativePath;
case 1: // progress information
return progress.label;
}
break;
case Qt::ToolTipRole:
break;
case Qt::DecorationRole:
2017-05-01 03:34:43 +02:00
switch (index.column()) {
2016-09-21 21:09:12 +02:00
case 0: // file icon
return progress.fileInfo.exists() ? m_fileIconProvider.icon(progress.fileInfo) : m_unknownIcon;
2017-05-01 03:34:43 +02:00
default:;
2016-09-21 21:09:12 +02:00
}
break;
case ItemPercentage:
return progress.downloadPercentage;
2016-09-28 00:06:21 +02:00
case ItemProgressLabel:
return progress.label;
case ItemPath:
return dir.path + progress.relativePath;
2017-05-01 03:34:43 +02:00
default:;
2016-09-21 21:09:12 +02:00
}
}
}
2017-05-01 03:34:43 +02:00
} else if (static_cast<size_t>(index.row()) < m_pendingDirs.size()) {
2016-09-21 21:09:12 +02:00
// dir IDs and overall dir progress
const SyncthingDir &dir = *m_pendingDirs[static_cast<size_t>(index.row())];
2017-05-01 03:34:43 +02:00
switch (role) {
2016-09-21 21:09:12 +02:00
case Qt::DisplayRole:
case Qt::EditRole:
2017-05-01 03:34:43 +02:00
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;
2016-09-21 21:09:12 +02:00
}
break;
case Qt::TextAlignmentRole:
2017-05-01 03:34:43 +02:00
switch (index.column()) {
case 0:
break;
case 1:
return static_cast<int>(Qt::AlignRight | Qt::AlignVCenter);
2016-09-21 21:09:12 +02:00
}
break;
case ItemPercentage:
return dir.downloadPercentage;
2016-09-28 00:06:21 +02:00
case ItemProgressLabel:
return dir.downloadLabel;
case ItemPath:
return dir.path;
2017-05-01 03:34:43 +02:00
default:;
2016-09-21 21:09:12 +02:00
}
}
}
return QVariant();
}
bool SyncthingDownloadModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
2017-05-01 03:34:43 +02:00
Q_UNUSED(index) Q_UNUSED(value) Q_UNUSED(role) return false;
2016-09-21 21:09:12 +02:00
}
int SyncthingDownloadModel::rowCount(const QModelIndex &parent) const
{
2017-05-01 03:34:43 +02:00
if (!parent.isValid()) {
2016-09-21 21:09:12 +02:00
return static_cast<int>(m_pendingDirs.size());
2017-05-01 03:34:43 +02:00
} else if (!parent.parent().isValid() && parent.row() >= 0 && static_cast<size_t>(parent.row()) < m_pendingDirs.size()) {
2016-09-21 21:09:12 +02:00
return static_cast<int>(m_pendingDirs[static_cast<size_t>(parent.row())]->downloadingItems.size());
} else {
return 0;
}
}
int SyncthingDownloadModel::columnCount(const QModelIndex &parent) const
{
2017-05-01 03:34:43 +02:00
if (!parent.isValid()) {
2016-09-28 00:06:21 +02:00
return singleColumnMode() ? 1 : 2; // label/ID, status/progress
2017-05-01 03:34:43 +02:00
} else if (!parent.parent().isValid()) {
2016-09-28 00:06:21 +02:00
return singleColumnMode() ? 1 : 2; // file, progress
2016-09-21 21:09:12 +02:00
} 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;
2017-05-01 03:34:43 +02:00
for (const SyncthingDir &dirInfo : m_connection.dirInfo()) {
2017-09-05 00:25:55 +02:00
const auto pendingIterator = find(m_pendingDirs.begin(), m_pendingDirs.end(), &dirInfo);
2017-05-01 03:34:43 +02:00
if (dirInfo.downloadingItems.empty()) {
if (pendingIterator != m_pendingDirs.end()) {
2016-09-21 21:09:12 +02:00
beginRemoveRows(QModelIndex(), row, row);
m_pendingDirs.erase(pendingIterator);
endRemoveRows();
}
} else {
2017-05-01 03:34:43 +02:00
if (pendingIterator != m_pendingDirs.end()) {
static const QVector<int> roles({ Qt::DisplayRole, Qt::EditRole, Qt::DecorationRole, Qt::ForegroundRole, Qt::ToolTipRole,
ItemPercentage, ItemProgressLabel, ItemPath });
2017-09-05 00:25:55 +02:00
const QModelIndex parentIndex(index(row, 0));
emit dataChanged(parentIndex, index(row, 1), roles);
emit dataChanged(index(0, 0, parentIndex), index(static_cast<int>(dirInfo.downloadingItems.size()), 1, parentIndex), roles);
2016-09-21 21:09:12 +02:00
} else {
beginInsertRows(QModelIndex(), row, row);
beginInsertRows(index(row, row), 0, static_cast<int>(dirInfo.downloadingItems.size()));
m_pendingDirs.insert(pendingIterator, &dirInfo);
endInsertRows();
endInsertRows();
}
++row;
}
}
}
2016-09-28 00:06:21 +02:00
void SyncthingDownloadModel::setSingleColumnMode(bool singleColumnModeEnabled)
{
2017-05-01 03:34:43 +02:00
if (m_singleColumnMode != singleColumnModeEnabled) {
if (m_singleColumnMode) {
2016-09-28 00:06:21 +02:00
beginInsertColumns(QModelIndex(), 1, 1);
m_singleColumnMode = true;
endInsertColumns();
} else {
beginRemoveColumns(QModelIndex(), 1, 1);
m_singleColumnMode = false;
endRemoveColumns();
}
}
}
2016-09-21 21:09:12 +02:00
} // namespace Data