Merge pull request #3187 from glassez/model

Improve TorrentModel class (Issue #2433).
This commit is contained in:
sledgehammer999 2015-06-21 16:32:30 +03:00
commit bc97208516
15 changed files with 576 additions and 695 deletions

View File

@ -59,6 +59,7 @@ struct SessionPrivate
virtual void handleTorrentRatioLimitChanged(BitTorrent::TorrentHandle *const torrent) = 0;
virtual void handleTorrentSavePathChanged(BitTorrent::TorrentHandle *const torrent) = 0;
virtual void handleTorrentLabelChanged(BitTorrent::TorrentHandle *const torrent, const QString &oldLabel) = 0;
virtual void handleTorrentMetadataReceived(BitTorrent::TorrentHandle *const torrent) = 0;
virtual void handleTorrentPaused(BitTorrent::TorrentHandle *const torrent) = 0;
virtual void handleTorrentResumed(BitTorrent::TorrentHandle *const torrent) = 0;

View File

@ -1631,6 +1631,11 @@ void Session::handleTorrentSavePathChanged(TorrentHandle *const torrent)
emit torrentSavePathChanged(torrent);
}
void Session::handleTorrentLabelChanged(TorrentHandle *const torrent, const QString &oldLabel)
{
emit torrentLabelChanged(torrent, oldLabel);
}
void Session::handleTorrentTrackersAdded(TorrentHandle *const torrent, const QList<TrackerEntry> &newTrackers)
{
foreach (const TrackerEntry &newTracker, newTrackers)

View File

@ -195,6 +195,7 @@ namespace BitTorrent
void torrentFinished(BitTorrent::TorrentHandle *const torrent);
void torrentFinishedChecking(BitTorrent::TorrentHandle *const torrent);
void torrentSavePathChanged(BitTorrent::TorrentHandle *const torrent);
void torrentLabelChanged(BitTorrent::TorrentHandle *const torrent, const QString &oldLabel);
void allTorrentsFinished();
void metadataLoaded(const BitTorrent::TorrentInfo &info);
void torrentMetadataLoaded(BitTorrent::TorrentHandle *const torrent);
@ -289,6 +290,7 @@ namespace BitTorrent
QString tempPath() const;
void handleTorrentRatioLimitChanged(TorrentHandle *const torrent);
void handleTorrentSavePathChanged(TorrentHandle *const torrent);
void handleTorrentLabelChanged(TorrentHandle *const torrent, const QString &oldLabel);
void handleTorrentMetadataReceived(TorrentHandle *const torrent);
void handleTorrentPaused(TorrentHandle *const torrent);
void handleTorrentResumed(TorrentHandle *const torrent);

View File

@ -969,6 +969,14 @@ int TorrentHandle::timeSinceDownload() const
return m_nativeStatus.time_since_download;
}
int TorrentHandle::timeSinceActivity() const
{
if (m_nativeStatus.time_since_upload < m_nativeStatus.time_since_download)
return m_nativeStatus.time_since_upload;
else
return m_nativeStatus.time_since_download;
}
int TorrentHandle::downloadLimit() const
{
SAFE_RETURN(int, download_limit, -1)
@ -1117,9 +1125,11 @@ void TorrentHandle::setName(const QString &name)
void TorrentHandle::setLabel(const QString &label)
{
if (m_label != label) {
QString oldLabel = m_label;
m_label = label;
m_needSaveResumeData = true;
adjustSavePath();
m_session->handleTorrentLabelChanged(this, oldLabel);
}
}

View File

@ -241,6 +241,7 @@ namespace BitTorrent
QDateTime completedTime() const;
int timeSinceUpload() const;
int timeSinceDownload() const;
int timeSinceActivity() const;
int downloadLimit() const;
int uploadLimit() const;
bool superSeeding() const;

View File

@ -332,8 +332,6 @@ MainWindow::MainWindow(QWidget *parent)
connect(executable_watcher, SIGNAL(fileChanged(QString)), this, SLOT(notifyOfUpdate(QString)));
executable_watcher->addPath(qApp->applicationFilePath());
// Populate the transfer list
transferList->getSourceModel()->populate();
transferList->setFocus();
// Update the number of torrents (tab)

View File

@ -97,7 +97,6 @@ public slots:
void saveSettings();
void reloadPreferences();
void openDoubleClickedFile(const QModelIndex &);
void updateSavePath(BitTorrent::TorrentHandle *const torrent);
void loadTrackers(BitTorrent::TorrentHandle *const torrent);
private:
@ -126,6 +125,7 @@ private:
private slots:
void filterText(const QString& filter);
void updateSavePath(BitTorrent::TorrentHandle *const torrent);
};
#endif // PROPERTIESWIDGET_H

View File

@ -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);
}

View File

@ -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,35 +35,11 @@
#include <QAbstractListModel>
#include <QList>
#include "core/bittorrent/torrenthandle.h"
class QIcon;
class TorrentModelItem : public QObject {
Q_OBJECT
public:
enum Column {TR_PRIORITY, TR_NAME, TR_SIZE, TR_TOTAL_SIZE, TR_PROGRESS, TR_STATUS, TR_SEEDS, TR_PEERS, TR_DLSPEED, TR_UPSPEED, TR_ETA, TR_RATIO, TR_LABEL, TR_ADD_DATE, TR_SEED_DATE, TR_TRACKER, TR_DLLIMIT, TR_UPLIMIT, TR_AMOUNT_DOWNLOADED, TR_AMOUNT_UPLOADED, TR_AMOUNT_DOWNLOADED_SESSION, TR_AMOUNT_UPLOADED_SESSION, TR_AMOUNT_LEFT, TR_TIME_ELAPSED, TR_SAVE_PATH, TR_COMPLETED, TR_RATIO_LIMIT, TR_SEEN_COMPLETE_DATE, TR_LAST_ACTIVITY, NB_COLUMNS};
public:
TorrentModelItem(BitTorrent::TorrentHandle *torrent);
inline int columnCount() const { return NB_COLUMNS; }
QVariant data(int column, int role = Qt::DisplayRole) const;
bool setData(int column, const QVariant &value, int role = Qt::DisplayRole);
inline BitTorrent::InfoHash hash() const { return m_torrent->hash(); }
BitTorrent::TorrentState state() const;
BitTorrent::TorrentHandle *torrentHandle() const;
signals:
void labelChanged(QString previous, QString current);
private:
static QIcon getIconByState(BitTorrent::TorrentState state);
static QColor getColorByState(BitTorrent::TorrentState state);
private:
BitTorrent::TorrentHandle *m_torrent;
};
namespace BitTorrent
{
class InfoHash;
class TorrentHandle;
}
class TorrentModel : public QAbstractListModel
{
@ -70,39 +47,59 @@ class TorrentModel : public QAbstractListModel
Q_DISABLE_COPY(TorrentModel)
public:
enum Column
{
TR_PRIORITY,
TR_NAME,
TR_SIZE,
TR_TOTAL_SIZE,
TR_PROGRESS,
TR_STATUS,
TR_SEEDS,
TR_PEERS,
TR_DLSPEED,
TR_UPSPEED,
TR_ETA,
TR_RATIO,
TR_LABEL,
TR_ADD_DATE,
TR_SEED_DATE,
TR_TRACKER,
TR_DLLIMIT,
TR_UPLIMIT,
TR_AMOUNT_DOWNLOADED,
TR_AMOUNT_UPLOADED,
TR_AMOUNT_DOWNLOADED_SESSION,
TR_AMOUNT_UPLOADED_SESSION,
TR_AMOUNT_LEFT,
TR_TIME_ELAPSED,
TR_SAVE_PATH,
TR_COMPLETED,
TR_RATIO_LIMIT,
TR_SEEN_COMPLETE_DATE,
TR_LAST_ACTIVITY,
NB_COLUMNS
};
explicit TorrentModel(QObject *parent = 0);
~TorrentModel();
inline int rowCount(const QModelIndex& index = QModelIndex()) const { Q_UNUSED(index); return m_items.size(); }
int columnCount(const QModelIndex &parent=QModelIndex()) const { Q_UNUSED(parent); return TorrentModelItem::NB_COLUMNS; }
int rowCount(const QModelIndex& index = QModelIndex()) const;
int columnCount(const QModelIndex &parent=QModelIndex()) const;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::DisplayRole);
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
int torrentRow(const BitTorrent::InfoHash &hash) const;
QString torrentHash(int row) const;
BitTorrent::TorrentHandle *torrentHandle(const QModelIndex &index) const;
Qt::ItemFlags flags(const QModelIndex &index) const;
void populate();
signals:
void torrentAdded(TorrentModelItem *torrentItem);
void torrentAboutToBeRemoved(TorrentModelItem *torrentItem);
void torrentChangedLabel(TorrentModelItem *torrentItem, QString previous, QString current);
BitTorrent::TorrentHandle *torrentHandle(const QModelIndex &index) const;
private slots:
void addTorrent(BitTorrent::TorrentHandle *const torrent);
void notifyTorrentChanged(int row);
void handleTorrentLabelChange(QString previous, QString current);
void handleTorrentAboutToBeRemoved(BitTorrent::TorrentHandle *const torrent);
void handleTorrentStatusUpdated(BitTorrent::TorrentHandle *const torrent);
private:
void beginInsertTorrent(int row);
void endInsertTorrent();
void beginRemoveTorrent(int row);
void endRemoveTorrent();
private:
QList<TorrentModelItem*> m_items;
QList<BitTorrent::TorrentHandle *> m_torrents;
};
#endif // TORRENTMODEL_H

View File

@ -56,27 +56,27 @@ void TransferListDelegate::paint(QPainter * painter, const QStyleOptionViewItem
QStyleOptionViewItemV2 opt = QItemDelegate::setOptions(index, option);
painter->save();
switch(index.column()) {
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 TorrentModel::TR_AMOUNT_DOWNLOADED:
case TorrentModel::TR_AMOUNT_UPLOADED:
case TorrentModel::TR_AMOUNT_DOWNLOADED_SESSION:
case TorrentModel::TR_AMOUNT_UPLOADED_SESSION:
case TorrentModel::TR_AMOUNT_LEFT:
case TorrentModel::TR_COMPLETED:
case TorrentModel::TR_SIZE:
case TorrentModel::TR_TOTAL_SIZE: {
QItemDelegate::drawBackground(painter, opt, index);
opt.displayAlignment = Qt::AlignRight | Qt::AlignVCenter;
QItemDelegate::drawDisplay(painter, opt, option.rect, Utils::Misc::friendlyUnit(index.data().toLongLong()));
break;
}
case TorrentModelItem::TR_ETA: {
case TorrentModel::TR_ETA: {
QItemDelegate::drawBackground(painter, opt, index);
opt.displayAlignment = Qt::AlignRight | Qt::AlignVCenter;
QItemDelegate::drawDisplay(painter, opt, option.rect, Utils::Misc::userFriendlyDuration(index.data().toLongLong()));
break;
}
case TorrentModelItem::TR_SEEDS:
case TorrentModelItem::TR_PEERS: {
case TorrentModel::TR_SEEDS:
case TorrentModel::TR_PEERS: {
QString display = QString::number(index.data().toLongLong());
qlonglong total = index.data(Qt::UserRole).toLongLong();
if (total > 0) {
@ -88,7 +88,7 @@ void TransferListDelegate::paint(QPainter * painter, const QStyleOptionViewItem
QItemDelegate::drawDisplay(painter, opt, opt.rect, display);
break;
}
case TorrentModelItem::TR_STATUS: {
case TorrentModel::TR_STATUS: {
const int state = index.data().toInt();
QString display;
switch(state) {
@ -138,23 +138,23 @@ void TransferListDelegate::paint(QPainter * painter, const QStyleOptionViewItem
QItemDelegate::drawDisplay(painter, opt, opt.rect, display);
break;
}
case TorrentModelItem::TR_UPSPEED:
case TorrentModelItem::TR_DLSPEED: {
case TorrentModel::TR_UPSPEED:
case TorrentModel::TR_DLSPEED: {
QItemDelegate::drawBackground(painter, opt, index);
const qulonglong speed = index.data().toULongLong();
opt.displayAlignment = Qt::AlignRight | Qt::AlignVCenter;
QItemDelegate::drawDisplay(painter, opt, opt.rect, Utils::Misc::friendlyUnit(speed)+tr("/s", "/second (.i.e per second)"));
break;
}
case TorrentModelItem::TR_UPLIMIT:
case TorrentModelItem::TR_DLLIMIT: {
case TorrentModel::TR_UPLIMIT:
case TorrentModel::TR_DLLIMIT: {
QItemDelegate::drawBackground(painter, opt, index);
const qlonglong limit = index.data().toLongLong();
opt.displayAlignment = Qt::AlignRight | Qt::AlignVCenter;
QItemDelegate::drawDisplay(painter, opt, opt.rect, limit > 0 ? Utils::String::fromDouble(limit/1024., 1) + " " + tr("KiB/s", "KiB/second (.i.e per second)") : QString::fromUtf8(""));
break;
}
case TorrentModelItem::TR_TIME_ELAPSED: {
case TorrentModel::TR_TIME_ELAPSED: {
QItemDelegate::drawBackground(painter, opt, index);
QString txt = Utils::Misc::userFriendlyDuration(index.data().toLongLong());
qlonglong seeding_time = index.data(Qt::UserRole).toLongLong();
@ -163,13 +163,13 @@ void TransferListDelegate::paint(QPainter * painter, const QStyleOptionViewItem
QItemDelegate::drawDisplay(painter, opt, opt.rect, txt);
break;
}
case TorrentModelItem::TR_ADD_DATE:
case TorrentModelItem::TR_SEED_DATE:
case TorrentModel::TR_ADD_DATE:
case TorrentModel::TR_SEED_DATE:
QItemDelegate::drawBackground(painter, opt, index);
QItemDelegate::drawDisplay(painter, opt, opt.rect, index.data().toDateTime().toLocalTime().toString(Qt::DefaultLocaleShortDate));
break;
case TorrentModelItem::TR_RATIO_LIMIT:
case TorrentModelItem::TR_RATIO: {
case TorrentModel::TR_RATIO_LIMIT:
case TorrentModel::TR_RATIO: {
QItemDelegate::drawBackground(painter, opt, index);
opt.displayAlignment = Qt::AlignRight | Qt::AlignVCenter;
const qreal ratio = index.data().toDouble();
@ -177,7 +177,7 @@ void TransferListDelegate::paint(QPainter * painter, const QStyleOptionViewItem
((ratio == -1) || (ratio > BitTorrent::TorrentHandle::MAX_RATIO)) ? QString::fromUtf8("") : Utils::String::fromDouble(ratio, 2));
break;
}
case TorrentModelItem::TR_PRIORITY: {
case TorrentModel::TR_PRIORITY: {
const int priority = index.data().toInt();
opt.displayAlignment = Qt::AlignRight | Qt::AlignVCenter;
if (priority > 0)
@ -188,7 +188,7 @@ void TransferListDelegate::paint(QPainter * painter, const QStyleOptionViewItem
}
break;
}
case TorrentModelItem::TR_PROGRESS: {
case TorrentModel::TR_PROGRESS: {
QStyleOptionProgressBarV2 newopt;
qreal progress = index.data().toDouble()*100.;
newopt.rect = opt.rect;
@ -211,7 +211,7 @@ void TransferListDelegate::paint(QPainter * painter, const QStyleOptionViewItem
#endif
break;
}
case TorrentModelItem::TR_LAST_ACTIVITY: {
case TorrentModel::TR_LAST_ACTIVITY: {
QString elapsedString;
long long elapsed = index.data().toLongLong();
QItemDelegate::drawBackground(painter, opt, index);

View File

@ -50,6 +50,7 @@
#include "core/torrentfilter.h"
#include "core/bittorrent/trackerentry.h"
#include "core/bittorrent/session.h"
#include "core/bittorrent/torrenthandle.h"
#include "core/net/downloadmanager.h"
#include "core/net/downloadhandler.h"
#include "core/utils/misc.h"
@ -70,8 +71,9 @@ FiltersBase::FiltersBase(QWidget *parent, TransferListWidget *transferList)
connect(this, SIGNAL(customContextMenuRequested(QPoint)), SLOT(showMenu(QPoint)));
connect(this, SIGNAL(currentRowChanged(int)), SLOT(applyFilter(int)));
connect(transferList->getSourceModel(), SIGNAL(torrentAdded(TorrentModelItem*)), SLOT(handleNewTorrent(TorrentModelItem*)));
connect(transferList->getSourceModel(), SIGNAL(torrentAboutToBeRemoved(TorrentModelItem*)), SLOT(torrentAboutToBeDeleted(TorrentModelItem*)));
connect(BitTorrent::Session::instance(), SIGNAL(torrentAdded(BitTorrent::TorrentHandle *const)), SLOT(handleNewTorrent(BitTorrent::TorrentHandle *const)));
connect(BitTorrent::Session::instance(), SIGNAL(torrentAboutToBeRemoved(BitTorrent::TorrentHandle *const)), SLOT(torrentAboutToBeDeleted(BitTorrent::TorrentHandle *const)));
}
QSize FiltersBase::sizeHint() const
@ -165,9 +167,9 @@ void StatusFiltersWidget::applyFilter(int row)
transferList->applyStatusFilter(row);
}
void StatusFiltersWidget::handleNewTorrent(TorrentModelItem*) {}
void StatusFiltersWidget::handleNewTorrent(BitTorrent::TorrentHandle *const) {}
void StatusFiltersWidget::torrentAboutToBeDeleted(TorrentModelItem*) {}
void StatusFiltersWidget::torrentAboutToBeDeleted(BitTorrent::TorrentHandle *const) {}
LabelFiltersList::LabelFiltersList(QWidget *parent, TransferListWidget *transferList)
: FiltersBase(parent, transferList)
@ -175,7 +177,8 @@ LabelFiltersList::LabelFiltersList(QWidget *parent, TransferListWidget *transfer
, m_totalLabeled(0)
{
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
connect(transferList->getSourceModel(), SIGNAL(torrentChangedLabel(TorrentModelItem*,QString,QString)), SLOT(torrentChangedLabel(TorrentModelItem*, QString, QString)));
connect(BitTorrent::Session::instance(), SIGNAL(torrentLabelChanged(BitTorrent::TorrentHandle *const, QString)), SLOT(torrentChangedLabel(BitTorrent::TorrentHandle *const, QString)));
// Add Label filters
QListWidgetItem *allLabels = new QListWidgetItem(this);
@ -309,12 +312,12 @@ void LabelFiltersList::removeUnusedLabels()
updateGeometry();
}
void LabelFiltersList::torrentChangedLabel(TorrentModelItem *torrentItem, QString old_label, QString new_label)
void LabelFiltersList::torrentChangedLabel(BitTorrent::TorrentHandle *const torrent, const QString &oldLabel)
{
Q_UNUSED(torrentItem);
qDebug("Torrent label changed from %s to %s", qPrintable(old_label), qPrintable(new_label));
removeItem(old_label);
addItem(new_label, true);
qDebug("Torrent label changed from %s to %s", qPrintable(oldLabel), qPrintable(torrent->label()));
removeItem(oldLabel);
QString newLabel = torrent->label();
addItem(newLabel, true);
}
void LabelFiltersList::showMenu(QPoint)
@ -384,21 +387,22 @@ void LabelFiltersList::applyFilter(int row)
}
}
void LabelFiltersList::handleNewTorrent(TorrentModelItem* torrentItem)
void LabelFiltersList::handleNewTorrent(BitTorrent::TorrentHandle *const torrent)
{
Q_ASSERT(torrent);
++m_totalTorrents;
QString label = torrentItem->data(TorrentModelItem::TR_LABEL).toString();
QString label = torrent->label();
addItem(label, true);
// FIXME: Drop this confusion.
// labelFilters->addItem() may have changed the label, update the model accordingly.
torrentItem->setData(TorrentModelItem::TR_LABEL, label);
torrent->setLabel(label);
}
void LabelFiltersList::torrentAboutToBeDeleted(TorrentModelItem* torrentItem)
void LabelFiltersList::torrentAboutToBeDeleted(BitTorrent::TorrentHandle *const torrent)
{
Q_ASSERT(torrent);
--m_totalTorrents;
Q_ASSERT(torrentItem);
QString label = torrentItem->data(TorrentModelItem::TR_LABEL).toString();
removeItem(label);
removeItem(torrent->label());
}
QString LabelFiltersList::labelFromRow(int row) const
@ -681,11 +685,10 @@ void TrackerFiltersList::applyFilter(int row)
transferList->applyTrackerFilter(getHashes(row));
}
void TrackerFiltersList::handleNewTorrent(TorrentModelItem* torrentItem)
void TrackerFiltersList::handleNewTorrent(BitTorrent::TorrentHandle *const torrent)
{
BitTorrent::TorrentHandle *const handle = torrentItem->torrentHandle();
QString hash = handle->hash();
QList<BitTorrent::TrackerEntry> trackers = handle->trackers();
QString hash = torrent->hash();
QList<BitTorrent::TrackerEntry> trackers = torrent->trackers();
foreach (const BitTorrent::TrackerEntry &tracker, trackers)
addItem(tracker.url(), hash);
@ -696,11 +699,10 @@ void TrackerFiltersList::handleNewTorrent(TorrentModelItem* torrentItem)
item(0)->setText(tr("All (%1)", "this is for the tracker filter").arg(++m_totalTorrents));
}
void TrackerFiltersList::torrentAboutToBeDeleted(TorrentModelItem* torrentItem)
void TrackerFiltersList::torrentAboutToBeDeleted(BitTorrent::TorrentHandle *const torrent)
{
BitTorrent::TorrentHandle *const handle = torrentItem->torrentHandle();
QString hash = handle->hash();
QList<BitTorrent::TrackerEntry> trackers = handle->trackers();
QString hash = torrent->hash();
QList<BitTorrent::TrackerEntry> trackers = torrent->trackers();
foreach (const BitTorrent::TrackerEntry &tracker, trackers)
removeItem(tracker.url(), hash);

View File

@ -40,7 +40,6 @@ class QCheckBox;
QT_END_NAMESPACE
class TransferListWidget;
class TorrentModelItem;
namespace BitTorrent
{
@ -68,8 +67,8 @@ protected:
private slots:
virtual void showMenu(QPoint) = 0;
virtual void applyFilter(int row) = 0;
virtual void handleNewTorrent(TorrentModelItem* torrentItem) = 0;
virtual void torrentAboutToBeDeleted(TorrentModelItem* torrentItem) = 0;
virtual void handleNewTorrent(BitTorrent::TorrentHandle *const) = 0;
virtual void torrentAboutToBeDeleted(BitTorrent::TorrentHandle *const) = 0;
};
class StatusFiltersWidget: public FiltersBase
@ -88,8 +87,8 @@ private:
// No need to redeclare them here as slots.
virtual void showMenu(QPoint);
virtual void applyFilter(int row);
virtual void handleNewTorrent(TorrentModelItem*);
virtual void torrentAboutToBeDeleted(TorrentModelItem*);
virtual void handleNewTorrent(BitTorrent::TorrentHandle *const);
virtual void torrentAboutToBeDeleted(BitTorrent::TorrentHandle *const);
};
class LabelFiltersList: public FiltersBase
@ -106,7 +105,7 @@ private slots:
void removeItem(const QString &label);
void removeSelectedLabel();
void removeUnusedLabels();
void torrentChangedLabel(TorrentModelItem *torrentItem, QString old_label, QString new_label);
void torrentChangedLabel(BitTorrent::TorrentHandle *const torrent, const QString &oldLabel);
private:
@ -114,8 +113,8 @@ private:
// No need to redeclare them here as slots.
virtual void showMenu(QPoint);
virtual void applyFilter(int row);
virtual void handleNewTorrent(TorrentModelItem* torrentItem);
virtual void torrentAboutToBeDeleted(TorrentModelItem* torrentItem);
virtual void handleNewTorrent(BitTorrent::TorrentHandle *const torrent);
virtual void torrentAboutToBeDeleted(BitTorrent::TorrentHandle *const torrent);
QString labelFromRow(int row) const;
int rowFromLabel(const QString &label) const;
@ -152,8 +151,8 @@ private:
// No need to redeclare them here as slots.
virtual void showMenu(QPoint);
virtual void applyFilter(int row);
virtual void handleNewTorrent(TorrentModelItem* torrentItem);
virtual void torrentAboutToBeDeleted(TorrentModelItem* torrentItem);
virtual void handleNewTorrent(BitTorrent::TorrentHandle *const torrent);
virtual void torrentAboutToBeDeleted(BitTorrent::TorrentHandle *const torrent);
QString trackerFromRow(int row) const;
int rowFromTracker(const QString &tracker) const;
QString getHost(const QString &trakcer) const;

View File

@ -75,7 +75,7 @@ bool TransferListSortModel::lessThan(const QModelIndex &left, const QModelIndex
{
const int column = sortColumn();
if (column == TorrentModelItem::TR_NAME) {
if (column == TorrentModel::TR_NAME) {
QVariant vL = left.data();
QVariant vR = right.data();
if (!vL.isValid() || !vR.isValid() || (vL == vR))
@ -87,7 +87,7 @@ bool TransferListSortModel::lessThan(const QModelIndex &left, const QModelIndex
return QSortFilterProxyModel::lessThan(left, right);
}
else if (column == TorrentModelItem::TR_ADD_DATE || column == TorrentModelItem::TR_SEED_DATE || column == TorrentModelItem::TR_SEEN_COMPLETE_DATE) {
else if (column == TorrentModel::TR_ADD_DATE || column == TorrentModel::TR_SEED_DATE || column == TorrentModel::TR_SEEN_COMPLETE_DATE) {
QDateTime vL = left.data().toDateTime();
QDateTime vR = right.data().toDateTime();
@ -97,10 +97,10 @@ bool TransferListSortModel::lessThan(const QModelIndex &left, const QModelIndex
return vL < vR;
}
else if (column == TorrentModelItem::TR_PRIORITY) {
else if (column == TorrentModel::TR_PRIORITY) {
return lowerPositionThan(left, right);
}
else if (column == TorrentModelItem::TR_PEERS || column == TorrentModelItem::TR_SEEDS) {
else if (column == TorrentModel::TR_PEERS || column == TorrentModel::TR_SEEDS) {
int left_active = left.data().toInt();
int left_total = left.data(Qt::UserRole).toInt();
int right_active = right.data().toInt();
@ -116,10 +116,10 @@ bool TransferListSortModel::lessThan(const QModelIndex &left, const QModelIndex
return (left_active < right_active);
}
}
else if (column == TorrentModelItem::TR_ETA) {
else if (column == TorrentModel::TR_ETA) {
TorrentModel *model = qobject_cast<TorrentModel *>(sourceModel());
const int prioL = model->data(model->index(left.row(), TorrentModelItem::TR_PRIORITY)).toInt();
const int prioR = model->data(model->index(right.row(), TorrentModelItem::TR_PRIORITY)).toInt();
const int prioL = model->data(model->index(left.row(), TorrentModel::TR_PRIORITY)).toInt();
const int prioR = model->data(model->index(right.row(), TorrentModel::TR_PRIORITY)).toInt();
const qlonglong etaL = left.data().toLongLong();
const qlonglong etaR = right.data().toLongLong();
const bool ascend = (sortOrder() == Qt::AscendingOrder);
@ -144,8 +144,8 @@ bool TransferListSortModel::lessThan(const QModelIndex &left, const QModelIndex
if (invalidL && invalidR) {
if (seedingL) { //Both seeding
QDateTime dateL = model->data(model->index(left.row(), TorrentModelItem::TR_SEED_DATE)).toDateTime();
QDateTime dateR = model->data(model->index(right.row(), TorrentModelItem::TR_SEED_DATE)).toDateTime();
QDateTime dateL = model->data(model->index(left.row(), TorrentModel::TR_SEED_DATE)).toDateTime();
QDateTime dateR = model->data(model->index(right.row(), TorrentModel::TR_SEED_DATE)).toDateTime();
//not valid dates should be sorted at the bottom.
if (!dateL.isValid()) return false;
@ -164,7 +164,7 @@ bool TransferListSortModel::lessThan(const QModelIndex &left, const QModelIndex
return !invalidL;
}
}
else if (column == TorrentModelItem::TR_LAST_ACTIVITY) {
else if (column == TorrentModel::TR_LAST_ACTIVITY) {
const qlonglong vL = left.data().toLongLong();
const qlonglong vR = right.data().toLongLong();
@ -173,7 +173,7 @@ bool TransferListSortModel::lessThan(const QModelIndex &left, const QModelIndex
return vL < vR;
}
else if (column == TorrentModelItem::TR_RATIO_LIMIT) {
else if (column == TorrentModel::TR_RATIO_LIMIT) {
const qreal vL = left.data().toDouble();
const qreal vR = right.data().toDouble();
@ -194,8 +194,8 @@ bool TransferListSortModel::lowerPositionThan(const QModelIndex &left, const QMo
const TorrentModel *model = dynamic_cast<TorrentModel*>(sourceModel());
// Sort according to TR_PRIORITY
const int queueL = model->data(model->index(left.row(), TorrentModelItem::TR_PRIORITY)).toInt();
const int queueR = model->data(model->index(right.row(), TorrentModelItem::TR_PRIORITY)).toInt();
const int queueL = model->data(model->index(left.row(), TorrentModel::TR_PRIORITY)).toInt();
const int queueR = model->data(model->index(right.row(), TorrentModel::TR_PRIORITY)).toInt();
if ((queueL > 0) || (queueR > 0)) {
if ((queueL > 0) && (queueR > 0))
return queueL < queueR;
@ -204,8 +204,8 @@ bool TransferListSortModel::lowerPositionThan(const QModelIndex &left, const QMo
}
// Sort according to TR_SEED_DATE
const QDateTime dateL = model->data(model->index(left.row(), TorrentModelItem::TR_SEED_DATE)).toDateTime();
const QDateTime dateR = model->data(model->index(right.row(), TorrentModelItem::TR_SEED_DATE)).toDateTime();
const QDateTime dateL = model->data(model->index(left.row(), TorrentModel::TR_SEED_DATE)).toDateTime();
const QDateTime dateR = model->data(model->index(right.row(), TorrentModel::TR_SEED_DATE)).toDateTime();
if (dateL.isValid() && dateR.isValid()) {
if (dateL != dateR)
return dateL < dateR;
@ -216,8 +216,8 @@ bool TransferListSortModel::lowerPositionThan(const QModelIndex &left, const QMo
return true;
// Finally, sort by hash
const QString hashL(model->torrentHash(left.row()));
const QString hashR(model->torrentHash(right.row()));
const QString hashL(model->torrentHandle(model->index(left.row()))->hash());
const QString hashR(model->torrentHandle(model->index(right.row()))->hash());
return hashL < hashR;
}

View File

@ -61,6 +61,8 @@
#include "autoexpandabledialog.h"
#include "transferlistsortmodel.h"
static QStringList extractHashes(const QList<BitTorrent::TorrentHandle *> &torrents);
TransferListWidget::TransferListWidget(QWidget *parent, MainWindow *main_window)
: QTreeView(parent)
, main_window(main_window)
@ -80,7 +82,7 @@ TransferListWidget::TransferListWidget(QWidget *parent, MainWindow *main_window)
nameFilterModel = new TransferListSortModel();
nameFilterModel->setDynamicSortFilter(true);
nameFilterModel->setSourceModel(listModel);
nameFilterModel->setFilterKeyColumn(TorrentModelItem::TR_NAME);
nameFilterModel->setFilterKeyColumn(TorrentModel::TR_NAME);
nameFilterModel->setFilterRole(Qt::DisplayRole);
nameFilterModel->setSortCaseSensitivity(Qt::CaseInsensitive);
@ -101,40 +103,40 @@ TransferListWidget::TransferListWidget(QWidget *parent, MainWindow *main_window)
// Default hidden columns
if (!column_loaded) {
setColumnHidden(TorrentModelItem::TR_ADD_DATE, true);
setColumnHidden(TorrentModelItem::TR_SEED_DATE, true);
setColumnHidden(TorrentModelItem::TR_UPLIMIT, true);
setColumnHidden(TorrentModelItem::TR_DLLIMIT, true);
setColumnHidden(TorrentModelItem::TR_TRACKER, true);
setColumnHidden(TorrentModelItem::TR_AMOUNT_DOWNLOADED, true);
setColumnHidden(TorrentModelItem::TR_AMOUNT_UPLOADED, true);
setColumnHidden(TorrentModelItem::TR_AMOUNT_DOWNLOADED_SESSION, true);
setColumnHidden(TorrentModelItem::TR_AMOUNT_UPLOADED_SESSION, true);
setColumnHidden(TorrentModelItem::TR_AMOUNT_LEFT, true);
setColumnHidden(TorrentModelItem::TR_TIME_ELAPSED, true);
setColumnHidden(TorrentModelItem::TR_SAVE_PATH, true);
setColumnHidden(TorrentModelItem::TR_COMPLETED, true);
setColumnHidden(TorrentModelItem::TR_RATIO_LIMIT, true);
setColumnHidden(TorrentModelItem::TR_SEEN_COMPLETE_DATE, true);
setColumnHidden(TorrentModelItem::TR_LAST_ACTIVITY, true);
setColumnHidden(TorrentModelItem::TR_TOTAL_SIZE, true);
setColumnHidden(TorrentModel::TR_ADD_DATE, true);
setColumnHidden(TorrentModel::TR_SEED_DATE, true);
setColumnHidden(TorrentModel::TR_UPLIMIT, true);
setColumnHidden(TorrentModel::TR_DLLIMIT, true);
setColumnHidden(TorrentModel::TR_TRACKER, true);
setColumnHidden(TorrentModel::TR_AMOUNT_DOWNLOADED, true);
setColumnHidden(TorrentModel::TR_AMOUNT_UPLOADED, true);
setColumnHidden(TorrentModel::TR_AMOUNT_DOWNLOADED_SESSION, true);
setColumnHidden(TorrentModel::TR_AMOUNT_UPLOADED_SESSION, true);
setColumnHidden(TorrentModel::TR_AMOUNT_LEFT, true);
setColumnHidden(TorrentModel::TR_TIME_ELAPSED, true);
setColumnHidden(TorrentModel::TR_SAVE_PATH, true);
setColumnHidden(TorrentModel::TR_COMPLETED, true);
setColumnHidden(TorrentModel::TR_RATIO_LIMIT, true);
setColumnHidden(TorrentModel::TR_SEEN_COMPLETE_DATE, true);
setColumnHidden(TorrentModel::TR_LAST_ACTIVITY, true);
setColumnHidden(TorrentModel::TR_TOTAL_SIZE, true);
}
//Ensure that at least one column is visible at all times
bool atLeastOne = false;
for (unsigned int i = 0; i<TorrentModelItem::NB_COLUMNS; i++) {
for (unsigned int i = 0; i<TorrentModel::NB_COLUMNS; i++) {
if (!isColumnHidden(i)) {
atLeastOne = true;
break;
}
}
if (!atLeastOne)
setColumnHidden(TorrentModelItem::TR_NAME, false);
setColumnHidden(TorrentModel::TR_NAME, false);
//When adding/removing columns between versions some may
//end up being size 0 when the new version is launched with
//a conf file from the previous version.
for (unsigned int i = 0; i<TorrentModelItem::NB_COLUMNS; i++)
for (unsigned int i = 0; i<TorrentModel::NB_COLUMNS; i++)
if (!columnWidth(i))
resizeColumnToContents(i);
@ -177,16 +179,6 @@ void TransferListWidget::previewFile(QString filePath)
openUrl(filePath);
}
int TransferListWidget::getRowFromHash(QString hash) const
{
return listModel->torrentRow(hash);
}
inline QString TransferListWidget::getHashFromRow(int row) const
{
return listModel->torrentHash(row);
}
inline QModelIndex TransferListWidget::mapToSource(const QModelIndex &index) const
{
Q_ASSERT(index.isValid());
@ -204,9 +196,7 @@ inline QModelIndex TransferListWidget::mapFromSource(const QModelIndex &index) c
void TransferListWidget::torrentDoubleClicked(const QModelIndex& index)
{
const int row = mapToSource(index).row();
const QString hash = getHashFromRow(row);
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
BitTorrent::TorrentHandle *const torrent = listModel->torrentHandle(mapToSource(index));
if (!torrent) return;
int action;
@ -227,37 +217,30 @@ void TransferListWidget::torrentDoubleClicked(const QModelIndex& index)
}
}
QStringList TransferListWidget::getSelectedTorrentsHashes() const
QList<BitTorrent::TorrentHandle *> TransferListWidget::getSelectedTorrents() const
{
QStringList hashes;
const QModelIndexList selectedIndexes = selectionModel()->selectedRows();
foreach (const QModelIndex &index, selectedIndexes)
hashes << getHashFromRow(mapToSource(index).row());
return hashes;
QList<BitTorrent::TorrentHandle *> torrents;
foreach (const QModelIndex &index, selectionModel()->selectedRows())
torrents << listModel->torrentHandle(mapToSource(index));
return torrents;
}
void TransferListWidget::setSelectedTorrentsLocation()
{
const QStringList hashes = getSelectedTorrentsHashes();
if (hashes.isEmpty()) return;
BitTorrent::TorrentHandle *const firstTorrent = BitTorrent::Session::instance()->findTorrent(hashes.first());
if (!firstTorrent) return;
const QList<BitTorrent::TorrentHandle *> torrents = getSelectedTorrents();
if (torrents.isEmpty()) return;
QString dir;
const QDir saveDir(firstTorrent->savePath());
const QDir saveDir(torrents[0]->savePath());
qDebug("Old save path is %s", qPrintable(saveDir.absolutePath()));
dir = QFileDialog::getExistingDirectory(this, tr("Choose save path"), saveDir.absolutePath(),
QFileDialog::DontConfirmOverwrite | QFileDialog::ShowDirsOnly | QFileDialog::HideNameFilterDetails);
if (!dir.isNull()) {
qDebug("New path is %s", qPrintable(dir));
foreach (const QString &hash, hashes) {
foreach (BitTorrent::TorrentHandle *const torrent, torrents) {
// Actually move storage
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
if (!torrent) continue;
torrent->move(Utils::Fs::expandPathAbs(dir));
main_window->getProperties()->updateSavePath(torrent);
}
}
}
@ -276,27 +259,20 @@ void TransferListWidget::resumeAllTorrents()
void TransferListWidget::startSelectedTorrents()
{
foreach (const QString &hash, getSelectedTorrentsHashes()) {
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
if (torrent)
torrent->resume();
}
foreach (BitTorrent::TorrentHandle *const torrent, getSelectedTorrents())
torrent->resume();
}
void TransferListWidget::forceStartSelectedTorrents()
{
foreach (const QString &hash, getSelectedTorrentsHashes()) {
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
if (torrent)
torrent->resume(true);
}
foreach (BitTorrent::TorrentHandle *const torrent, getSelectedTorrents())
torrent->resume(true);
}
void TransferListWidget::startVisibleTorrents()
{
for (int i = 0; i < nameFilterModel->rowCount(); ++i) {
const int row = mapToSource(nameFilterModel->index(i, 0)).row();
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(getHashFromRow(row));
BitTorrent::TorrentHandle *const torrent = listModel->torrentHandle(mapToSource(nameFilterModel->index(i, 0)));
if (torrent)
torrent->resume();
}
@ -304,18 +280,14 @@ void TransferListWidget::startVisibleTorrents()
void TransferListWidget::pauseSelectedTorrents()
{
foreach (const QString &hash, getSelectedTorrentsHashes()) {
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
if (torrent)
torrent->pause();
}
foreach (BitTorrent::TorrentHandle *const torrent, getSelectedTorrents())
torrent->pause();
}
void TransferListWidget::pauseVisibleTorrents()
{
for (int i = 0; i < nameFilterModel->rowCount(); ++i) {
const int row = mapToSource(nameFilterModel->index(i, 0)).row();
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(getHashFromRow(row));
BitTorrent::TorrentHandle *const torrent = listModel->torrentHandle(mapToSource(nameFilterModel->index(i, 0)));
if (torrent)
torrent->pause();
}
@ -324,117 +296,103 @@ void TransferListWidget::pauseVisibleTorrents()
void TransferListWidget::deleteSelectedTorrents()
{
if (main_window->getCurrentTabWidget() != this) return;
const QStringList& hashes = getSelectedTorrentsHashes();
if (hashes.empty()) return;
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hashes[0]);
const QList<BitTorrent::TorrentHandle *> torrents = getSelectedTorrents();
if (torrents.empty()) return;
bool delete_local_files = false;
if (Preferences::instance()->confirmTorrentDeletion() &&
!DeletionConfirmationDlg::askForDeletionConfirmation(delete_local_files, hashes.size(), torrent->name()))
!DeletionConfirmationDlg::askForDeletionConfirmation(delete_local_files, torrents.size(), torrents[0]->name()))
return;
foreach (const QString &hash, hashes)
BitTorrent::Session::instance()->deleteTorrent(hash, delete_local_files);
foreach (BitTorrent::TorrentHandle *const torrent, torrents)
BitTorrent::Session::instance()->deleteTorrent(torrent->hash(), delete_local_files);
}
void TransferListWidget::deleteVisibleTorrents()
{
if (nameFilterModel->rowCount() <= 0) return;
QStringList hashes;
for (int i = 0; i<nameFilterModel->rowCount(); ++i) {
const int row = mapToSource(nameFilterModel->index(i, 0)).row();
hashes << getHashFromRow(row);
}
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hashes[0]);
QList<BitTorrent::TorrentHandle *> torrents;
for (int i = 0; i < nameFilterModel->rowCount(); ++i)
torrents << listModel->torrentHandle(mapToSource(nameFilterModel->index(i, 0)));
bool delete_local_files = false;
if (Preferences::instance()->confirmTorrentDeletion() &&
!DeletionConfirmationDlg::askForDeletionConfirmation(delete_local_files, hashes.size(), torrent->name()))
!DeletionConfirmationDlg::askForDeletionConfirmation(delete_local_files, torrents.size(), torrents[0]->name()))
return;
foreach (const QString &hash, hashes)
BitTorrent::Session::instance()->deleteTorrent(hash, delete_local_files);
foreach (BitTorrent::TorrentHandle *const torrent, torrents)
BitTorrent::Session::instance()->deleteTorrent(torrent->hash(), delete_local_files);
}
void TransferListWidget::increasePrioSelectedTorrents()
{
qDebug() << Q_FUNC_INFO;
if (main_window->getCurrentTabWidget() == this)
BitTorrent::Session::instance()->increaseTorrentsPriority(getSelectedTorrentsHashes());
BitTorrent::Session::instance()->increaseTorrentsPriority(extractHashes(getSelectedTorrents()));
}
void TransferListWidget::decreasePrioSelectedTorrents()
{
qDebug() << Q_FUNC_INFO;
if (main_window->getCurrentTabWidget() == this)
BitTorrent::Session::instance()->decreaseTorrentsPriority(getSelectedTorrentsHashes());
BitTorrent::Session::instance()->decreaseTorrentsPriority(extractHashes(getSelectedTorrents()));
}
void TransferListWidget::topPrioSelectedTorrents()
{
if (main_window->getCurrentTabWidget() == this)
BitTorrent::Session::instance()->topTorrentsPriority(getSelectedTorrentsHashes());
BitTorrent::Session::instance()->topTorrentsPriority(extractHashes(getSelectedTorrents()));
}
void TransferListWidget::bottomPrioSelectedTorrents()
{
if (main_window->getCurrentTabWidget() == this)
BitTorrent::Session::instance()->bottomTorrentsPriority(getSelectedTorrentsHashes());
BitTorrent::Session::instance()->bottomTorrentsPriority(extractHashes(getSelectedTorrents()));
}
void TransferListWidget::copySelectedMagnetURIs() const
{
QStringList magnet_uris;
const QStringList hashes = getSelectedTorrentsHashes();
foreach (const QString &hash, hashes) {
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
if (torrent)
magnet_uris << torrent->toMagnetUri();
}
foreach (BitTorrent::TorrentHandle *const torrent, getSelectedTorrents())
magnet_uris << torrent->toMagnetUri();
qApp->clipboard()->setText(magnet_uris.join("\n"));
}
void TransferListWidget::copySelectedNames() const
{
QStringList torrent_names;
const QStringList hashes = getSelectedTorrentsHashes();
foreach (const QString &hash, hashes) {
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
if (torrent)
torrent_names << torrent->name();
}
foreach (BitTorrent::TorrentHandle *const torrent, getSelectedTorrents())
torrent_names << torrent->name();
qApp->clipboard()->setText(torrent_names.join("\n"));
}
void TransferListWidget::hidePriorityColumn(bool hide)
{
qDebug("hidePriorityColumn(%d)", hide);
setColumnHidden(TorrentModelItem::TR_PRIORITY, hide);
if (!hide && !columnWidth(TorrentModelItem::TR_PRIORITY))
resizeColumnToContents(TorrentModelItem::TR_PRIORITY);
setColumnHidden(TorrentModel::TR_PRIORITY, hide);
if (!hide && !columnWidth(TorrentModel::TR_PRIORITY))
resizeColumnToContents(TorrentModel::TR_PRIORITY);
}
void TransferListWidget::openSelectedTorrentsFolder() const
{
QSet<QString> pathsList;
const QStringList hashes = getSelectedTorrentsHashes();
foreach (const QString &hash, hashes) {
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
if (torrent) {
QString rootFolder = torrent->rootPath();
qDebug("Opening path at %s", qPrintable(rootFolder));
if (!pathsList.contains(rootFolder)) {
pathsList.insert(rootFolder);
openUrl(rootFolder);
}
foreach (BitTorrent::TorrentHandle *const torrent, getSelectedTorrents()) {
QString rootFolder = torrent->rootPath();
qDebug("Opening path at %s", qPrintable(rootFolder));
if (!pathsList.contains(rootFolder)) {
pathsList.insert(rootFolder);
openUrl(rootFolder);
}
}
}
void TransferListWidget::previewSelectedTorrents()
{
const QStringList hashes = getSelectedTorrentsHashes();
foreach (const QString &hash, hashes) {
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
if (torrent && torrent->hasMetadata())
foreach (BitTorrent::TorrentHandle *const torrent, getSelectedTorrents()) {
if (torrent->hasMetadata())
new PreviewSelect(this, torrent);
}
}
@ -444,19 +402,17 @@ void TransferListWidget::setDlLimitSelectedTorrents()
QList<BitTorrent::TorrentHandle *> selected_torrents;
bool first = true;
bool all_same_limit = true;
const QStringList hashes = getSelectedTorrentsHashes();
foreach (const QString &hash, hashes) {
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
if (torrent && !torrent->isSeed()) {
foreach (BitTorrent::TorrentHandle *const torrent, getSelectedTorrents()) {
if (!torrent->isSeed()) {
selected_torrents << torrent;
// Determine current limit for selected torrents
if (first)
first = false;
else
if (all_same_limit && (torrent->downloadLimit() != selected_torrents.first()->downloadLimit()))
all_same_limit = false;
else if (all_same_limit && (torrent->downloadLimit() != selected_torrents.first()->downloadLimit()))
all_same_limit = false;
}
}
if (selected_torrents.empty()) return;
bool ok = false;
@ -477,19 +433,15 @@ void TransferListWidget::setUpLimitSelectedTorrents()
QList<BitTorrent::TorrentHandle *> selected_torrents;
bool first = true;
bool all_same_limit = true;
const QStringList hashes = getSelectedTorrentsHashes();
foreach (const QString &hash, hashes) {
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
if (torrent) {
selected_torrents << torrent;
// Determine current limit for selected torrents
if (first)
first = false;
else
if (all_same_limit && (torrent->uploadLimit() != selected_torrents.first()->uploadLimit()))
all_same_limit = false;
}
foreach (BitTorrent::TorrentHandle *const torrent, getSelectedTorrents()) {
selected_torrents << torrent;
// Determine current limit for selected torrents
if (first)
first = false;
else if (all_same_limit && (torrent->uploadLimit() != selected_torrents.first()->uploadLimit()))
all_same_limit = false;
}
if (selected_torrents.empty()) return;
bool ok = false;
@ -507,26 +459,20 @@ void TransferListWidget::setUpLimitSelectedTorrents()
void TransferListWidget::setMaxRatioSelectedTorrents()
{
const QStringList hashes = getSelectedTorrentsHashes();
if (hashes.isEmpty())
return;
const QList<BitTorrent::TorrentHandle *> torrents = getSelectedTorrents();
if (torrents.isEmpty()) return;
bool useGlobalValue = true;
qreal currentMaxRatio = BitTorrent::Session::instance()->globalMaxRatio();;
if (hashes.count() == 1) {
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hashes.first());
if (torrent)
currentMaxRatio = torrent->maxRatio(&useGlobalValue);
}
if (torrents.count() == 1)
currentMaxRatio = torrents[0]->maxRatio(&useGlobalValue);
UpDownRatioDlg dlg(useGlobalValue, currentMaxRatio, BitTorrent::TorrentHandle::MAX_RATIO, this);
if (dlg.exec() != QDialog::Accepted) return;
foreach (const QString &hash, hashes) {
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
if (torrent) {
qreal ratio = (dlg.useDefault() ? BitTorrent::TorrentHandle::USE_GLOBAL_RATIO : dlg.ratio());
torrent->setRatioLimit(ratio);
}
foreach (BitTorrent::TorrentHandle *const torrent, torrents) {
qreal ratio = (dlg.useDefault() ? BitTorrent::TorrentHandle::USE_GLOBAL_RATIO : dlg.ratio());
torrent->setRatioLimit(ratio);
}
}
@ -535,12 +481,8 @@ void TransferListWidget::recheckSelectedTorrents()
QMessageBox::StandardButton ret = QMessageBox::question(this, tr("Recheck confirmation"), tr("Are you sure you want to recheck the selected torrent(s)?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
if (ret != QMessageBox::Yes) return;
const QStringList hashes = getSelectedTorrentsHashes();
foreach (const QString &hash, hashes) {
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
if (torrent)
torrent->forceRecheck();
}
foreach (BitTorrent::TorrentHandle *const torrent, getSelectedTorrents())
torrent->forceRecheck();
}
// hide/show columns menu
@ -550,7 +492,7 @@ void TransferListWidget::displayDLHoSMenu(const QPoint&)
hideshowColumn.setTitle(tr("Column visibility"));
QList<QAction*> actions;
for (int i = 0; i < listModel->columnCount(); ++i) {
if (!BitTorrent::Session::instance()->isQueueingEnabled() && i == TorrentModelItem::TR_PRIORITY) {
if (!BitTorrent::Session::instance()->isQueueingEnabled() && i == TorrentModel::TR_PRIORITY) {
actions.append(0);
continue;
}
@ -560,7 +502,7 @@ void TransferListWidget::displayDLHoSMenu(const QPoint&)
actions.append(myAct);
}
int visibleCols = 0;
for (unsigned int i = 0; i<TorrentModelItem::NB_COLUMNS; i++) {
for (unsigned int i = 0; i<TorrentModel::NB_COLUMNS; i++) {
if (!isColumnHidden(i))
visibleCols++;
@ -586,32 +528,22 @@ void TransferListWidget::displayDLHoSMenu(const QPoint&)
void TransferListWidget::toggleSelectedTorrentsSuperSeeding() const
{
const QStringList hashes = getSelectedTorrentsHashes();
foreach (const QString &hash, hashes) {
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
if (torrent && torrent->hasMetadata())
foreach (BitTorrent::TorrentHandle *const torrent, getSelectedTorrents()) {
if (torrent->hasMetadata())
torrent->setSuperSeeding(!torrent->superSeeding());
}
}
void TransferListWidget::toggleSelectedTorrentsSequentialDownload() const
{
const QStringList hashes = getSelectedTorrentsHashes();
foreach (const QString &hash, hashes) {
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
if (torrent)
torrent->toggleSequentialDownload();
}
foreach (BitTorrent::TorrentHandle *const torrent, getSelectedTorrents())
torrent->toggleSequentialDownload();
}
void TransferListWidget::toggleSelectedFirstLastPiecePrio() const
{
QStringList hashes = getSelectedTorrentsHashes();
foreach (const QString &hash, hashes) {
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
if (torrent)
torrent->setFirstLastPiecePriority(!torrent->hasFirstLastPiecePriority());
}
foreach (BitTorrent::TorrentHandle *const torrent, getSelectedTorrents())
torrent->setFirstLastPiecePriority(!torrent->hasFirstLastPiecePriority());
}
void TransferListWidget::askNewLabelForSelection()
@ -649,9 +581,9 @@ void TransferListWidget::renameSelectedTorrent()
const QModelIndexList selectedIndexes = selectionModel()->selectedRows();
if (selectedIndexes.size() != 1) return;
if (!selectedIndexes.first().isValid()) return;
QModelIndex mi = listModel->index(mapToSource(selectedIndexes.first()).row(), TorrentModelItem::TR_NAME);
const QString hash = getHashFromRow(mi.row());
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
const QModelIndex mi = listModel->index(mapToSource(selectedIndexes.first()).row(), TorrentModel::TR_NAME);
BitTorrent::TorrentHandle *const torrent = listModel->torrentHandle(mi);
if (!torrent) return;
// Ask for a new Name
@ -666,19 +598,15 @@ void TransferListWidget::renameSelectedTorrent()
void TransferListWidget::setSelectionLabel(QString label)
{
const QStringList& hashes = getSelectedTorrentsHashes();
foreach (const QString &hash, hashes) {
Q_ASSERT(!hash.isEmpty());
const int row = getRowFromHash(hash);
listModel->setData(listModel->index(row, TorrentModelItem::TR_LABEL), QVariant(label), Qt::DisplayRole);
}
foreach (const QModelIndex &index, selectionModel()->selectedRows())
listModel->setData(listModel->index(mapToSource(index).row(), TorrentModel::TR_LABEL), label, Qt::DisplayRole);
}
void TransferListWidget::removeLabelFromRows(QString label)
{
for (int i = 0; i < listModel->rowCount(); ++i) {
if (listModel->data(listModel->index(i, TorrentModelItem::TR_LABEL)) == label) {
listModel->setData(listModel->index(i, TorrentModelItem::TR_LABEL), "", Qt::DisplayRole);
if (listModel->data(listModel->index(i, TorrentModel::TR_LABEL)) == label) {
listModel->setData(listModel->index(i, TorrentModel::TR_LABEL), "", Qt::DisplayRole);
}
}
}
@ -750,9 +678,8 @@ void TransferListWidget::displayListMenu(const QPoint&)
qDebug("Displaying menu");
foreach (const QModelIndex &index, selectedIndexes) {
// Get the file name
QString hash = getHashFromRow(mapToSource(index).row());
// Get handle and pause the torrent
torrent = BitTorrent::Session::instance()->findTorrent(hash);
torrent = listModel->torrentHandle(mapToSource(index));
if (!torrent) continue;
if (torrent->hasMetadata())
@ -907,8 +834,7 @@ void TransferListWidget::currentChanged(const QModelIndex& current, const QModel
qDebug("CURRENT CHANGED");
BitTorrent::TorrentHandle *torrent = 0;
if (current.isValid()) {
const int row = mapToSource(current).row();
torrent = BitTorrent::Session::instance()->findTorrent(getHashFromRow(row));
torrent = listModel->torrentHandle(mapToSource(current));
// Scroll Fix
scrollTo(current);
}
@ -946,8 +872,8 @@ void TransferListWidget::applyStatusFilter(int f)
nameFilterModel->setStatusFilter(static_cast<TorrentFilter::Type>(f));
// Select first item if nothing is selected
if (selectionModel()->selectedRows(0).empty() && nameFilterModel->rowCount() > 0) {
qDebug("Nothing is selected, selecting first row: %s", qPrintable(nameFilterModel->index(0, TorrentModelItem::TR_NAME).data().toString()));
selectionModel()->setCurrentIndex(nameFilterModel->index(0, TorrentModelItem::TR_NAME), QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
qDebug("Nothing is selected, selecting first row: %s", qPrintable(nameFilterModel->index(0, TorrentModel::TR_NAME).data().toString()));
selectionModel()->setCurrentIndex(nameFilterModel->index(0, TorrentModel::TR_NAME), QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
}
}
@ -964,3 +890,11 @@ bool TransferListWidget::loadSettings()
return ok;
}
QStringList extractHashes(const QList<BitTorrent::TorrentHandle *> &torrents)
{
QStringList hashes;
foreach (BitTorrent::TorrentHandle *const torrent, torrents)
hashes << torrent->hash();
return hashes;
}

View File

@ -95,12 +95,10 @@ public slots:
void renameSelectedTorrent();
protected:
int getRowFromHash(QString hash) const;
QString getHashFromRow(int row) const;
QModelIndex mapToSource(const QModelIndex &index) const;
QModelIndex mapFromSource(const QModelIndex &index) const;
bool loadSettings();
QStringList getSelectedTorrentsHashes() const;
QList<BitTorrent::TorrentHandle *> getSelectedTorrents() const;
protected slots:
void torrentDoubleClicked(const QModelIndex& index);