mirror of
https://github.com/qbittorrent/qBittorrent
synced 2025-07-30 11:38:50 -07:00
Improve TorrentModel class.
This commit is contained in:
parent
7699b7ce6f
commit
64c8f61bb1
15 changed files with 576 additions and 695 deletions
|
@ -1,6 +1,7 @@
|
|||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2010 Christophe Dumez
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2010 Christophe Dumez <chris@qbittorrent.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -34,110 +35,315 @@
|
|||
#include <QIcon>
|
||||
|
||||
#include "core/bittorrent/session.h"
|
||||
#include "core/bittorrent/torrenthandle.h"
|
||||
#include "core/torrentfilter.h"
|
||||
#include "core/utils/fs.h"
|
||||
#include "torrentmodel.h"
|
||||
|
||||
namespace {
|
||||
QIcon get_paused_icon() {
|
||||
static QIcon cached = QIcon(":/icons/skin/paused.png");
|
||||
return cached;
|
||||
}
|
||||
static QIcon getIconByState(BitTorrent::TorrentState state);
|
||||
static QColor getColorByState(BitTorrent::TorrentState state);
|
||||
|
||||
QIcon get_queued_icon() {
|
||||
static QIcon cached = QIcon(":/icons/skin/queued.png");
|
||||
return cached;
|
||||
}
|
||||
static QIcon getPausedIcon();
|
||||
static QIcon getQueuedIcon();
|
||||
static QIcon getDownloadingIcon();
|
||||
static QIcon getStalledDownloadingIcon();
|
||||
static QIcon getUploadingIcon();
|
||||
static QIcon getStalledUploadingIcon();
|
||||
static QIcon getCompletedIcon();
|
||||
static QIcon getCheckingIcon();
|
||||
static QIcon getErrorIcon();
|
||||
|
||||
QIcon get_downloading_icon() {
|
||||
static QIcon cached = QIcon(":/icons/skin/downloading.png");
|
||||
return cached;
|
||||
}
|
||||
static bool isDarkTheme();
|
||||
|
||||
QIcon get_stalled_downloading_icon() {
|
||||
static QIcon cached = QIcon(":/icons/skin/stalledDL.png");
|
||||
return cached;
|
||||
}
|
||||
// TorrentModel
|
||||
|
||||
QIcon get_uploading_icon() {
|
||||
static QIcon cached = QIcon(":/icons/skin/uploading.png");
|
||||
return cached;
|
||||
}
|
||||
|
||||
QIcon get_stalled_uploading_icon() {
|
||||
static QIcon cached = QIcon(":/icons/skin/stalledUP.png");
|
||||
return cached;
|
||||
}
|
||||
|
||||
QIcon get_completed_icon() {
|
||||
static QIcon cached = QIcon(":/icons/skin/completed.png");
|
||||
return cached;
|
||||
}
|
||||
|
||||
QIcon get_checking_icon() {
|
||||
static QIcon cached = QIcon(":/icons/skin/checking.png");
|
||||
return cached;
|
||||
}
|
||||
|
||||
QIcon get_error_icon() {
|
||||
static QIcon cached = QIcon(":/icons/skin/error.png");
|
||||
return cached;
|
||||
}
|
||||
|
||||
bool isDarkTheme()
|
||||
TorrentModel::TorrentModel(QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
{
|
||||
QPalette pal = QApplication::palette();
|
||||
// QPalette::Base is used for the background of the Treeview
|
||||
QColor color = pal.color(QPalette::Active, QPalette::Base);
|
||||
return (color.lightness() < 127);
|
||||
}
|
||||
// Load the torrents
|
||||
foreach (BitTorrent::TorrentHandle *const torrent, BitTorrent::Session::instance()->torrents())
|
||||
addTorrent(torrent);
|
||||
|
||||
// Listen for torrent changes
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(torrentAdded(BitTorrent::TorrentHandle *const)), SLOT(addTorrent(BitTorrent::TorrentHandle *const)));
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(torrentAboutToBeRemoved(BitTorrent::TorrentHandle *const)), SLOT(handleTorrentAboutToBeRemoved(BitTorrent::TorrentHandle *const)));
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(torrentStatusUpdated(BitTorrent::TorrentHandle *const)), this, SLOT(handleTorrentStatusUpdated(BitTorrent::TorrentHandle *const)));
|
||||
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(torrentFinished(BitTorrent::TorrentHandle *const)), SLOT(handleTorrentStatusUpdated(BitTorrent::TorrentHandle *const)));
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(torrentMetadataLoaded(BitTorrent::TorrentHandle *const)), SLOT(handleTorrentStatusUpdated(BitTorrent::TorrentHandle *const)));
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(torrentResumed(BitTorrent::TorrentHandle *const)), SLOT(handleTorrentStatusUpdated(BitTorrent::TorrentHandle *const)));
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(torrentPaused(BitTorrent::TorrentHandle *const)), SLOT(handleTorrentStatusUpdated(BitTorrent::TorrentHandle *const)));
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(torrentFinishedChecking(BitTorrent::TorrentHandle *const)), SLOT(handleTorrentStatusUpdated(BitTorrent::TorrentHandle *const)));
|
||||
}
|
||||
|
||||
TorrentModelItem::TorrentModelItem(BitTorrent::TorrentHandle *torrent)
|
||||
: m_torrent(torrent)
|
||||
int TorrentModel::rowCount(const QModelIndex &index) const
|
||||
{
|
||||
Q_UNUSED(index);
|
||||
return m_torrents.size();
|
||||
}
|
||||
|
||||
BitTorrent::TorrentState TorrentModelItem::state() const
|
||||
int TorrentModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
return m_torrent->state();
|
||||
Q_UNUSED(parent);
|
||||
return NB_COLUMNS;
|
||||
}
|
||||
|
||||
QIcon TorrentModelItem::getIconByState(BitTorrent::TorrentState state)
|
||||
QVariant TorrentModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (orientation == Qt::Horizontal) {
|
||||
if (role == Qt::DisplayRole) {
|
||||
switch(section) {
|
||||
case TR_PRIORITY: return "#";
|
||||
case TR_NAME: return tr("Name", "i.e: torrent name");
|
||||
case TR_SIZE: return tr("Size", "i.e: torrent size");
|
||||
case TR_PROGRESS: return tr("Done", "% Done");
|
||||
case TR_STATUS: return tr("Status", "Torrent status (e.g. downloading, seeding, paused)");
|
||||
case TR_SEEDS: return tr("Seeds", "i.e. full sources (often untranslated)");
|
||||
case TR_PEERS: return tr("Peers", "i.e. partial sources (often untranslated)");
|
||||
case TR_DLSPEED: return tr("Down Speed", "i.e: Download speed");
|
||||
case TR_UPSPEED: return tr("Up Speed", "i.e: Upload speed");
|
||||
case TR_RATIO: return tr("Ratio", "Share ratio");
|
||||
case TR_ETA: return tr("ETA", "i.e: Estimated Time of Arrival / Time left");
|
||||
case TR_LABEL: return tr("Label");
|
||||
case TR_ADD_DATE: return tr("Added On", "Torrent was added to transfer list on 01/01/2010 08:00");
|
||||
case TR_SEED_DATE: return tr("Completed On", "Torrent was completed on 01/01/2010 08:00");
|
||||
case TR_TRACKER: return tr("Tracker");
|
||||
case TR_DLLIMIT: return tr("Down Limit", "i.e: Download limit");
|
||||
case TR_UPLIMIT: return tr("Up Limit", "i.e: Upload limit");
|
||||
case TR_AMOUNT_DOWNLOADED: return tr("Downloaded", "Amount of data downloaded (e.g. in MB)");
|
||||
case TR_AMOUNT_UPLOADED: return tr("Uploaded", "Amount of data uploaded (e.g. in MB)");
|
||||
case TR_AMOUNT_DOWNLOADED_SESSION: return tr("Session Download", "Amount of data downloaded since program open (e.g. in MB)");
|
||||
case TR_AMOUNT_UPLOADED_SESSION: return tr("Session Upload", "Amount of data uploaded since program open (e.g. in MB)");
|
||||
case TR_AMOUNT_LEFT: return tr("Remaining", "Amount of data left to download (e.g. in MB)");
|
||||
case TR_TIME_ELAPSED: return tr("Time Active", "Time (duration) the torrent is active (not paused)");
|
||||
case TR_SAVE_PATH: return tr("Save path", "Torrent save path");
|
||||
case TR_COMPLETED: return tr("Completed", "Amount of data completed (e.g. in MB)");
|
||||
case TR_RATIO_LIMIT: return tr("Ratio Limit", "Upload share ratio limit");
|
||||
case TR_SEEN_COMPLETE_DATE: return tr("Last Seen Complete", "Indicates the time when the torrent was last seen complete/whole");
|
||||
case TR_LAST_ACTIVITY: return tr("Last Activity", "Time passed since a chunk was downloaded/uploaded");
|
||||
case TR_TOTAL_SIZE: return tr("Total Size", "i.e. Size including unwanted data");
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
else if (role == Qt::TextAlignmentRole) {
|
||||
switch(section) {
|
||||
case TR_AMOUNT_DOWNLOADED:
|
||||
case TR_AMOUNT_UPLOADED:
|
||||
case TR_AMOUNT_DOWNLOADED_SESSION:
|
||||
case TR_AMOUNT_UPLOADED_SESSION:
|
||||
case TR_AMOUNT_LEFT:
|
||||
case TR_COMPLETED:
|
||||
case TR_SIZE:
|
||||
case TR_TOTAL_SIZE:
|
||||
case TR_ETA:
|
||||
case TR_SEEDS:
|
||||
case TR_PEERS:
|
||||
case TR_UPSPEED:
|
||||
case TR_DLSPEED:
|
||||
case TR_UPLIMIT:
|
||||
case TR_DLLIMIT:
|
||||
case TR_RATIO_LIMIT:
|
||||
case TR_RATIO:
|
||||
case TR_PRIORITY:
|
||||
case TR_LAST_ACTIVITY:
|
||||
return QVariant(Qt::AlignRight | Qt::AlignVCenter);
|
||||
default:
|
||||
return QAbstractListModel::headerData(section, orientation, role);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QVariant TorrentModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid()) return QVariant();
|
||||
|
||||
BitTorrent::TorrentHandle *const torrent = m_torrents.value(index.row());
|
||||
if (!torrent) return QVariant();
|
||||
|
||||
if ((role == Qt::DecorationRole) && (index.column() == TR_NAME))
|
||||
return getIconByState(torrent->state());
|
||||
|
||||
if (role == Qt::ForegroundRole)
|
||||
return getColorByState(torrent->state());
|
||||
|
||||
if ((role != Qt::DisplayRole) && (role != Qt::UserRole))
|
||||
return QVariant();
|
||||
|
||||
switch(index.column()) {
|
||||
case TR_NAME:
|
||||
return torrent->name();
|
||||
case TR_PRIORITY:
|
||||
return torrent->queuePosition();
|
||||
case TR_SIZE:
|
||||
return torrent->wantedSize();
|
||||
case TR_PROGRESS:
|
||||
return torrent->progress();
|
||||
case TR_STATUS:
|
||||
return static_cast<int>(torrent->state());
|
||||
case TR_SEEDS:
|
||||
return (role == Qt::DisplayRole) ? torrent->seedsCount() : torrent->completeCount();
|
||||
case TR_PEERS:
|
||||
return (role == Qt::DisplayRole) ? (torrent->peersCount() - torrent->seedsCount()) : torrent->incompleteCount();
|
||||
case TR_DLSPEED:
|
||||
return torrent->downloadPayloadRate();
|
||||
case TR_UPSPEED:
|
||||
return torrent->uploadPayloadRate();
|
||||
case TR_ETA:
|
||||
return torrent->eta();
|
||||
case TR_RATIO:
|
||||
return torrent->realRatio();
|
||||
case TR_LABEL:
|
||||
return torrent->label();
|
||||
case TR_ADD_DATE:
|
||||
return torrent->addedTime();
|
||||
case TR_SEED_DATE:
|
||||
return torrent->completedTime();
|
||||
case TR_TRACKER:
|
||||
return torrent->currentTracker();
|
||||
case TR_DLLIMIT:
|
||||
return torrent->downloadLimit();
|
||||
case TR_UPLIMIT:
|
||||
return torrent->uploadLimit();
|
||||
case TR_AMOUNT_DOWNLOADED:
|
||||
return torrent->totalDownload();
|
||||
case TR_AMOUNT_UPLOADED:
|
||||
return torrent->totalUpload();
|
||||
case TR_AMOUNT_DOWNLOADED_SESSION:
|
||||
return torrent->totalPayloadDownload();
|
||||
case TR_AMOUNT_UPLOADED_SESSION:
|
||||
return torrent->totalPayloadUpload();
|
||||
case TR_AMOUNT_LEFT:
|
||||
return torrent->incompletedSize();
|
||||
case TR_TIME_ELAPSED:
|
||||
return (role == Qt::DisplayRole) ? torrent->activeTime() : torrent->seedingTime();
|
||||
case TR_SAVE_PATH:
|
||||
return torrent->savePathParsed();
|
||||
case TR_COMPLETED:
|
||||
return torrent->completedSize();
|
||||
case TR_RATIO_LIMIT:
|
||||
return torrent->maxRatio();
|
||||
case TR_SEEN_COMPLETE_DATE:
|
||||
return torrent->lastSeenComplete();
|
||||
case TR_LAST_ACTIVITY:
|
||||
if (torrent->isPaused() || torrent->isChecking())
|
||||
return -1;
|
||||
return torrent->timeSinceActivity();
|
||||
case TR_TOTAL_SIZE:
|
||||
return torrent->totalSize();
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool TorrentModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << value;
|
||||
if (!index.isValid() || (role != Qt::DisplayRole)) return false;
|
||||
|
||||
qDebug("Index is valid and role is DisplayRole");
|
||||
BitTorrent::TorrentHandle *const torrent = m_torrents.value(index.row());
|
||||
if (!torrent) return false;
|
||||
|
||||
// Label, seed date and Name columns can be edited
|
||||
switch(index.column()) {
|
||||
case TR_NAME:
|
||||
torrent->setName(value.toString());
|
||||
break;
|
||||
case TR_LABEL:
|
||||
torrent->setLabel(value.toString());
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void TorrentModel::addTorrent(BitTorrent::TorrentHandle *const torrent)
|
||||
{
|
||||
if (m_torrents.indexOf(torrent) == -1) {
|
||||
const int row = m_torrents.size();
|
||||
beginInsertRows(QModelIndex(), row, row);
|
||||
m_torrents << torrent;
|
||||
endInsertRows();
|
||||
}
|
||||
}
|
||||
|
||||
Qt::ItemFlags TorrentModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid()) return 0;
|
||||
|
||||
// Explicitly mark as editable
|
||||
return QAbstractListModel::flags(index) | Qt::ItemIsEditable;
|
||||
}
|
||||
|
||||
BitTorrent::TorrentHandle *TorrentModel::torrentHandle(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid()) return 0;
|
||||
|
||||
return m_torrents.value(index.row());
|
||||
}
|
||||
|
||||
void TorrentModel::handleTorrentAboutToBeRemoved(BitTorrent::TorrentHandle *const torrent)
|
||||
{
|
||||
const int row = m_torrents.indexOf(torrent);
|
||||
if (row >= 0) {
|
||||
beginRemoveRows(QModelIndex(), row, row);
|
||||
m_torrents.removeAt(row);
|
||||
endRemoveRows();
|
||||
}
|
||||
}
|
||||
|
||||
void TorrentModel::handleTorrentStatusUpdated(BitTorrent::TorrentHandle *const torrent)
|
||||
{
|
||||
const int row = m_torrents.indexOf(torrent);
|
||||
if (row >= 0)
|
||||
emit dataChanged(index(row, 0), index(row, columnCount() - 1));
|
||||
}
|
||||
|
||||
// Static functions
|
||||
|
||||
QIcon getIconByState(BitTorrent::TorrentState state)
|
||||
{
|
||||
switch (state) {
|
||||
case BitTorrent::TorrentState::Downloading:
|
||||
case BitTorrent::TorrentState::ForcedDownloading:
|
||||
case BitTorrent::TorrentState::DownloadingMetadata:
|
||||
return get_downloading_icon();
|
||||
return getDownloadingIcon();
|
||||
case BitTorrent::TorrentState::Allocating:
|
||||
case BitTorrent::TorrentState::StalledDownloading:
|
||||
return get_stalled_downloading_icon();
|
||||
return getStalledDownloadingIcon();
|
||||
case BitTorrent::TorrentState::StalledUploading:
|
||||
return get_stalled_uploading_icon();
|
||||
return getStalledUploadingIcon();
|
||||
case BitTorrent::TorrentState::Uploading:
|
||||
case BitTorrent::TorrentState::ForcedUploading:
|
||||
return get_uploading_icon();
|
||||
return getUploadingIcon();
|
||||
case BitTorrent::TorrentState::PausedDownloading:
|
||||
return get_paused_icon();
|
||||
return getPausedIcon();
|
||||
case BitTorrent::TorrentState::PausedUploading:
|
||||
return get_completed_icon();
|
||||
return getCompletedIcon();
|
||||
case BitTorrent::TorrentState::QueuedDownloading:
|
||||
case BitTorrent::TorrentState::QueuedUploading:
|
||||
return get_queued_icon();
|
||||
return getQueuedIcon();
|
||||
case BitTorrent::TorrentState::CheckingDownloading:
|
||||
case BitTorrent::TorrentState::CheckingUploading:
|
||||
return get_checking_icon();
|
||||
return getCheckingIcon();
|
||||
case BitTorrent::TorrentState::Unknown:
|
||||
case BitTorrent::TorrentState::Error:
|
||||
return get_error_icon();
|
||||
return getErrorIcon();
|
||||
default:
|
||||
Q_ASSERT(false);
|
||||
return get_error_icon();
|
||||
return getErrorIcon();
|
||||
}
|
||||
}
|
||||
|
||||
QColor TorrentModelItem::getColorByState(BitTorrent::TorrentState state)
|
||||
QColor getColorByState(BitTorrent::TorrentState state)
|
||||
{
|
||||
bool dark = isDarkTheme();
|
||||
|
||||
|
@ -181,336 +387,64 @@ QColor TorrentModelItem::getColorByState(BitTorrent::TorrentState state)
|
|||
}
|
||||
}
|
||||
|
||||
bool TorrentModelItem::setData(int column, const QVariant &value, int role)
|
||||
QIcon getPausedIcon()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << column << value;
|
||||
if (role != Qt::DisplayRole) return false;
|
||||
|
||||
// Label, seed date and Name columns can be edited
|
||||
switch(column) {
|
||||
case TR_NAME:
|
||||
m_torrent->setName(value.toString());
|
||||
return true;
|
||||
case TR_LABEL: {
|
||||
QString new_label = value.toString();
|
||||
if (m_torrent->label() != new_label) {
|
||||
QString old_label = m_torrent->label();
|
||||
m_torrent->setLabel(new_label);
|
||||
emit labelChanged(old_label, new_label);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
static QIcon cached = QIcon(":/icons/skin/paused.png");
|
||||
return cached;
|
||||
}
|
||||
|
||||
QVariant TorrentModelItem::data(int column, int role) const
|
||||
QIcon getQueuedIcon()
|
||||
{
|
||||
if ((role == Qt::DecorationRole) && (column == TR_NAME))
|
||||
return getIconByState(state());
|
||||
|
||||
if (role == Qt::ForegroundRole)
|
||||
return getColorByState(state());
|
||||
|
||||
if ((role != Qt::DisplayRole) && (role != Qt::UserRole))
|
||||
return QVariant();
|
||||
|
||||
switch(column) {
|
||||
case TR_NAME:
|
||||
return m_torrent->name();
|
||||
case TR_PRIORITY:
|
||||
return m_torrent->queuePosition();
|
||||
case TR_SIZE:
|
||||
return m_torrent->hasMetadata() ? m_torrent->wantedSize() : -1;
|
||||
case TR_PROGRESS:
|
||||
return m_torrent->progress();
|
||||
case TR_STATUS:
|
||||
return static_cast<int>(m_torrent->state());
|
||||
case TR_SEEDS:
|
||||
return (role == Qt::DisplayRole) ? m_torrent->seedsCount() : m_torrent->completeCount();
|
||||
case TR_PEERS:
|
||||
return (role == Qt::DisplayRole) ? (m_torrent->peersCount() - m_torrent->seedsCount()) : m_torrent->incompleteCount();
|
||||
case TR_DLSPEED:
|
||||
return m_torrent->downloadPayloadRate();
|
||||
case TR_UPSPEED:
|
||||
return m_torrent->uploadPayloadRate();
|
||||
case TR_ETA:
|
||||
return m_torrent->eta();
|
||||
case TR_RATIO:
|
||||
return m_torrent->realRatio();
|
||||
case TR_LABEL:
|
||||
return m_torrent->label();
|
||||
case TR_ADD_DATE:
|
||||
return m_torrent->addedTime();
|
||||
case TR_SEED_DATE:
|
||||
return m_torrent->completedTime();
|
||||
case TR_TRACKER:
|
||||
return m_torrent->currentTracker();
|
||||
case TR_DLLIMIT:
|
||||
return m_torrent->downloadLimit();
|
||||
case TR_UPLIMIT:
|
||||
return m_torrent->uploadLimit();
|
||||
case TR_AMOUNT_DOWNLOADED:
|
||||
return m_torrent->totalDownload();
|
||||
case TR_AMOUNT_UPLOADED:
|
||||
return m_torrent->totalUpload();
|
||||
case TR_AMOUNT_DOWNLOADED_SESSION:
|
||||
return m_torrent->totalPayloadDownload();
|
||||
case TR_AMOUNT_UPLOADED_SESSION:
|
||||
return m_torrent->totalPayloadUpload();
|
||||
case TR_AMOUNT_LEFT:
|
||||
return m_torrent->incompletedSize();
|
||||
case TR_TIME_ELAPSED:
|
||||
return (role == Qt::DisplayRole) ? m_torrent->activeTime() : m_torrent->seedingTime();
|
||||
case TR_SAVE_PATH:
|
||||
return m_torrent->savePathParsed();
|
||||
case TR_COMPLETED:
|
||||
return m_torrent->completedSize();
|
||||
case TR_RATIO_LIMIT:
|
||||
return m_torrent->maxRatio();
|
||||
case TR_SEEN_COMPLETE_DATE:
|
||||
return m_torrent->lastSeenComplete();
|
||||
case TR_LAST_ACTIVITY:
|
||||
if (m_torrent->isPaused() || m_torrent->isChecking())
|
||||
return -1;
|
||||
if (m_torrent->timeSinceUpload() < m_torrent->timeSinceDownload())
|
||||
return m_torrent->timeSinceUpload();
|
||||
else
|
||||
return m_torrent->timeSinceDownload();
|
||||
case TR_TOTAL_SIZE:
|
||||
return m_torrent->hasMetadata() ? m_torrent->totalSize() : -1;
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
static QIcon cached = QIcon(":/icons/skin/queued.png");
|
||||
return cached;
|
||||
}
|
||||
|
||||
BitTorrent::TorrentHandle *TorrentModelItem::torrentHandle() const
|
||||
QIcon getDownloadingIcon()
|
||||
{
|
||||
return m_torrent;
|
||||
static QIcon cached = QIcon(":/icons/skin/downloading.png");
|
||||
return cached;
|
||||
}
|
||||
|
||||
// TORRENT MODEL
|
||||
|
||||
TorrentModel::TorrentModel(QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
QIcon getStalledDownloadingIcon()
|
||||
{
|
||||
static QIcon cached = QIcon(":/icons/skin/stalledDL.png");
|
||||
return cached;
|
||||
}
|
||||
|
||||
void TorrentModel::populate()
|
||||
QIcon getUploadingIcon()
|
||||
{
|
||||
// Load the torrents
|
||||
foreach (BitTorrent::TorrentHandle *const torrent, BitTorrent::Session::instance()->torrents())
|
||||
addTorrent(torrent);
|
||||
|
||||
// Listen for torrent changes
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(torrentAdded(BitTorrent::TorrentHandle *const)), SLOT(addTorrent(BitTorrent::TorrentHandle *const)));
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(torrentAboutToBeRemoved(BitTorrent::TorrentHandle *const)), SLOT(handleTorrentAboutToBeRemoved(BitTorrent::TorrentHandle *const)));
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(torrentStatusUpdated(BitTorrent::TorrentHandle *const)), this, SLOT(handleTorrentStatusUpdated(BitTorrent::TorrentHandle *const)));
|
||||
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(torrentFinished(BitTorrent::TorrentHandle *const)), SLOT(handleTorrentStatusUpdated(BitTorrent::TorrentHandle *const)));
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(torrentMetadataLoaded(BitTorrent::TorrentHandle *const)), SLOT(handleTorrentStatusUpdated(BitTorrent::TorrentHandle *const)));
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(torrentResumed(BitTorrent::TorrentHandle *const)), SLOT(handleTorrentStatusUpdated(BitTorrent::TorrentHandle *const)));
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(torrentPaused(BitTorrent::TorrentHandle *const)), SLOT(handleTorrentStatusUpdated(BitTorrent::TorrentHandle *const)));
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(torrentFinishedChecking(BitTorrent::TorrentHandle *const)), SLOT(handleTorrentStatusUpdated(BitTorrent::TorrentHandle *const)));
|
||||
static QIcon cached = QIcon(":/icons/skin/uploading.png");
|
||||
return cached;
|
||||
}
|
||||
|
||||
TorrentModel::~TorrentModel() {
|
||||
qDebug() << Q_FUNC_INFO << "ENTER";
|
||||
qDeleteAll(m_items);
|
||||
m_items.clear();
|
||||
qDebug() << Q_FUNC_INFO << "EXIT";
|
||||
}
|
||||
|
||||
QVariant TorrentModel::headerData(int section, Qt::Orientation orientation,
|
||||
int role) const
|
||||
QIcon getStalledUploadingIcon()
|
||||
{
|
||||
if (orientation == Qt::Horizontal) {
|
||||
if (role == Qt::DisplayRole) {
|
||||
switch(section) {
|
||||
case TorrentModelItem::TR_PRIORITY: return "#";
|
||||
case TorrentModelItem::TR_NAME: return tr("Name", "i.e: torrent name");
|
||||
case TorrentModelItem::TR_SIZE: return tr("Size", "i.e: torrent size");
|
||||
case TorrentModelItem::TR_PROGRESS: return tr("Done", "% Done");
|
||||
case TorrentModelItem::TR_STATUS: return tr("Status", "Torrent status (e.g. downloading, seeding, paused)");
|
||||
case TorrentModelItem::TR_SEEDS: return tr("Seeds", "i.e. full sources (often untranslated)");
|
||||
case TorrentModelItem::TR_PEERS: return tr("Peers", "i.e. partial sources (often untranslated)");
|
||||
case TorrentModelItem::TR_DLSPEED: return tr("Down Speed", "i.e: Download speed");
|
||||
case TorrentModelItem::TR_UPSPEED: return tr("Up Speed", "i.e: Upload speed");
|
||||
case TorrentModelItem::TR_RATIO: return tr("Ratio", "Share ratio");
|
||||
case TorrentModelItem::TR_ETA: return tr("ETA", "i.e: Estimated Time of Arrival / Time left");
|
||||
case TorrentModelItem::TR_LABEL: return tr("Label");
|
||||
case TorrentModelItem::TR_ADD_DATE: return tr("Added On", "Torrent was added to transfer list on 01/01/2010 08:00");
|
||||
case TorrentModelItem::TR_SEED_DATE: return tr("Completed On", "Torrent was completed on 01/01/2010 08:00");
|
||||
case TorrentModelItem::TR_TRACKER: return tr("Tracker");
|
||||
case TorrentModelItem::TR_DLLIMIT: return tr("Down Limit", "i.e: Download limit");
|
||||
case TorrentModelItem::TR_UPLIMIT: return tr("Up Limit", "i.e: Upload limit");
|
||||
case TorrentModelItem::TR_AMOUNT_DOWNLOADED: return tr("Downloaded", "Amount of data downloaded (e.g. in MB)");
|
||||
case TorrentModelItem::TR_AMOUNT_UPLOADED: return tr("Uploaded", "Amount of data uploaded (e.g. in MB)");
|
||||
case TorrentModelItem::TR_AMOUNT_DOWNLOADED_SESSION: return tr("Session Download", "Amount of data downloaded since program open (e.g. in MB)");
|
||||
case TorrentModelItem::TR_AMOUNT_UPLOADED_SESSION: return tr("Session Upload", "Amount of data uploaded since program open (e.g. in MB)");
|
||||
case TorrentModelItem::TR_AMOUNT_LEFT: return tr("Remaining", "Amount of data left to download (e.g. in MB)");
|
||||
case TorrentModelItem::TR_TIME_ELAPSED: return tr("Time Active", "Time (duration) the torrent is active (not paused)");
|
||||
case TorrentModelItem::TR_SAVE_PATH: return tr("Save path", "Torrent save path");
|
||||
case TorrentModelItem::TR_COMPLETED: return tr("Completed", "Amount of data completed (e.g. in MB)");
|
||||
case TorrentModelItem::TR_RATIO_LIMIT: return tr("Ratio Limit", "Upload share ratio limit");
|
||||
case TorrentModelItem::TR_SEEN_COMPLETE_DATE: return tr("Last Seen Complete", "Indicates the time when the torrent was last seen complete/whole");
|
||||
case TorrentModelItem::TR_LAST_ACTIVITY: return tr("Last Activity", "Time passed since a chunk was downloaded/uploaded");
|
||||
case TorrentModelItem::TR_TOTAL_SIZE: return tr("Total Size", "i.e. Size including unwanted data");
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
else if (role == Qt::TextAlignmentRole) {
|
||||
switch(section) {
|
||||
case TorrentModelItem::TR_AMOUNT_DOWNLOADED:
|
||||
case TorrentModelItem::TR_AMOUNT_UPLOADED:
|
||||
case TorrentModelItem::TR_AMOUNT_DOWNLOADED_SESSION:
|
||||
case TorrentModelItem::TR_AMOUNT_UPLOADED_SESSION:
|
||||
case TorrentModelItem::TR_AMOUNT_LEFT:
|
||||
case TorrentModelItem::TR_COMPLETED:
|
||||
case TorrentModelItem::TR_SIZE:
|
||||
case TorrentModelItem::TR_TOTAL_SIZE:
|
||||
case TorrentModelItem::TR_ETA:
|
||||
case TorrentModelItem::TR_SEEDS:
|
||||
case TorrentModelItem::TR_PEERS:
|
||||
case TorrentModelItem::TR_UPSPEED:
|
||||
case TorrentModelItem::TR_DLSPEED:
|
||||
case TorrentModelItem::TR_UPLIMIT:
|
||||
case TorrentModelItem::TR_DLLIMIT:
|
||||
case TorrentModelItem::TR_RATIO_LIMIT:
|
||||
case TorrentModelItem::TR_RATIO:
|
||||
case TorrentModelItem::TR_PRIORITY:
|
||||
case TorrentModelItem::TR_LAST_ACTIVITY:
|
||||
return QVariant(Qt::AlignRight | Qt::AlignVCenter);
|
||||
default:
|
||||
return QAbstractListModel::headerData(section, orientation, role);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
static QIcon cached = QIcon(":/icons/skin/stalledUP.png");
|
||||
return cached;
|
||||
}
|
||||
|
||||
QVariant TorrentModel::data(const QModelIndex &index, int role) const
|
||||
QIcon getCompletedIcon()
|
||||
{
|
||||
if (!index.isValid()) return QVariant();
|
||||
|
||||
if (index.row() >= 0 && index.row() < rowCount() && index.column() >= 0 && index.column() < columnCount())
|
||||
return m_items[index.row()]->data(index.column(), role);
|
||||
|
||||
return QVariant();
|
||||
static QIcon cached = QIcon(":/icons/skin/completed.png");
|
||||
return cached;
|
||||
}
|
||||
|
||||
bool TorrentModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
QIcon getCheckingIcon()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << value;
|
||||
if (!index.isValid() || (role != Qt::DisplayRole)) return false;
|
||||
|
||||
qDebug("Index is valid and role is DisplayRole");
|
||||
if ((index.row() >= 0) && (index.row() < rowCount()) && (index.column() >= 0) && (index.column() < columnCount())) {
|
||||
bool change = m_items[index.row()]->setData(index.column(), value, role);
|
||||
if (change)
|
||||
notifyTorrentChanged(index.row());
|
||||
return change;
|
||||
}
|
||||
|
||||
return false;
|
||||
static QIcon cached = QIcon(":/icons/skin/checking.png");
|
||||
return cached;
|
||||
}
|
||||
|
||||
int TorrentModel::torrentRow(const BitTorrent::InfoHash &hash) const
|
||||
QIcon getErrorIcon()
|
||||
{
|
||||
int row = 0;
|
||||
|
||||
foreach (TorrentModelItem *const item, m_items) {
|
||||
if (item->hash() == hash) return row;
|
||||
++row;
|
||||
}
|
||||
return -1;
|
||||
static QIcon cached = QIcon(":/icons/skin/error.png");
|
||||
return cached;
|
||||
}
|
||||
|
||||
void TorrentModel::addTorrent(BitTorrent::TorrentHandle *const torrent)
|
||||
bool isDarkTheme()
|
||||
{
|
||||
if (torrentRow(torrent->hash()) < 0) {
|
||||
beginInsertTorrent(m_items.size());
|
||||
TorrentModelItem *item = new TorrentModelItem(torrent);
|
||||
connect(item, SIGNAL(labelChanged(QString, QString)), SLOT(handleTorrentLabelChange(QString, QString)));
|
||||
m_items << item;
|
||||
emit torrentAdded(item);
|
||||
endInsertTorrent();
|
||||
}
|
||||
}
|
||||
|
||||
void TorrentModel::beginInsertTorrent(int row)
|
||||
{
|
||||
beginInsertRows(QModelIndex(), row, row);
|
||||
}
|
||||
|
||||
void TorrentModel::endInsertTorrent()
|
||||
{
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
void TorrentModel::beginRemoveTorrent(int row)
|
||||
{
|
||||
beginRemoveRows(QModelIndex(), row, row);
|
||||
}
|
||||
|
||||
void TorrentModel::endRemoveTorrent()
|
||||
{
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
void TorrentModel::notifyTorrentChanged(int row)
|
||||
{
|
||||
emit dataChanged(index(row, 0), index(row, columnCount() - 1));
|
||||
}
|
||||
|
||||
Qt::ItemFlags TorrentModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return 0;
|
||||
// Explicitly mark as editable
|
||||
return QAbstractListModel::flags(index) | Qt::ItemIsEditable;
|
||||
}
|
||||
|
||||
void TorrentModel::handleTorrentLabelChange(QString previous, QString current)
|
||||
{
|
||||
emit torrentChangedLabel(static_cast<TorrentModelItem*>(sender()), previous, current);
|
||||
}
|
||||
|
||||
QString TorrentModel::torrentHash(int row) const
|
||||
{
|
||||
if (row >= 0 && row < rowCount())
|
||||
return m_items.at(row)->hash();
|
||||
return QString();
|
||||
}
|
||||
|
||||
BitTorrent::TorrentHandle *TorrentModel::torrentHandle(const QModelIndex &index) const
|
||||
{
|
||||
if (index.isValid() && (index.row() >= 0) && (index.row() < rowCount()))
|
||||
return m_items[index.row()]->torrentHandle();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void TorrentModel::handleTorrentAboutToBeRemoved(BitTorrent::TorrentHandle *const torrent)
|
||||
{
|
||||
const int row = torrentRow(torrent->hash());
|
||||
qDebug() << Q_FUNC_INFO << row;
|
||||
if (row >= 0) {
|
||||
emit torrentAboutToBeRemoved(m_items.at(row));
|
||||
|
||||
beginRemoveTorrent(row);
|
||||
delete m_items.takeAt(row);
|
||||
endRemoveTorrent();
|
||||
}
|
||||
}
|
||||
|
||||
void TorrentModel::handleTorrentStatusUpdated(BitTorrent::TorrentHandle *const torrent)
|
||||
{
|
||||
const int row = torrentRow(torrent->hash());
|
||||
if (row >= 0)
|
||||
notifyTorrentChanged(row);
|
||||
QPalette pal = QApplication::palette();
|
||||
// QPalette::Base is used for the background of the Treeview
|
||||
QColor color = pal.color(QPalette::Active, QPalette::Base);
|
||||
return (color.lightness() < 127);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue